Skip to content

CloudNativeBergen/cnctl

Repository files navigation

cnctl

CI Release License: MIT

The organizer CLI for Cloud Native Days Norway. Review talk proposals, manage the sponsor pipeline, and run your conference — all from the terminal.

✨ Features

  • 🔐 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, $EDITOR integration, and variable substitution
  • 🎨 Color-coded output — status badges at a glance (green = confirmed, yellow = submitted, red = rejected, …)
  • 📊 JSON output — pipe to jq or feed into scripts with --json
  • 🖥️ Cross-platform — prebuilt binaries for macOS, Linux, and Windows

📦 Installation

Homebrew (macOS and Linux)

brew tap CloudNativeBergen/tap
brew install cnctl

Download a prebuilt binary

Grab 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-missing

Build provenance (requires GitHub CLI):

gh attestation verify cnctl-aarch64-apple-darwin.tar.gz --repo CloudNativeBergen/cnctl

Every release is signed with Sigstore via GitHub Artifact Attestations so you can verify exactly which commit and workflow produced your binary.

Build from source

Requires Rust 1.85+.

git clone https://github.com/CloudNativeBergen/cnctl.git
cd cnctl
cargo install --path .

🚀 Quick start

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 credentials

📖 Usage

Authentication

Log in via your browser using GitHub or LinkedIn OAuth:

cnctl login

This 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 status

Log out and remove stored credentials:

cnctl logout

Proposals

Interactive 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 list

Filter 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 --asc

Available 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> --json

Reviews

Interactive 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.

Sponsors

View the full sponsor pipeline with status, tier, and contract info:

cnctl admin sponsors list

Filter 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 --json

Dive into a specific sponsor for contacts, billing details, and notes:

cnctl admin sponsors get <sponsor-id>

Sponsor Emails

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-en

Send 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 --json

Edit 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.

🤖 Agent Usage

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.

Token-Optimized Output

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.

Key Commands for Agents

# 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-json

Note: For maximum efficiency, we recommend agents use the RTK (Rust Token Killer) wrapper when invoking cnctl if it's available in your environment (rtk cnctl ...).

🛠️ Development

Prerequisites

Build and test

# 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 test

Project structure

src/
  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

🤝 Contributing

Contributions are welcome! See CONTRIBUTING.md for guidelines.

📄 License

MIT © Hans Kristian Flaatten

About

CLI for Cloud Native Days Norway conference management

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages