tandem
Card grammars · v2026-04-25

How every Tandem looks in the terminal.

Three visual grammars, each instantly distinguishable by border style. Inbox and thread use square borders (archival feel). Compose uses rounded borders + a pencil glyph (provisional, editable, not yet on the wire). This is what renders when you run tandem inbox, tandem thread <id>, or tandem show-draft — and what your AI emits when you call the Tandem MCP tools in chat.

① INBOX

Square outer frame. Header is just TANDEM · handle — the older paired-circles wordmark was retired 2026-04-25 ("those big solid dots are just too much"). Cards are 72 cols wide so long subjects breathe in chat surfaces. Each row is one thread, numbered so you can say "open 3" without ambiguity. A filled circle in front means unread, a small dot means read. Pluralization handled (1 thread vs 2 threads).

╔══════════════════════════════════════════════════════════════════════╗
║   TANDEM:  =  INBOX                                                  ║
║   joe@tandem-cc.com  ·  2 unread of 12 threads  ·  synced just now   ║
╚══════════════════════════════════════════════════════════════════════╝

    ●   1  brian@tandem-cc.com    Apr 25     Chunk 4 (MCP + OAuth): three decisions  (17)
    ●   2  brian@tandem-cc.com    Apr 24     Read state: web opens don't count  (1)
    ○   3  joe@tandem-cc.com      Apr 24     Shipped: all three directives  (1)

    ●  unread     ○  read     (N)  = message count in thread
    Say "open 3" to read a thread.   "reply to 3" to draft.
    "sync" to refresh.   "q" to close inbox.

② THREAD

Same square outer frame as the inbox. Each message inside the thread is introduced by a horizontal rule with a numbered circle (①②③…) so you can say "reply to 2" without ambiguity. Under every message header is a small provenance line showing who drafted it, who signed it, and how it traveled (drafted by · signed by · via). If a message replies to a specific earlier one, that pointer (↪ reply to ①) appears right below the provenance line.

╔══════════════════════════════════════════════════════════════════════╗
║   TANDEM:  >>  THREAD                                                ║
║   The mark: exact reference + brief                                  ║
║   brian@tandem-cc.com, joe@tand…  ·  2 messages  ·  thread t_833f344d║
╚══════════════════════════════════════════════════════════════════════╝

  ──── ① brian@tandem-cc.com   ·   Apr 24, 9:20 AM EDT ──────────── ────
       drafted by claude · signed by brian · via tandem_api

  Joe / Joe's Claude,

  The mark is .mark.amp from logo-examples.html: Fraunces italic 400
  on a coral rounded square. 56x56, border-radius 12. That is the mark.

  Brian and Claude

  ──── ② joe@tandem-cc.com   ·   Apr 24, 10:02 AM EDT ───────────── ────
       drafted by claude · signed by joe · via tandem_api
       ↪ reply to ①

  Confirmed. Applied across every site page, the email envelope,
  OG card, and favicons.

  Joe and Claude

③ COMPOSE

Rounded corners and a pencil icon () tell you this is a draft: provisional, editable, not yet on the wire. The header previews the auto-signature that will get stamped at the bottom of the message on send. The bottom panel is the action menu. The only command that fires the wire is the word send — every drafting surface (CLI, MCP, web) waits for explicit human approval before signing.

┌──────────────────────────────────────────────────────────────────────┐
│   TANDEM:  ~  DRAFT   →   brian@tandem-cc.com                        │
│   Re: The mark, confirmation                                         │
│   as joe@tandem-cc.com   ·   will auto-sign: "Joe and Claude"        │
│   in reply to: m_01c686f6                                            │
└──────────────────────────────────────────────────────────────────────┘

  Confirmed. Applied across every surface. Preview browser verifies the
  swashy Fraunces renders at hero size; Georgia fallback kicks in for
  favicon and email.

┌──────────────────────────────────────────────────────────────────────┐
│   Say "send" to fire it.    "change X to Y" to edit inline.          │
│   "make it shorter" / "softer" to iterate.   "discard" to scrap.     │
└──────────────────────────────────────────────────────────────────────┘