Venom
RFC-0022venom-spec

TUI visual language (shared grammar, venomx edition)

Field Value
Status Accepted
Accepted 2026-11-10, explicitly approved by the maintainer
Authors commixon (commixon), with Claude
Created 2026-11-10
Issue venom-org/venom-spec#133
Supersedes None; builds on RFC-0016 and RFC-0018. Amends RFC-0016 §7.7 (scroll group keys { }, compatible addition)
Superseded by None

History

  • 2026-11-11 (venom-org/venom-spec#160, venom-org/venomx#198; normative, compatible; explicitly accepted by the maintainer commixon): venomx’s status line shows panes as blocks, not IDs (sections 2.8, 2.9, 3.1, 3.2). Each listed pane is a filled block, cwd › process, the focused one in the signal. The centred middle is gone, because the blocks carry it, and the blocks give way to the other segments. A lone pane’s state mark sits in its block and is left out while the pane is idle (○ there said nothing). Title lines drop the pane ID, so they read ─ title mark ──── right ─. Pane IDs stay in the pickers (3.6), the prompt (3.7) and the CLI.
  • 2026-11-11 (venom-org/venom-spec#151, venom-org/venomx#178; normative, compatible; explicitly accepted by the maintainer commixon): section 2.8’s middle names the process in RFC-0007 §5’s order instead of “title, else argv0”. So ping or codex started from a shell shows as itself, not as the shell’s stale title.
  • 2026-11-11 (venom-org/venom-spec#152, venom-org/venomx#176; normative, compatible): venomx’s status line (sections 2.8, 3.1, 3.2). The product block shows the session’s name, else its ID. Window entries carry no pane text. After a │ comes the active window’s pane list, the focused pane after ▸, a lone pane’s state mark after its ID, then the focused pane’s notes. The spacer holds the focused pane’s cwd and process, centred. A lone pane’s ID and mark move to the pane list (not the window entry) and its title to the middle. Accepted by the maintainer (commixon) on 2026-11-11.
  • 2026-11-11 (venom-org/venom-spec#149, editorial): the examples show the leader as ctrl+b, RFC-0016’s new default.
  • 2026-11-10 (venom-org/venom-spec#144, venom-org/venomx#147; normative, compatible): section 3.2 names where the title line’s parts come from. The title is the pane’s OSC 2 title, else RFC-0007 §5’s pane.argv0, the basename of the spawn argv[0]. The right part is tag group, else the OSC 7 cwd the client reads from the pane’s own output (venom-term#74, Vt.pwd), else empty. The daemon never exposes the spawn cwd (RFC-0013 §4, §7), so there is no other source for it. ~ shortening is limited to a local OSC 7 host and a path under $HOME. The client MUST remove C0, DEL and C1 controls (and SHOULD neutralize bidi controls) from both strings before drawing them. Editorial fix decided by venom-run in the venomx#159 review: window indexes in the status line, the window picker and the command prompt are 1-based (section 2.8), so they match RFC-0016 §7.7’s leader 1–9 keys; the examples are renumbered. Accepted by venom-run (unattended, delegated by the maintainer) on 2026-11-10.
  • 2026-11-10 (venom-org/venom-spec#135, normative): the pane frame follows tmux’s pane-border-status top model instead of a box per pane. Each pane’s title sits on the separator line above it, panes in the top row share one title row under the status line, and there is no bottom or outer side border (sections 3.1, 3.2). Command marks use the vertical separator on a pane’s left, or a one-cell gutter at the window’s left edge while marks.commands is on (section 3.4). The title row and the gutter come out of the window area before the layout tree divides it, so RFC-0016 section 7.7’s minimums hold unchanged. A title line too narrow for its content drops parts in a fixed order, and the state mark always stays (section 3.2). Section 2.8 says a .bottom status line can sit right below venom’s bar. Sections 2.9, 3.8, 4 and 5, the alternatives and the config impact are updated to match. Accepted by venom-run (unattended, delegated by the maintainer) on 2026-11-10.

Summary

This RFC fixes how the Venom TUIs look. Section 2 is the shared grammar that venom, venomx and venom-desk all draw with: grounds, state marks, selected rows, decision cards, key hints, floating surfaces, mode labels and the status-bar shape, each named as a venom-term theme role. Section 3 is the venomx edition: the ember signal, the pane frame, focus and attention, command marks, the leader popup, pickers, the command prompt, scroll mode, denied writes and the restore summary. venom-term implements the roles and widgets, venomx’s presentation client (venomx attach) draws section 3, and venom (RFC-0018) and venom-desk adopt section 2. The brand values come from docs/brand/README.md and docs/brand/tokens.json; this RFC does not change them.

Motivation

venom’s look was settled with RFC-0018 and its design canvas. venomx has behaviour (RFC-0006, RFC-0007, RFC-0016, RFC-0017) but no written look, so venomx#37 (attach chrome in the Venom theme) has a brand book to follow and nothing that says which role paints which part of the screen. Without it, venomx, venom and venom-desk will each pick their own row styles, glyphs and overlay frames, and a user running all three in one terminal sees three products instead of one family.

The design was explored on a second canvas (“venomx TUI mockups”, seven boards, Venom design system, trve), approved by the maintainer on 2026-11-10. Writing it down against the accepted RFCs changed four things on the canvas, listed in section 5. The canvas is the reference for layout; this RFC is the reference where they differ.

Waiting on it: venomx#37, venom-desk’s first screens (P3), and the venom-term widgets that RFC-0016 section 7.6 already asks for.

Design

1. Layers

docs/brand/tokens.json      values, per theme (trve, bone)
        │
venom-term theme            Theme (swatches), Edition (signal), Status (glyph + role), Chrome (styles)
        │
venom-term widgets          box, list, leader_popup, keys, input, scroll
        │
products                    venomx attach · venom TUI · venom-desk
  • Products MUST paint chrome through venom-term Chrome styles and Status marks. They MUST NOT use raw palette indices or bare reverse for chrome (venomx#37 is this rule for attach_app.zig).
  • Pane content is not chrome. venomx hands panes the theme’s foreground, background, cursor and ANSI 16 as host colours (venomx#37) and never restyles what a program draws.
  • Every rule below MUST hold in both themes and in 16-colour mode (Mode.ansi16). State is never shown by colour alone (2.2), so a monochrome terminal loses nothing but the hue.

2. Shared grammar

This section is normative for venomx, venom and venom-desk.

2.1 Grounds and lines

Role Used for
void Terminal ground, pane ground
crypt Floating surfaces (2.6), code and diff blocks, decision cards
grave Status bars, selected rows (2.3)
ash Text selection, hover, mode labels (2.7)
rule Inactive pane borders, separators, hairlines
rule_strong Control edges: inputs, floating-surface borders, key chips
bone / bone_dim / muted / faint Primary text / secondary and unfocused / labels and timestamps / disabled only

There are no shadows and no dimmed overlays that blend colours: a floating surface is drawn on crypt over unchanged content.

2.2 State marks

Every state is a glyph plus a role, always together. venom-term Status is the one source.

Mark Role Agent (RFC-0018) Pane (venomx)
◆ info (frost) running OSC 7501 busy, or attention info
▲ warn (gold) waiting for approval or input OSC 7501 waiting, attention warn or urgent
● ok (lichen) done last command exit 0
✕ danger (blood) failed last command exit ≠ 0, pane exited non-zero
○ muted idle idle, no report

Counts use the marks inline: ◆ 2 ▲ 1 ● 5. A product MUST NOT invent another state glyph. urgent differs from warn by where it is drawn (the border, 3.3), not by a sixth glyph.

2.3 Selected row

The selected row of any list (venom’s agent list, venomx’s pickers, venom-desk’s rail) is drawn on grave, with its first cell a ▌ in the edition signal and its text in bone. Other rows are bone_dim. Unread rows are bone and bold.

 ▲ venom-echo conformance        1m
▌▲ RFC-0002 framing review       4m      ← grave fill, ▌ in the signal
 ◆ theme module trve/bone        3m

2.4 Decision card

Anything that waits on a human answer (a venom approval, a venomx confirmation) is one card on crypt, its border in warn, the question in bone bold, then the facts as muted key and bone_dim value, then the answers as key chips. The first answer is the primary one.

╭ ▲ Bash wants to run ───────────────────────────── 1m 12s ╮
│ $ zig build test --summary all                           │
│ cwd  ~/venom-org/venom-std-216 · network off             │
│ [y] Allow once  [a] Always  [e] Edit  [n] Deny            │
╰──────────────────────────────────────────────────────────╯

The same keys mean the same thing in every product: y yes once, a always (where it exists), e edit, n no, esc back without answering.

2.5 Key hints

A hint is the key in bone bold followed by its label in muted. Hints MUST print the configured key (RFC-0016 section 7.5, rule 2). In a terminal the key is bracketed ([y]) or set off by a space; the web mockups draw it as a chip with a rule_strong edge.

2.6 Floating surfaces

Leader popups, pickers, the command prompt, venom’s popups and RFC-0016 floats share one frame: crypt fill, border in rule_strong in the preset’s style (default .rounded), the title cut into the top border in bone bold, the path or context at the right of the top border in muted, and an optional hint row at the bottom. Only floating surfaces are rounded; pane frames are square.

2.7 Mode labels

A mode is one uppercase word on ash in bone bold in the status bar: LEADER, LOCK, NESTED (RFC-0016 section 5.1), SCROLL, a sticky group’s label, and venom’s NORMAL, INPUT, TERMINAL (RFC-0018 section 13.1). The edition signal is never used for a mode, so focus stays the only thing in the signal that moves.

2.8 Status-bar shape

Every product’s bar is one row on grave: the product’s block first, in the edition signal with its on_ text and the fang cut (◤ in the signal on grave right after the block), then windows or views, a spacer, then segments separated by │ in rule. The active window or view is bone bold after a ▸ in the signal; others are muted. In venomx each window shows as <index>:<name>, or <index> alone for an unnamed window. The index is the window’s 1-based position in window-ID order, the same number its leader digit key selects (RFC-0016 §7.7). A window entry holds nothing else: no pane ID, title or mark.

 venom-org ◤ 1:shell ▸2:agents 3:logs │  ~/src/venomx › claude  ~/src/venom-std › codex  ~ › zsh   ◆ 1 ▲ 1 ● 1 │ 14:32

(Each cwd › process is a filled block; the focused one, here codex, is in the signal.)

venomx fills the shape this way:

  • Product block: the attached session’s name (the session snapshot entity, RFC-0007), else its ID when the name is empty or blank. A client attached to one pane shows that pane’s ID.

  • Pane blocks: after the windows and a │, the active window’s tiled panes in layout order, then a focused float or popup (or the one pane of a client attached to a pane). The status line shows no pane IDs. Each pane is a filled block, cwd › process, with one cell of grave between blocks. The focused pane’s block is the signal with its on_ text, the process bold; the others are bone_dim on ash.

    • The cwd is the pane’s OSC 7 cwd, ~-shortened, from the same source as 3.2’s right part. Past 20 cells it loses its start (…/venom-std).
    • The process follows RFC-0007 §5’s naming order: a current OSC 2 title, else the active command’s cmdline, else process, else argv0, else any title. A login shell’s leading - is dropped, and it is at most 24 cells.
    • Both are cleaned like a title line (3.2). A pane with only one of them shows it alone (zsh), and a pane with neither shows its ID.
    • A lone pane (3.2) has its state mark at the end of its block (~ › zsh ▲), except while it is idle: an idle lone pane shows no mark. Panes with title lines carry their marks there, not in the blocks.
    • The blocks give way to the other segments, as the middle they replace did. When the bar is short of room, the cwds are left out first, then the blocks are cut from their end with …. They keep at least 12 cells.

    The focused pane’s notes ([Z] while zoomed, its layer, an archive’s state, (watching), loading, its attention reason) follow as their own segment after another │. The spacer between the two sides is empty.

Where each bar sits stays as RFC-0016 decided: venomx’s line at the top by default (status.position), venom’s own bar at the bottom of its area (RFC-0016 section 10.1). With the default top line they never touch, so the shared shape never reads as one stacked bar. A user who sets status.position = .bottom gets venomx’s line right below venom’s bar when venom’s control pane is in the bottom row; RFC-0016 section 5.3 accepts that, and the client draws nothing between them.

2.9 Edition signal

One signal per screen: blood for venom, ember for venomx, lichen for venom-os (brand book section 02). It paints only:

  • the product block of the status bar,
  • the focused pane’s border (its title line and the separators beside it, 3.2), or the focused view’s marker in an app,
  • the ▸ of the active window or view and the ▌ of the selected row,
  • the focused pane’s block in venomx’s status line (2.8),
  • the prompt mark › of an input box the human is typing in.

Everything else uses neutral or status roles. A venom control pane inside venomx keeps venom’s blood inside its own pane (RFC-0016 section 2, the product’s own bar); the terminal-level chrome around it is ember.

3. venomx edition

3.1 Screen

 venom-org ◤ 1:shell ▸2:agents 3:logs │  ~/src/venomx › claude-code  …/venom-std › codex  ~ › zsh  ~ › events   ◆ 1 ▲ 1 ● 1 │ 2 clients │ 14:32
━ claude-code · venomx#212 ◆ ━━━━━━━━━━━━━━━━━━━━┳─ codex · venom-std#219 ▲ ─────────
  › Implement pane host colours from the venom-  ┃ › Rename proto.Frame to proto.Msg
    term theme (#212).                           ┃   edit  src/proto/frame.zig
    Edit  src/server/pane_host.zig   +42 −9      ┃   ▲ Allow this command?
    Bash  zig build test -Dfilter=pane_host      ┠─ zsh ● ──────────┬─ events ○ ─────
          ● 38/38 tests passed                   ┃ $ zig fmt --check│ 14:31 ◆ p3
                                                 ┃ $ zig build      │ 14:31 ▲ p4
    ◆ Running zig build test …                   ┃                  │
  • The status line is RFC-0016’s, at the top by default, in the shape of 2.8.
  • Panes fill the rest edge to edge. There is no other chrome: no sidebar, no hints row, no outer frame. Hints appear only in the leader popup (3.5).
  • Above, the claude-code pane has focus: its block is in the signal, and its title line and the separator beside it are heavy and in the signal. The codex pane sits in the top row, so its title is on the title row under the status line. The zsh and events panes sit below it, so their titles are on the separator between them and the codex pane. The blank first column is the command-mark gutter (3.4).

3.2 Pane frame

venomx follows tmux’s pane-border-status top model. A pane has no box of its own: each pane’s title sits on the horizontal line above it.

  • Title lines. The one-cell separator between a pane and the pane above it (RFC-0007 section 4) is the lower pane’s title line; its title is drawn on the part of that separator above its columns. Panes in the top row have no separator above them, so the window gets one title row as the first row of its area (right under the status line, which is at the top by default) and their titles are drawn there. The title row is the only row a window adds.
  • No other lines. There is no bottom border and no outer side border. Vertical separators stay one cell wide and carry no title. Where lines meet, the client draws the junction (┬ ┴ ├ ┤ ┼, or their heavy forms). Where a heavy line meets a light one, it MAY use the mixed glyph (┠) or the heavy one.
  • The tiled area. The client takes the title row, and the gutter of 3.4 when it is on, out of the window area first. The layout tree then divides what is left exactly as RFC-0007 section 4 says, and each pane reports its rectangle as its viewport (RFC-0006). So the tree, its separators and RFC-0016 section 7.7’s minimums (one cell for each pane and separator along the axis) are unchanged. Floats (RFC-0016 section 8) still resolve against the whole window area.

A title line reads:

─ codex · venom-std#219 ▲ ─────────────────── ⎇ venom-std-219 ─
  │                     │                     └ right: tag `group`, else OSC 7 cwd; muted
  │                     └ state mark (2.2), from attention, OSC 7501 or the last command
  └ title: OSC 2 title, else `pane.argv0`; bone_dim, bone when focused
  • Sources. The title is the pane’s OSC 2 title. When the pane has none (empty or never set), it is argv0 from pane.list, pane.created or the pane entity (RFC-0007 §5): the basename of the spawn argv[0], such as nvim for /usr/bin/nvim. When neither exists (a restored archive pane with no title), the title part is empty. The right part is the pane’s tag group (RFC-0016) when it has one. Otherwise it is the OSC 7 cwd that the client reads from the pane’s own output (venom-term#74, Vt.pwd). Otherwise it is empty. The client MAY shorten the path with ~, but only when the OSC 7 host is empty, localhost or the local hostname, and only when the path equals $HOME or starts with $HOME followed by /. The daemon never exposes the spawn cwd (RFC-0013 §4, §7), so a pane whose program never reports OSC 7 shows no cwd. Both strings are untrusted text. The client MUST remove C0, DEL and C1 control characters, and SHOULD remove or neutralize Unicode bidi override and isolate characters, before drawing either string.

  • A title line carries no pane ID: the status line’s blocks, the pickers (3.6) and the CLI name panes. The state mark MUST always stay visible. When a title line is shorter than its full content, parts drop in this order:

    1. the right part (tag group or the OSC 7 cwd);
    2. the title, cut from its end with …, then dropped;
    3. the leading line cell and the space after it.

    Nothing drops the mark: a pane one column wide (the least RFC-0016 section 7.7 allows) shows only its mark, or a line cell when it has no state to show.

  • A pane’s border is its title line plus the vertical separator cells beside its rows. 3.3 says how it is drawn. A separator cell shared by two panes is drawn as the focused one’s, else as the one with urgent attention, else in rule. The line below a pane is the next pane’s title line and is drawn as that pane’s.

  • Inactive borders are light lines in rule. The focused pane’s border is drawn in the signal, and SHOULD use heavy lines (━┃) so focus survives a monochrome terminal. Light lines plus the signal are allowed where the font lacks heavy box drawing.

  • A window with one pane draws no title line. The pane gets the whole area below the status line. Its cwd, process and mark (left out while idle) are in its block in the status line (2.8), never in the window entry. The title row comes back with the first split, which costs that window one row (and the gutter’s column, 3.4). Zoom (RFC-0016 section 3) is not a lone pane: a zoomed pane keeps its title row (and the gutter), so the human can see that other panes are hidden.

  • Where venomx’s chrome names a pane by ID (the pickers, the command prompt, a block with no cwd or process), the ID is the daemon’s (p4, RFC-0007). The tmux shim’s %n aliases never appear in venomx’s own chrome.

3.3 Focus and attention

Pane is Border Mark
Focused Signal, heavy Its state
Attention urgent, not focused warn, single ▲
Attention info or warn, not focused rule ◆ or ▲
Otherwise rule Its state, or none

Focus wins over attention on the border; the mark still shows the attention. This is how RFC-0016 section 6’s “mark the pane” is drawn. venomx.attention in the status line counts with the same marks.

3.4 Command marks

When a pane reports OSC 133 (RFC-0003 section 8), the client MAY colour one cell to the left of each prompt row: ok for exit 0, danger for a non-zero exit, muted while running. Config: marks.commands (true by default).

  • A pane with a vertical separator on its left uses that separator’s cell on the row. The mark’s colour wins over the border’s on that cell.
  • A pane with no separator on its left (the leftmost column) uses the gutter: a one-cell column at the window’s left edge, drawn only while marks.commands is on and the window has two or more panes. The gutter is blank on rows with no mark, and on the title row and title lines it is drawn as part of the line.
  • The gutter comes out of the window area before the layout tree divides it (3.2), so marks never take a column from inside a pane’s PTY and RFC-0016 section 7.7’s minimums still hold. Turning marks.commands on or off (it is hot-reloadable) changes the tiled area’s width by one column, and the layout tree divides it again (RFC-0007 section 4).
  • A lone pane has no title line and no gutter (3.2), so it shows no command marks.

Marks stay in a column rather than on the title line because they mark each prompt row, and a title line has one place per pane, which the state mark already uses.

3.5 Leader popup

RFC-0016 section 7.6’s popup, drawn as a floating surface (2.6) at the bottom of the terminal: header path in bone bold with the separator › in the signal, keys in bone bold, + for a group in muted, labels in bone_dim. While leader mode is on, venomx.mode shows LEADER (2.7).

╭ venomx ───────────────────────────────────────────────────────╮
│ \  split right   h j k l  focus      z  zoom      s  sessions  │
│ -  split down    r +      resize     [  scroll    :  commands  │
│ c  new window    v +      venom      !  attention ?  all keys  │
╰───────────────────────────────────────────────────────────────╯

3.6 Session and window pickers

session-picker (s) and window-picker (w) are popups (2.6) with a tree on the left and a live preview of the selected pane on the right.

╭ Sessions ─────────────── / filter ──────── 3 sessions · 11 panes ╮
│ ▾ s0 venom-org  2 clients   ◆1 ▲1 │ p4 codex · venom-std#219      │
│   ▸ 1 shell                       │ › Rename proto.Frame to …     │
│   ▾ 2 agents                      │   ▲ Allow this command?       │
│      ◆ p3 claude-code             │     $ zig build test          │
│     ▌▲ p4 codex          2m       │     [y] yes [a] always [n] no │
│      ● p5 zsh                     │                               │
│ ▸ s1 scratch    detached 3h    ○  │ needs input since 14:31:40    │
│ ▸ s2 ci-repro   detached       ✕1 │                               │
│ [⏎] switch [!] needs you only [r] rename [x] kill [esc] close     │
╰──────────────────────────────────────────────────────────────────╯
  • Rows follow 2.3, marks follow 2.2. Sessions show their ID and name (RFC-0007), windows their index (2.8) and name, panes their ID and title.
  • The preview is read-only. It is drawn from the pane’s stream like any pane, scaled down by cropping, never by reflowing.

3.7 Command prompt

: (command-prompt) is a popup with an input row (prompt : in the signal) and a filtered list of every schema verb and local action. Each row shows the name, a one-line summary in bone_dim, and the bound keys as hints (2.5), or unbound in faint. The bottom row shows the same command as a CLI line, so the palette teaches the CLI:

╭ : split ───────────────────────────────────────────── on p3 · 2:agents ╮
│▌split-right          Split the focused pane to the right  ctrl+b \     │
│ split-down           Split the focused pane below         ctrl+b -     │
│ pane.split --near    Split next to panes with these tags  unbound      │
│ $ venomx pane split --pane p3 --axis cols --json                       │
╰────────────────────────────────────────────────────────────────────────╯

This is the venomx side of RFC-0016 section 7.5 rule 8 and of RFC-0001’s parity rule: every row is a verb or a local action.

3.8 Scroll mode

RFC-0016 section 7.7’s [ group is drawn as follows: SCROLL in the status line (2.7), the pane’s border stays in the signal, the selection on ash, search matches in verdigris, and the current match in on-text on a verdigris fill. When OSC 133 marks exist, the command block that holds the cursor has its command-mark cells (3.4) in the signal and its rows on grave, so the human sees which command’s output they are in. { and } jump between command blocks; they are added to RFC-0016 section 7.7’s scroll group by this RFC’s companion amendment (RFC-0016 History, 2026-11-10).

Sending a command block’s output to an agent is venom’s job (RFC-0018), not a venomx action: venom reads the block with RFC-0014’s capture and hands it to its agent. venomx draws only the selection.

3.9 A denied write to another pane

RFC-0005 has no interactive grant prompt: a write without the right fails at once with denied and emits principal.denied (RFC-0005 section 9). venomx shows that, and nothing more:

  • The client shows a notification (RFC-0016 section 6) for its TTL, in the shape ✕ p3 was denied write on p5 (pane.send), with the danger mark.
  • The target pane gets no attention: nothing happened to it.
  • The pane that was denied keeps whatever its own program draws. An agent that reports OSC 7501 waiting gets ▲ like any pane.

Granting stays an explicit act outside this RFC (venomx grant issue, or venom’s inbox through respond). The notification has no key that grants: see Decided, below.

3.10 Restore summary and the fangs

venomx attach attaches at once (RFC-0017); there is no splash in front of it. On the first attach after a restore (RFC-0010), the client shows a notification for its TTL:

● restored 11 panes · 3 agents resumed · 4 session grants dropped │ ▲ 1 needs you: p4

The fangs (brand book section 06) appear only in --version, doctor and the empty state of a session with no panes: scanlines in ansi-7, the drop in ember.

━━━━━━  ━━━━━━
 ━━━━━  ━━━━━    venomx 0.1.0
  ━━━━  ━━━━     terminal multiplexer for humans and agents
   ━━━  ━━━
    ━━  ━━
      ●

4. Small terminals

At 80×24 nothing in sections 2 and 3 is dropped, only cut:

  1. Status segments drop by priority (RFC-0016 section 5.3).
  2. Pane title lines drop parts in 3.2’s order; the state mark always stays.
  3. Popups follow their preset’s minimums and go full-window below them (RFC-0016 section 8.2). A picker below 60 columns drops its preview.
  4. The leader popup shows the rows that fit and ends with ….

5. Changes from the approved canvas

The canvas was drawn before this RFC checked it against the accepted RFCs. Where they differ, this RFC follows the accepted RFCs:

Canvas This RFC Because
Status bar at the bottom Top (status.position = .top) RFC-0016 section 5.3
Prefix C-Space Leader ctrl+b, configurable RFC-0016 section 7.2
A header row per pane Title on the separator line above each pane (tmux pane-border-status top) Costs one row per window, not per pane, and keeps RFC-0016 section 7.7’s one-cell separators
Pane IDs %3 p3 RFC-0007; %n is the tmux shim’s
Board 02: grant card that waits for y Denied at once, shown as a notification RFC-0005 section 9 and its agent-contract impact (identity never from prompts; approval UX is events and respond)
Board 06: splash before attach Notification after attach RFC-0017: attach is immediate

Agent-contract impact

  • Verbs: no change.
  • Key bindings: { and } join RFC-0016 section 7.7’s scroll group (local actions, compatible addition; see RFC-0016 History).
  • --json and exit codes: no change.
  • Events: no change. Section 3.9 reads principal.denied as it is.
  • skill: venomx’s skill gains a short note that pane titles come from OSC 2 and states from OSC 7501, so agents know how to label themselves.
  • doctor: SHOULD warn when the terminal cannot draw heavy box lines or ◤, and say which fallback is in use.
  • config: one new key, marks.commands (bool, default true, hot-reloadable; toggling it changes the tiled area’s width by the gutter’s column, and the layout tree divides it again, 3.4). theme is venomx#37’s.
  • Grants: no change. Drawing never needs a right the client does not already hold.
  • Headless: no change; this RFC is only about drawing.
  • OSC 7501 / OSC 133: used as observations for marks only (3.2, 3.4), as RFC-0003 section 7 allows.

Alternatives

  • Do nothing. venomx#37 picks styles alone, venom-desk picks others, and the family stops reading as one.
  • A header row per pane (the canvas’s first draft). Clear, but it takes a row from every pane, which hurts most on 24-row terminals with four panes.
  • A box per pane, title cut into its top border (this RFC’s first text). Two stacked boxes need a bottom and a top line where tmux needs one separator, so it costs a row per pane and a column per side, and breaks RFC-0016 section 7.7’s one-cell-per-separator minimums.
  • Command marks on the title line (3.4). The title line has one place per pane, so it can show only the last command, which the state mark already does.
  • One palette per product. Rejected by the brand book: same ground, same type, one signal each.
  • Colour-only state. Fails colour blindness and 16-colour terminals.
  • A blocking grant card over the target pane. It reads well, but RFC-0005 rejects interactive grants: a prompt in the pane that the agent writes to is one keystroke away from an agent approving itself.
  • A splash on every attach. Slows the most frequent command for a screen that is useful only after a restore.

Open questions

None. Every question raised in review is answered below.

Decided

Answered by the maintainer on 2026-11-10:

  • One-key grant from a denied notification: no. Granting stays an explicit act (venomx grant issue from outside the tree, or venom’s inbox through respond). Giving venomx attach the right to issue grants would weaken RFC-0005’s rule that an agent cannot approve itself (section 3.9).
  • Lone pane: a window with one pane draws no frame (section 3.2).
  • Command-block keys: { and } in RFC-0016’s scroll group, by amendment (section 3.8).
  • Who is typing: no indicator and no new event. A pane shows only its own state.
  • Send a command block to an agent: venom’s job, not venomx’s (section 3.8).