Skip to content

feat: sprout-cli — agent-first CLI with full MCP parity (48 commands)#158

Merged
tlongwell-block merged 3 commits intomainfrom
cli-rewrite-v1
Mar 22, 2026
Merged

feat: sprout-cli — agent-first CLI with full MCP parity (48 commands)#158
tlongwell-block merged 3 commits intomainfrom
cli-rewrite-v1

Conversation

@tlongwell-block
Copy link
Collaborator

@tlongwell-block tlongwell-block commented Mar 22, 2026

Summary

New sprout-cli crate — an agent-first, JSON-only CLI for the Sprout relay. 48 commands covering all 42 MCP tools plus token management, auth bootstrap, and additional REST-only operations. Also adds two new REST endpoints to the relay.

CLI (crates/sprout-cli)

Design: Pure JSON on stdout, structured JSON errors on stderr, meaningful exit codes (0/1/2/3/4). Designed for agent consumption — no tables, no colors, no rendering dependencies.

Auth: Three-tier resolution:

  1. SPROUT_API_TOKEN — Bearer token (fastest, no extra HTTP call)
  2. SPROUT_PRIVATE_KEY — auto-mints a 1-day token via NIP-98 at startup
  3. SPROUT_PUBKEY — X-Pubkey header (dev mode, SPROUT_REQUIRE_AUTH_TOKEN=false)

Architecture:

sprout <command> [flags]
    │
    ├─ main.rs ──▶ commands/*.rs ──▶ client.rs ──▶ Sprout Relay REST API
    │  (clap)       (handlers)       (reqwest)
    │
    ├─ validate.rs   (UUID, hex, content size, percent-encode)
    └─ error.rs      (CliError → JSON stderr + exit code)

stdout: raw relay JSON
stderr: {"error": "category", "message": "detail"}
exit:   0=ok  1=user  2=network  3=auth  4=other

Stats: ~2900 lines across 13 source files. 38 unit tests. Clippy clean (workspace -D warnings).

Relay (2 new REST endpoints)

  • PUT /api/messages/{event_id} — edit message (kind:40003)
  • POST /api/messages/{event_id}/votes — vote on forum post (kind:45002)

These were previously WebSocket-only in the MCP server. Adding REST endpoints makes the relay API feature-complete and lets the CLI stay pure REST.

Commands (48 total)

Full command list

Messages: send-message, send-diff-message, edit-message, delete-message, get-messages, get-thread, search

Channels: list-channels, get-channel, create-channel, update-channel, set-channel-topic, set-channel-purpose, join-channel, leave-channel, archive-channel, unarchive-channel, delete-channel, list-channel-members, add-channel-member, remove-channel-member, get-canvas, set-canvas

Reactions: add-reaction, remove-reaction, get-reactions

DMs: list-dms, open-dm, add-dm-member

Users: get-users, set-profile, get-presence, set-presence, set-channel-add-policy

Workflows: list-workflows, create-workflow, update-workflow, delete-workflow, trigger-workflow, get-workflow-runs, get-workflow, approve-step

Feed: get-feed

Forum: vote-on-post

Auth & Tokens: auth, list-tokens, delete-token, delete-all-tokens

Testing

All 48 commands verified against a local relay. See crates/sprout-cli/TESTING.md for the full runbook.

cargo test -p sprout-cli    # 38 tests
cargo clippy -p sprout-cli  # zero warnings

Complete rewrite of sprout-cli as an agent-first, JSON-only CLI covering
all 42 MCP tools plus 6 CLI-only commands (token management, auth,
get-workflow, delete-channel).

## CLI (new crate: sprout-cli)

- 48 flat commands matching MCP tool names (sprout send-message, etc.)
- Pure JSON stdout, structured JSON errors on stderr
- Exit codes: 0=ok, 1=user, 2=network, 3=auth, 4=other
- Three-tier auth: SPROUT_API_TOKEN > SPROUT_PRIVATE_KEY (auto-mint) > SPROUT_PUBKEY
- Input validation before every network call (UUID, hex64, content size, enums)
- Single request() method — no HTTP method duplication
- 38 unit tests, clippy clean

## Relay (2 new REST endpoints)

- PUT /api/messages/{event_id} — edit message (kind:40003)
- POST /api/messages/{event_id}/votes — vote on forum post (kind:45002)

These were previously WebSocket-only. Adding REST endpoints makes the
relay API feature-complete and enables the CLI to cover all 42 MCP tools
without WebSocket/Nostr signing complexity.

## Why a rewrite

The previous CLI scored 3/10 in crossfire review (Opus + Codex):
- Did not compile (5 errors)
- 13 commands vs 42 MCP tools
- Token minted on every invocation
- No input validation
- Architecture doc described a different app

The new CLI was crossfired to 9-10/10 (Opus 9/10, Codex 10/10).
- Add crates/sprout-cli/TESTING.md: live testing runbook covering all 48
  commands, 3 auth modes, error paths, and cleanup. Crossfired to 8.5/10.
- Fix NIP-98 x-forwarded-proto header in auto_mint_token and cmd_auth.
  The relay defaults x-forwarded-proto to 'https', causing URL mismatch
  on localhost (http://). Both functions now send the correct scheme header.
- Fix workflow YAML examples in TESTING.md to use correct trigger format
  (tagged enum with 'on:' field, not bare string).
- Fix open-dm field extraction (relay returns 'channel_id' not 'id').
@tlongwell-block tlongwell-block merged commit 4c9b8aa into main Mar 22, 2026
8 checks passed
@tlongwell-block tlongwell-block deleted the cli-rewrite-v1 branch March 22, 2026 01:23
tlongwell-block added a commit that referenced this pull request Mar 22, 2026
* origin/main:
  feat: sprout-cli — agent-first CLI with full MCP parity (48 commands) (#158)
  fix(desktop): resolve composer cursor drift on multi-line input (#153)

# Conflicts:
#	crates/sprout-relay/src/router.rs
tlongwell-block added a commit that referenced this pull request Mar 22, 2026
* origin/main:
  feat: sprout-cli — agent-first CLI with full MCP parity (48 commands) (#158)
  fix(desktop): resolve composer cursor drift on multi-line input (#153)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant