The organizer CLI for Cloud Native Days Norway. Review talk proposals, manage the sponsor pipeline, and run your conference β all from the terminal.
- π Browser-based login β authenticate with GitHub or LinkedIn OAuth, no API keys to manage
- π Interactive proposal review β fuzzy-search, filter by status/format, sort by rating, and scroll through details with vim-style keybindings
- π° Sponsor pipeline β track sponsors from prospect to paid, with contacts, tiers, and contract status
- π§ Sponsor emails β send templated emails to sponsors with interactive template picker,
$EDITORintegration, and variable substitution - π¨ Color-coded output β status badges at a glance (green = confirmed, yellow = submitted, red = rejected, β¦)
- π JSON output β pipe to
jqor feed into scripts with--json - π₯οΈ Cross-platform β prebuilt binaries for macOS, Linux, and Windows
brew tap CloudNativeBergen/tap
brew install cnctlGrab the latest build for your platform from GitHub Releases:
# macOS (Apple Silicon)
curl -LO https://github.com/CloudNativeBergen/cnctl/releases/latest/download/cnctl-aarch64-apple-darwin.tar.gz
tar xzf cnctl-aarch64-apple-darwin.tar.gz
sudo mv cnctl /usr/local/bin/
# macOS (Intel)
curl -LO https://github.com/CloudNativeBergen/cnctl/releases/latest/download/cnctl-x86_64-apple-darwin.tar.gz
tar xzf cnctl-x86_64-apple-darwin.tar.gz
sudo mv cnctl /usr/local/bin/
# Linux (x86_64)
curl -LO https://github.com/CloudNativeBergen/cnctl/releases/latest/download/cnctl-x86_64-unknown-linux-gnu.tar.gz
tar xzf cnctl-x86_64-unknown-linux-gnu.tar.gz
sudo mv cnctl /usr/local/bin/
# Linux (arm64)
curl -LO https://github.com/CloudNativeBergen/cnctl/releases/latest/download/cnctl-aarch64-unknown-linux-gnu.tar.gz
tar xzf cnctl-aarch64-unknown-linux-gnu.tar.gz
sudo mv cnctl /usr/local/bin/π Verify your download
Checksum:
curl -LO https://github.com/CloudNativeBergen/cnctl/releases/latest/download/SHA256SUMS
sha256sum -c SHA256SUMS --ignore-missingBuild provenance (requires GitHub CLI):
gh attestation verify cnctl-aarch64-apple-darwin.tar.gz --repo CloudNativeBergen/cnctlEvery release is signed with Sigstore via GitHub Artifact Attestations so you can verify exactly which commit and workflow produced your binary.
Requires Rust 1.85+.
git clone https://github.com/CloudNativeBergen/cnctl.git
cd cnctl
cargo install --path .cnctl login # opens browser β pick your conference
cnctl status # verify session
cnctl admin proposals list # interactive fuzzy-search
cnctl admin proposals list --status accepted,confirmed --sort rating
cnctl admin proposals list --json | jq '.[] | .title'
cnctl admin proposals review <id> # interactive review prompts
cnctl admin proposals review <id> --content 4 --relevance 3 --speaker 5 --comment "Great talk"
cnctl admin sponsors list
cnctl admin sponsors list --status negotiating,closedWon
cnctl admin sponsors get <id>
cnctl admin sponsors email <id> # interactive template picker
cnctl admin sponsors email <id> --template <slug> # use specific template
cnctl admin sponsors email <id> --message "Hello" # send direct message
cnctl admin sponsors email <id> --dry-run # preview without sending
cnctl logout # clear credentialsLog in via your browser using GitHub or LinkedIn OAuth:
cnctl loginThis opens a browser window, authenticates you, and lets you select which conference to work with. Your session token is stored locally at ~/.config/cnctl/config.toml.
You must be registered as a conference organizer to use the admin commands.
Check your current session:
cnctl statusLog out and remove stored credentials:
cnctl logoutInteractive mode (default) β launches a fuzzy-search menu where you can type to filter, use arrow keys to navigate, and press enter to view details:
cnctl admin proposals listFilter and sort directly from the command line:
# Only accepted talks, sorted by review rating (highest first)
cnctl admin proposals list --status accepted --sort rating
# Lightning talks that are still pending review
cnctl admin proposals list --status submitted --format lightning_10
# Sort alphabetically by speaker name, ascending
cnctl admin proposals list --sort speaker --ascAvailable filters:
| Flag | Values |
|---|---|
--status |
submitted, accepted, confirmed, waitlisted, rejected, withdrawn, draft, deleted |
--format |
lightning_10, presentation_20, presentation_25, presentation_40, presentation_45, workshop_120, workshop_240 |
--sort |
created, title, speaker, rating, reviews, status |
View a single proposal with full details β speakers, topics, description, outline, and review scores:
cnctl admin proposals get <proposal-id>In interactive mode, selecting a proposal opens a scrollable detail view:
| Key | Action |
|---|---|
β / k |
Scroll up |
β / j |
Scroll down |
Ctrl+U / PgUp |
Half-page up |
Ctrl+D / PgDn |
Half-page down |
β / h |
Previous proposal |
β / l |
Next proposal |
r |
Start a review |
q / Esc |
Back to list |
JSON output for scripting and automation:
cnctl admin proposals list --json
cnctl admin proposals get <proposal-id> --jsonInteractive review β shows the proposal, then prompts for scores (1β5) and a comment:
cnctl admin proposals review <proposal-id>Non-interactive β provide all scores and comment as flags:
cnctl admin proposals review <proposal-id> \
--content 4 --relevance 3 --speaker 5 \
--comment "Clear structure, relevant topic, confident speaker"If the proposal has already been reviewed by you, your previous scores and comment are pre-filled as defaults. You can press Esc at any prompt to cancel, and a confirmation summary is shown before submitting.
View the full sponsor pipeline with status, tier, and contract info:
cnctl admin sponsors listFilter by status:
cnctl admin sponsors list --status prospect,negotiating
cnctl admin sponsors list --status closedWon| Flag | Values |
|---|---|
--status |
prospect, contacted, negotiating, closed-won, closed-lost |
JSON output:
cnctl admin sponsors list --jsonDive into a specific sponsor for contacts, billing details, and notes:
cnctl admin sponsors get <sponsor-id>Send templated emails to sponsor contacts directly from the terminal. Templates are managed in the web UI and delivered with full conference branding via Resend.
Interactive mode (default) β shows a fuzzy-search template picker, pre-sorted by relevance for the sponsor's status and language:
cnctl admin sponsors email <sponsor-id>Select a specific template:
cnctl admin sponsors email <sponsor-id> --template cold-outreach-enSend a direct message (skip templates):
cnctl admin sponsors email <sponsor-id> --message "Quick follow-up on our call."Preview without sending:
cnctl admin sponsors email <sponsor-id> --dry-run
cnctl admin sponsors email <sponsor-id> --dry-run --jsonEdit in your editor before sending:
cnctl admin sponsors email <sponsor-id> --edit| Flag | Description |
|---|---|
--template |
Template slug (skip interactive picker) |
--subject |
Override the email subject |
--message |
Use this body directly (skip template selection) |
--edit |
Open $EDITOR to edit the message before sending |
--dry-run |
Preview the email without sending |
--json |
Output as JSON |
Template variables like {{{SPONSOR_NAME}}}, {{{CONTACT_NAMES}}}, and {{{CONFERENCE_TITLE}}} are automatically resolved from the sponsor and conference context.
- Rust 1.85+
- mise (optional, for task runner)
# Using mise (recommended)
mise run check # clippy + fmt-check + test (parallel)
mise run build # release build
# Using cargo directly
cargo clippy --all-targets -- -D warnings
cargo fmt -- --check
cargo testsrc/
main.rs β CLI entry point and argument parsing (clap)
lib.rs β public module exports
auth.rs β browser-based OAuth flow with local callback server
client.rs β tRPC HTTP client
config.rs β TOML config read/write (~/.config/cnctl/)
template.rs β {{{VAR}}} template variable substitution
commands/ β command orchestration
proposals/ β proposal list, detail, review, filters, interactive mode
sponsors/ β sponsor list, detail, email sending with template picker
display/ β terminal output formatting (colors, layout, truncation)
types/ β API response types with typed enums (serde)
ui/ β reusable TUI components (pager, spinner, terminal helpers)
tests/
e2e.rs β end-to-end tests with wiremock
Contributions are welcome! See CONTRIBUTING.md for guidelines.
MIT Β© Hans Kristian Flaatten