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, elseargv0”. Sopingorcodexstarted 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 spawnargv[0]. The right part is taggroup, 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 leader1–9keys; 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 topmodel 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 whilemarks.commandsis 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.bottomstatus line can sit right below venom’s bar. Sections 2.9, 3.8, 4 and 5, the alternatives and theconfigimpact 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
Chromestyles andStatusmarks. They MUST NOT use raw palette indices or barereversefor chrome (venomx#37 is this rule forattach_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
sessionsnapshot 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 ofgravebetween blocks. The focused pane’s block is the signal with itson_text, the processbold; the others arebone_dimonash.- 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, elseprocess, elseargv0, 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. - The cwd is the pane’s OSC 7 cwd,
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-codepane has focus: its block is in the signal, and its title line and the separator beside it are heavy and in the signal. Thecodexpane sits in the top row, so its title is on the title row under the status line. Thezshandeventspanes sit below it, so their titles are on the separator between them and thecodexpane. 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
argv0frompane.list,pane.createdor thepaneentity (RFC-0007 §5): the basename of the spawnargv[0], such asnvimfor/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 taggroup(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,localhostor the local hostname, and only when the path equals$HOMEor starts with$HOMEfollowed 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:
- the right part (tag
groupor the OSC 7 cwd); - the title, cut from its end with
…, then dropped; - 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.
- the right part (tag
-
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
urgentattention, else inrule. 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%naliases 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.commandsis 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.commandson 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 thedangermark. - 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:
- Status segments drop by priority (RFC-0016 section 5.3).
- Pane title lines drop parts in 3.2’s order; the state mark always stays.
- 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.
- 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). --jsonand exit codes: no change.- Events: no change. Section 3.9 reads
principal.deniedas 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, defaulttrue, hot-reloadable; toggling it changes the tiled area’s width by the gutter’s column, and the layout tree divides it again, 3.4).themeis 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 issuefrom outside the tree, or venom’s inbox throughrespond). Givingvenomx attachthe 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).