Skip to content

CloudNativeBergen/cnctl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

28 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

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.

πŸ› οΈ 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