Relationships
#4031 swamp inbox lists your Swamp Club inbox messages newest first, unread only by default, by date, kind and title, with no reading and no read-state changes yet
Opened by stack72 · 10/27/2026
Summary
Add swamp inbox, which lists the signed-in user's Swamp Club inbox messages: newest first, unread only by default. It shows each message's date, kind and title, and nothing else. Reading is not part of this. The command shows no message body, has no swamp inbox read, and never marks anything read. Its job for now is to show that the inbox exists and what is in it.
This builds on:
- swamp-club#3990: the contract in
design/surfaces/inbox.mdandSwampClubClient.listInboxMessages - swamp-club#4001: the Swamp Club endpoints, now live
It replaces the listing half of the older swamp-club#2024, which targeted /api/v1/notifications. Build from this issue, not that one.
Behaviour
swamp inbox works outside a swamp repo and is gated, like swamp subscription status. It makes one live call to GET /api/inbox/messages.
| Invocation | Lists |
|---|---|
swamp inbox |
Unread messages, newest first (status=unread) |
swamp inbox --all |
Read and unread (status=all) |
swamp inbox --limit 10 |
At most 10 (1 to 100; default 20) |
swamp inbox --before <id> |
The page older than message <id> |
Log mode:
● 2026-10-26 announcement swamp 1.42 is out
● 2026-10-25 issue_update Your issue #3990 shipped
2026-10-24 points You earned 50 points
2 unread of 3 shown.
To see older: swamp inbox --all --before 01JBX5Q8ZK00000000000000ZP●marks an unread message. Dates are the local calendar date ofcreatedAt. The kind column is padded to its widest value.- The
To see older:line appears only whennextCursoris not null, and it repeats--allwhen that was given. - With nothing to show:
No unread messages. To include read ones: swamp inbox --all- with
--all:Your inbox is empty.
- When the page reports
dropped > 0, print a warning on stderr:1 message from Swamp Club did not match the inbox format and was left out.A server drifting from the contract then shows up instead of losing messages silently.
JSON mode prints one document on stdout:
{
"status": "unread",
"messages": [
{ "id": "01JBX5Q8ZK0000000000000104", "kind": "announcement", "title": "swamp 1.42 is out",
"createdAt": "2026-10-26T09:00:00.000Z", "readAt": null }
],
"nextCursor": null,
"dropped": 0
}body, link and action are left out of both modes on purpose. They are the reading part, and they arrive with swamp inbox read. Leaving them out also keeps text Swamp Club wrote, other than the title, out of an agent's context.
Errors
The client's existing UserErrors are shown as they are:
- not signed in:
notAuthenticated(), assubscription statusshows it - a collective API key: "The inbox needs a personal API key; collective keys have no inbox."
- a server without the inbox: "This Swamp Club server has no inbox."
--limitoutside 1 to 100, or a--beforethat is not a ULID: refused before any network call
The server URL is SWAMP_CLUB_URL, else the stored credential's server, as for subscription status.
Design
src/libswamp/inbox/list.ts: aninboxList(ctx, deps, input)generator. It yieldsloading_credentials, thencontacting_server, thencompletedwith the page reduced to the fields above, orerror. Its deps are{ loadCredentials, listMessages(serverUrl, apiKey, options, signal) }. Passctx.signalto the client. Export it and its event type fromsrc/libswamp/mod.ts.src/presentation/renderers/inbox_list.ts:createInboxListRenderer(mode), with log and JSON. Use theTo …:call-to-action style from the workflow renderer.src/cli/commands/inbox.ts: the command, with the action on theinboxcommand itself, soswamp inbox readcan be added later as a subcommand without changing howswamp inboxbehaves. Options:--all,--limit <n:integer>,--before <id:string>.src/cli/mod.ts: register.command("inbox", inboxCommand)besidesubscription, and add"inbox"toNON_REPO_COMMANDS.- Leave the inbox cache (
InboxCacheFileRepository) alone. Updating it belongs to the read and wiring PRs. - Don't change the skill. Its rule 4 already covers the notice, and
swamp helpmakes the command discoverable.
Tests
src/libswamp/inbox/list_test.ts, usingmessagesPagefrominbox_responses.fixture.json:- the default sends
status=unreadand limit 20 --all,--limitand--beforeare passed through- fields are reduced, with no
body,linkoraction droppedandnextCursorare passed throughnotAuthenticatedwhen there is no key- a client
UserErrorpasses through ctx.signalis used- refused input makes no call
- the default sends
src/presentation/renderers/inbox_list_test.ts:- log: rows, the unread marker, kind padding, the count line,
To see older:with and without--all, both empty states, the dropped warning on stderr - JSON: the exact document
- log: rows, the unread marker, kind padding, the count line,
src/cli/mod_test.ts:inboxis repo-less.src/cli/auth_gate_exemptions_test.ts: pin["inbox"]asgated.integration/json_mode_conformance_test.tsandcli_help_wording_test.tspick the command up frommod.ts. Run all ofintegration/before verifying.
Do one live check with the compiled binary against swamp-club.com: a staff send to yourself through #4001, then swamp inbox, swamp inbox --all --json, and swamp inbox with a collective key. Record the output in the PR.
Out of scope
swamp inbox read, message bodies, links and actions, and marking messages read- The background poll and the post-command notice
- Manual pages (filed separately once reading ships)
In Progress
Click a lifecycle step above to view its details.
Sign in to post a ripple.