Skip to main content
← Back to list
01Issue
FeatureTriagedSwamp CLIPublic
Assigneesskunk-ape

Relationships

↔ sibling #1553

#1376 CLI: swamp invite <email> to drive the platform-invite API

Opened by keeb · 7/24/2026

Problem

swamp-club now exposes an authenticated endpoint to invite someone to the platform: POST /api/v1/invites (session cookie or personal API key). An operative who invites someone whose recruit later reaches Tier 5 earns 200,000 points and the First Rule badge. Today the only way to call it is a hand-rolled curl with a bearer token — there's no first-class CLI affordance, so the feature is effectively invisible to CLI-first operatives.

The CLI already holds the operative's swamp-club auth (OAuth device session / personal API key), so it's positioned to drive this endpoint directly.

Proposed solution

Add a command — swamp invite <email> — that POSTs to /api/v1/invites using the operative's existing credential and reports the result.

Endpoint contract (already live in swamp-club, routes/api/v1/invites/index.ts):

  • POST {origin}/api/v1/invites, body {"email": "<addr>"}
  • Auth: Authorization: Bearer swamp_* / x-api-key (the credential the CLI already presents to swamp-club)
  • Responses:
    • 200 {"ok": true} — uniform for created / already-invited no-op / stale-resend / already-an-operative. This is deliberate anti-enumeration: the endpoint never reveals whether the address is new, already invited, or already a member. The CLI must not claim to know which happened.
    • 400 {"error": "..."} — malformed email / missing body
    • 429 {"error": "..."} — the inviter's pending-invite cap (20) is reached
    • 401 {"error": "Unauthorized"} — not authenticated → the CLI should nudge swamp auth login

UX / messaging:

  • On 200, print something anti-enumeration-safe, e.g. Invited <email> to the swamp. — never "new user created" vs "already a member".
  • Because the reward is deferred (200k + First Rule badge land only once the recruit accepts and reaches Tier 5), the CLI should NOT imply an immediate reward. A one-line hint is fine: "You'll earn the First Rule badge if they reach Tier 5."
  • Surface 429 as a friendly cap message and 401 as a login prompt.

Exit codes: 0 on 200; non-zero on 4xx, with the server's error string printed.

Alternatives considered

  • Leave it to manual curl — works, but undiscoverable and easy to get the auth header wrong.
  • Web-only — the invite form/flow lives on swamp-club; but CLI-first operatives (the ones most likely to farm the reward legitimately) never see it.

Notes

  • Code for the endpoint is in swamp-club (routes/api/v1/invites/index.ts, lib/app/invite-to-platform.ts); this issue is only about the swamp CLI client (~/git/swamp).
  • The origin should follow whatever base URL the CLI already uses for swamp-club API calls (e.g. whoami), not a new hardcoded host.
02Bog Flow
✓OPEN◉TRIAGED○IN PROGRESS○SHIPPED+ 2 MORETRIAGE+ 1 MORECLASSIFICATION

Triaged

9/16/2026, 2:20:48 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
skunk-ape assigned skunk-ape9/16/2026, 2:18:56 PM
skunk-ape linked sibling of #15539/16/2026, 12:39:49 AM
Editable. Press Enter to edit.

skunk-ape commented 9/16/2026, 4:20:53 PM

Direction note, not a closure: this issue stays open and valid. A second, complementary shape is now specced separately — a long-lived reusable referral link, one per operative, shared as a URL rather than sent to an address: #2179 (swamp-club API + payout) and #2180 (swamp auth invite-link in the CLI).

The two differ deliberately. This one is per-address, single-use, gated on the recruit reaching Tier 5, and pays 200,000 plus the First Rule badge. The referral link is reusable by anyone, gated on the referred account verifying its email, and pays a smaller amount. Neither supersedes the other, and nothing here changes.

Triage findings recorded against this issue still stand: the endpoint contract matches the description, a personal swamp_* key already authenticates the route via resolveRequestAuth, and no swamp-club change is needed — the work is entirely in the CLI repo.

skunk-ape commented 9/16/2026, 4:32:57 PM

Command-shape decision, affecting this issue: swamp invite becomes a command group, shared with #2180.

swamp invite                 -> group help
swamp invite <address>       -> per-address invite   (this issue)
swamp invite link            -> referral link        (#2180)
swamp invite rule1           -> alias for link

The bare-address form specced here is unchanged — no email noun is being forced onto it. The group takes an optional [email] positional whose action falls through to groupCommandAction (src/cli/group_action.ts) when absent, so bare swamp invite prints help instead of erroring on a missing argument. Cliffy resolves subcommand names before positional arguments, so link and rule1 cannot be swallowed as addresses.

This makes invite the one group in the CLI carrying both a positional argument and subcommands — src/cli/commands/issue.ts is pure-group. Deliberate: swamp invite email <address> is ceremony on the commonest path.

Whichever of the two issues lands first creates src/cli/commands/invite.ts and registers the group; the second adds its half to the existing group. Worth coordinating so neither scaffolds it twice.

Sign in to post a ripple.