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.
cnctl is built from the ground up to be fully operable by LLM agents (like Claude Code, Cursor, or Gemini). Using the --agent global flag enforces machine-readable output and drastically reduces token context window waste.
When --agent is passed, cnctl automatically:
- Formats all output as compact (single-line) JSON rather than pretty-printed text or tables.
- Bypasses interactive prompts, menus, and UI spinners.
- Limits list outputs to a maximum of 50 items and wraps them in a metadata envelope (
{"data": [...], "_meta": {"truncated": true}}). - Returns structured mutation confirmations (
{"ok": true, "id": "..."}). - Returns categorized error codes and actionable hints instead of raw human-readable errors.
# Globally enable token-optimized output across any command
cnctl --agent admin proposals list
# Extreme token compression: Only output essential fields (id, name, status)
cnctl --agent admin sponsors list --compact
cnctl --agent admin speakers list --compact
cnctl --agent admin proposals list --compact
# Agent schema and capabilities discovery
cnctl agent-info --json
cnctl help-jsonNote: For maximum efficiency, we recommend agents use the RTK (Rust Token Killer) wrapper when invoking
cnctlif it's available in your environment (rtk cnctl ...).
- 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