Review of 8659ba25..be987fbb:
- Usage: a Free account answers premium_interactions {entitlement: 0, remaining: 0,
percent_remaining: 0, unlimited: false, has_quota: false}, which read as 100% used. The parser now
returns null when has_quota is false or the entitlement is not positive, with that payload as a
fixture. Free meters chat (200) and completions (2000) too, so the comment no longer says they
are unlimited on every plan.
- agent read: rows were skipped until a `❯ <prompt>` row, so an answer taller than the pane
(prompt scrolled off the top) read as "". With no prompt row AND no banner / trust dialog on
screen, the rows above the composer are now the tail of the last answer. Text typed in the
composer (a prompt-shaped row between the two rules) is not a prompt row.
- Page keys: measured on 1.0.95 in tmux that Copilot pages on PageUp/PageDown (three PageUp moved
lines 109-140 to 010-042, PageDown returned) as well as on SGR wheel reports, so copilot joins
claude and opencode in _localScrollbackIsHollow(); the stale-tracking-flag fallback the comment
and docs describe is now true, for the main pane and a TerminalTile (same function), with tests.
- X-GitHub-Api-Version is 2022-11-28, a version GitHub supports (verified against the live
endpoint); readPlanUsageTelemetryEnabled() is checked before isCopilotAvailable() so a switched-off
chip skips the resolver probe too.
- Palette label for Copilot in panels-ui.js; stale comments in types/session.ts and stock.ts.
- Docs: Past Sessions continues with --continue (resumeSessionId is for API callers), nothing sets
continueSession on a respawn, and only a tab name the user set is passed as --name; the usage
wording for Free; the wheel and mouse-strip paragraphs in CLAUDE.md and
architecture-invariants; the changeset describes the whole feature.
- New docs/copilot-integration.md in the shape of the other CLI guides: install and identity
probe, authentication (keychain vs plain-text config.json, COPILOT_GITHUB_TOKEN), what Codeman
wires up (Run button --yolo and its clamp, model, resume, continue, --name rule), BYOK custom
endpoints, terminal behaviour (drag selection, wheel and touch), the codeman agent verbs
(ready mark, read), plan usage, Docker, Remote SSH, what is deliberately not wired, known gaps.
- Agent-CLIs wiki: the eleven-modes table, a GitHub Copilot CLI section, the env prefix row, the
feature-comparison rows and the status endpoint list.
- README, Home, FAQ, Core Concepts, Docker Cases, Remote SSH, Contributing, The Dashboard and
Custom Model Endpoints: mode lists and counts; CLAUDE.md: stack line, SessionMode, prefixes,
resolver list, external-CLI notes and the plan-usage source; api-reference MCP target wording;
the env allowlist error message names COPILOT_*.
Copilot's TUI turns mouse tracking on itself. Under `strip-mux-only` those DECSETs reached
xterm, which then reported a plain drag to the TUI instead of selecting (only Shift+drag
selected), so Auto Copy and copy-on-select did nothing. This is the failure opencode had and
`strip-mux-and-mouse` was added for: the DECSETs are stripped, a drag is a local selection and
clicks still reach the CLI through the browser's hand-encoded tap (`cliMouseTracking`).
Stripping them also stops xterm from encoding the wheel for the CLI, so
`_shouldForwardWheelToApp` now forwards it as SGR reports while Copilot is tracking the mouse
(the same bytes xterm sent natively, which is what scrolling was verified against). Shift+wheel
stays on local scrollback and a stale flag falls back to PageUp/PageDown.
Tests: the strip flavor for copilot (stripped DECSETs, 3J kept, cliMouseTracking, direct-PTY
untouched) and the wheel gate (forwards while tracking, no other non-claude mode changes).
- Drop GH_TOKEN / GITHUB_TOKEN from env.allowedKeys. The allowlist is one global list with no
mode context, so they were settable on every session. COPILOT_GITHUB_TOKEN is already admitted
by the COPILOT_ prefix.
- Declare capabilities.mcpConfig (copilot-json, COPILOT_HOME relocation) so Settings does not
list Copilot as unsupported while the sync-only target also lists it. The sync-only row is
skipped while the run mode is enabled.
- Require a leading alphanumeric on the resume id (path-segment in the registry, matching regex in
the schema): --resume's value is optional, so `--resume --yolo` made --yolo its own flag and
bypassed the allowAll clamp. Golden cases added; "ids only" wording corrected.
- Remove the unread overlays.credStore line and document signing in inside a Docker container.
- Add the zh-CN "Run GitHub Copilot" string, pin the new declarations in tests and update the
MCP registry expectations.
Copilot (`copilot`, npm @github/copilot) as a stock CLI entry with the same launch options as the other agent CLIs: model (--model), resume (--resume), continue (--continue) and allow-all (--yolo, clamped off for non-granted multi-user owners). Adds a resolver and GET /api/copilot/status probe, the agent-image package, Run-menu/mobile/logo entries, skill docs and tests.
Follow-up to the previous commit, after a fact check against the code.
- Answer surfaces: the header bell answers Claude prompts, the phone
strip only Claude dialogs (and only with the inbox on), and push
Approve/Deny only a Claude permission prompt (PUSH_EVENT_MAP gives
actions to permission_prompt alone). README, its Chinese mirror, the
notifications page and the phone guide now say so.
- Antigravity and Grok Build: after the 3 s launch settle, idle is armed
only by Claude's prompt marker and working only by a braille spinner,
so "idle when output stops changing" was wrong. The wiki, the grok
guide and the API reference now call their status unreliable.
- DeepSeek Harness: its idle and working reports become stop and
agent_working, which drive respawn, waits and the inbox but not the
session's own working/idle display. Keeping Agents Running says that,
and that the respawn path needs the status bridge.
- The wait section of the API reference no longer calls exit the only
dependable signal for screen-checked modes; the inbox page names how
Codex and DeepSeek items clear; Core Concepts and Hooks And
Integrations no longer call DeepSeek "the one" exception; Agent CLIs
notes that Codex dialogs still raise the red alert; the inbox design
doc notes the alert-only items.
- Skill: stop and blocked list deepseek, and SKILL.md no longer says
codex has neither a transcript nor blocked. Mirrored with
scripts/sync-plugin.mjs.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The README (and its Chinese mirror) said the Approvals Inbox queues every
pending prompt and answers it from the bell or the phone. It holds prompts
from Claude Code, Codex (screen-read) and DeepSeek Harness only, and only
Claude's are answerable: Codex and DeepSeek items are alerts that say to
answer in the terminal, with no Approve/Deny on the push or the phone strip.
The wiki, the TUI guide and the phone guide now say the same.
Keeping Agents Running, Troubleshooting and the API reference still said
every CLI but Claude, Codex and DeepSeek falls back to output
stabilization. OpenCode, Gemini CLI, Pi and OMP declare
capabilities.workDetect too and get the same screen check; only
Antigravity and Grok Build declare none. Core Concepts now mentions
Codex's screen-read dialogs, and the respawn gotcha notes that DeepSeek's
own end-of-turn report reaches the respawn controller.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- docs/api-reference.md: a non-admin's GET /api/settings omits
voiceSettings.apiKey, caseOrder and lastUsedCase; a new "System
operations" table for the admin-only routes and the scoped
POST /api/auth/revoke; the error-code table now lists FORBIDDEN and the
other multi-user codes (PASSWORD_CHANGE_REQUIRED, USER_NOT_FOUND,
USER_EXISTS, LAST_ADMIN).
- docs/wiki/Multi-User-Mode.md: what a regular user reads, that their run
mode and respawn presets stay theirs on the device, the slow sign-in
case, and the admin-only system operations.
- docs/multi-user-plan.md: Settings and System ops rows marked implemented.
- CLAUDE.md: the Multi-user mode paragraph names the new pieces and tests.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
api-reference gains a Settings section (GET/PUT /api/settings, the model
config, the case order and PUT /api/config, with the 403 FORBIDDEN a non-admin
gets in multi-user mode). The Multi-User Mode wiki page explains what a regular
user's App Settings save does now, Settings-Reference links it, the plan's
Settings row is marked implemented, and CLAUDE.md notes the gate for the
Multi-user paragraph and for anyone adding a settings write.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
feat(codex): raise codex approval, question and trust dialogs as BLOCKED
Conflict resolved against #634 in src/session.ts _probePaneWorking():
#624's assignment (a dialog on screen is never work) is kept, and #634's
trust-dialog verdict block (log the hold once, remember the reading)
follows it, before _readWatching().
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
feat(shortcuts): rebindable previous/next session, duplicate-chord refusal, rebinds stay out of the PTY
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
On codex-cli 0.162.0, with 0.163.0 released, every launch first shows the
"Update available" prompt, and choosing Skip leads to a variant of the
workspace trust prompt: "2. Back to Agent Command Center" over the key-hint
row "enter continue · esc back". The pattern only accepted cancel,
interrupt, quit, answer or all as the closing word, so a fresh git repo
launched from Codeman sat on that trust prompt reading idle, with no red
alert and no blocked signal (measured live on a throwaway instance).
Adding "back" is safe because the hint row must still START with one of
the anchored hints ("enter continue" here): the popups the user opens at
the keyboard (/model, /permissions, /review, Implement this plan?) end in
"esc back" too, but their row starts with "enter select", so they stay
unmatched, as every existing negative fixture confirms. The new fixture is
the live capture with the scratch path replaced.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The Docker rule was applied to the CASE folder and its common git dir
only. A Docker case can be linked to any host folder, including a managed
worktree (`<repo>/.claude/worktrees/<name>`), which is a natural setup for
running one of the parallel agents in a container. Removing that worktree
from the local case's dialog, or through Close Session's "Kill & remove
worktree", ran `git worktree remove`, which runs a git status INSIDE the
tree (container-written files, checkout filters on this machine) and then
deletes the whole tree, ignored files included, while the container still
mounts it. Reproduced on an isolated instance: DELETE answered 200 and the
Docker case's workspace was gone.
That contradicts the invariant the PR itself documents in CLAUDE.md ("git
never runs ... at or inside a Docker workspace"). removeCaseWorktree now
refuses (400) a present worktree that is, sits inside, or holds a Docker
case workspace, before any git runs; the DELETE route passes the Docker
roots it already reads for the case check. A worktree whose folder is gone
is unaffected (git only drops its record there). Unit and route tests
cover both directions and an unrelated Docker workspace; docs updated.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
docs/releasing.md step 3 lists everything `npm run version-packages`
writes, and the COM commit stages explicit paths, so the new generated
file has to be named there: committed with the release, the version
check in test/whats-new.test.ts that fails a hand bump (with the two
commands that regenerate it), and that a release without bold lead-ins
ships an empty list and no toast.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The wiki said .codeman-uploads/ is the one path "a local agent, a container
and a remote host all see the same way", two sentences after saying uploads
are refused for remote (SSH) sessions. Only a local agent and a Docker case
(workspace bind-mounted at the same absolute path) share it, which is why the
route refuses remote sessions; say that.
The same paragraph said every image goes in after a re-encode on the device,
but _normalizeImageForUpload passes a GIF through untouched to keep its
frames.
CLAUDE.md and a test comment described the image fallback as behaving
"as before 1.36", a release that never existed (1.35.0 was followed by
1.40.0). It means the image path as it was before this change.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The skill only had a section inside "Driving Codeman From An Agent". It now
has its own page, docs/wiki/Codeman-Skill.md, built around three real runs:
- five Claude Code workers powering on in the tile grid (2026-10-15)
- eight worker tabs with lineage lines back to the lead (2026-10-15)
- a DeepSeek Harness worker and a Claude Code worker from one prompt
(2026-10-10)
plus every install route, prompts that work as written, a run start to
finish, which workers it can drive, what it will and will not do on its
own, the Codex notes and what is in the skill. The page says that the grid
recording put each worker on the grid as it started, since sessions an
agent starts do not join the grid by themselves.
The agent page keeps a short skill section (the heading anchor stays) and
links to the new page; the sidebar, Home, FAQ and Settings Reference link
to it too. The FAQ answer no longer says the skill is enabled per case only.
docs/media-assets.md records the new embeds.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Two live captures of a Claude Code lead driving the codeman skill, added to
the agent skill section of both READMEs:
- Step 2: `use codeman to start 5 claude workers, one per TODO item`, five
Claude Code workers power on as tiles in the grid (1120x630, 17 s, 10 MB).
- Step 3: the same prompt with 8 workers in the normal view, eight tabs
power on with lineage lines back to the lead, then a click into a live
worker (1120x630, 16 s, 8 MB).
Real sessions only, cut from the same raw takes as the promo videos; the
time-lapse stretches are labelled on screen. CRT beats play at 50 fps, the
busy time-lapses at 25 fps, one global palette, no lossy pass. Privacy OCR
on every second frame: clean. docs/media-assets.md lists both.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The dialog's own prompt glyph armed idle confirmation and the quiet dialog passed it, so a fresh case reported idle about 4 s in. An agent that waited for idle and then prompted typed into the dialog, and its Enter confirmed No, exit and killed the pane.
The scan must schedule its own next read rather than wait for PTY output, but a call inside the throttle was simply dropped. The dialog's own paint is often the last output a launching pane produces and lands inside that throttle, so the session sat on the dialog with no keystroke ever sent. A stopped session no longer scans, since the kill's own output kept it answering a dialog in a dead pane.
Claude Code's and Codex's selection dialogs ignore a bracketed paste, so
after the previous commit a pasted `3` + Enter confirmed the highlighted
option instead of option 3. sendInput() now types a single character with
`send-keys -l` as master did (submitsAsKeys()). One character cannot form
the burst Codex reads as a paste, so the Codex fix is unaffected.
The trailing-`;` escape moves into escapeTmuxTrailingSemicolon() and now
also covers every `send-keys -l` call in sendInput() and
sendInputToPane(); tmux 3.5a types `x;` for `send-keys -l 'x\;'`.
Docs: the @fileoverview lines and orchestrator-loop-architecture.md still
described `send-keys -l`; CLAUDE.md, architecture-invariants.md and
cron-guide.md name the single-character exception.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
sendInput() typed the text of a text+Enter pair with `send-keys -l` and
sent Enter 50 ms later. Codex detects an unmarked paste from a fast
character burst and folds an Enter inside that window into the paste as a
newline, so the prompt stays in the composer unsubmitted. Measured with
codex-cli 0.162.1 in a throwaway tmux pane: 1505 chars stuck 3/3 as
`[Pasted Content 1506 chars]`, a 98-char line stuck 1/4. SubmitVerifier
re-presses Enter for the short case, but it cannot match the long one: the
composer shows the placeholder instead of the prompt's head.
The text now goes in via set-buffer + `paste-buffer -p -d` (markers only
when the pane requested bracketed paste), followed by the separate Enter as
before. Same pane, same texts: 4/4 and 3/3 submitted. Each send gets its
own named buffer; a paste that fails (pane or server gone) deletes it,
since tmux never trims named buffers on its own.
Also escapes a trailing `;` in the text, which tmux treats as a command
separator (`send-keys -l 'x;'` typed `x`, a lone `;` typed nothing).
sendInputToPane() has no callers in src/ and is left as it was.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
While a codex dialog was up, the session re-read its screen every 2 s with
a synchronous `tmux capture-pane`, for as long as the dialog stayed up. That
read costs about 8 ms of blocked event loop (measured 2026-10-14), and an
approval can sit unanswered overnight: 1,800 execs an hour per waiting
session, measured as 300 in 10 quiet minutes in the unit test.
A dialog leaves the screen only through a repaint, and tmux sends every
repaint to the session's client as PTY output. So while the last reading
saw the dialog and nothing has been drawn since, it is still up and the
read is skipped; a safety-net read still runs every 30 s
(BLOCKED_QUIET_RECHECK_MS). The clear keeps its 2 to 4 s latency, because
the answer itself is output. Never skipped once a reading has missed the
dialog: tmux updates the pane before it sends the repaint, and the
confirming read must not wait for output that may already have arrived.
The session-state tests now change the fake screen the way a real pane
changes (with output), and two new tests pin the skip and the confirming
read (the second fails with the guard removed).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
With Codeman Agent Skill on (agentSkillEnabled), every session create
writes the skill into the folder the session runs in, so a session in a
worktree leaves an untracked .claude/skills/codeman/ (claude) or
.agents/skills/codeman/ (codex, gemini and the rest) behind. git then
refuses `git worktree remove` for that worktree forever, and an agent
running `git add -A` there would commit Codeman's skill into its branch
(reproduced: the worktree's status showed "?? .agents/" and
"?? .claude/").
A create now excludes <skills dir>/codeman/ next to the hooks file, for
every skills folder the registry names (capabilities.agentSkillDir,
read at call time by the route and passed in as data, so no CLI id is
branched on). Like the other lines it is only added when git does not
already ignore the path, and only to the repository's local
info/exclude.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
When a managed worktree's folder is deleted by hand (a user in a file
manager, an agent's rm -rf), git keeps its record and lists it as
prunable. Codeman then had no way out: the dialog showed the row as
"missing" with no action, DELETE answered "No worktree named ...", and
the name could never be used again (the branch still existed, and with
another branch git refused "a missing but already registered
worktree"). Reproduced on git 2.43; git's own `git worktree remove` on
the missing path drops the record with exit 0.
Removal (only removal, never a session start) now accepts a worktree
whose folder is gone when git lists it at exactly the managed path, as
prunable or locked, and no component on the way is a symlink or a file.
The live-session and lock refusals still apply. The dialog offers
Remove... (not Open) on such a row, with a note saying what it does.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Document what the two previous commits changed for users and for whoever
adds the field to another CLI:
- docs/cli-registry.md: the `blockedLine`/`blockedLines` fields, how codex's
pattern was measured, and the three rules any declaring CLI keeps (end on
chrome only the CLI draws, alert only; raise on one reading, clear on two;
hooks win).
- docs/architecture-invariants.md: a "Screen-read blocked dialogs (codex)"
entry, plus the wait-signal, idle-detection, watching and Approvals Inbox
entries it changes.
- docs/api-reference.md, docs/extending-codeman.md and the wiki (Agent CLIs,
Notifications and Approvals, Hooks, HTTP API, Driving Codeman From An
Agent): `blocked` now fires for codex, `stop` still does not, codex
approvals are alert-only cards answered in the terminal.
- CLAUDE.md: `stop` and `blocked` are no longer one rule, the config-regex
list gains `blockedLine`, and a short pointer that a codex dialog match is
only ever an alert.
- The codeman skill's signal table and verbs note, mirrored into
plugins/codeman by scripts/sync-plugin.mjs.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Documents the worktree endpoints and quick-start's worktree field in
docs/api-reference.md, adds a Git Worktrees page to the wiki (sidebar,
Home index, a pointer from Core Concepts where sessions sharing one
case folder is explained), and records the rules that keep the feature
safe in docs/architecture-invariants.md with a short CLAUDE.md pointer:
only the managed .claude/worktrees path is ever touched, git never runs
over a Docker workspace, removal is never forced and branch delete is
-d only, and sessions start through the existing create paths.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The Attach button, the Compose and paste-dialog pickers, terminal drop and the
clipboard now take documents beside images and videos: the office formats
pdf/docx/pptx/xlsx/zip and the text family txt/md/csv/tsv/json/log/yaml/yml/xml.
A document is admitted by its name's extension (the MIME a phone attaches to a
.md is anyone's guess), buffered under the same 50MB image cap, and judged on
its bytes by the same fail-closed sniffer: a magic-number signature for the
binary formats, UTF-8 with no NUL byte for text. It is saved under a sanitized
stem of its name, so Q3 report.pdf is findable as paste-<ts>-<hex>-Q3-report.pdf.
sh/py/js/html are refused by name with a clear 400. That is a scope choice, not
a security property: file-raw already serves non-media text inert, so this keeps
the server from storing what it would serve or an agent could run, and html and
svg are the ones deliberately kept out. One client classifier (_promptAttachKind)
now returns image, video or document, and the server's dispatch mirrors it: an
image MIME wins whatever the name says, a document extension takes the document
branch, and a foreign extension with no image MIME is refused only after the
image sniff fails, so nothing the image path accepted by its bytes is lost.
Only GIFs that a public page embeds stay in docs/images/: the five README
GIFs plus subagent-demo-20260724.gif, which the published "mission control"
article hotlinks from master. Seven GIFs nothing embeds leave the tree
(their masters are kept in the maintainer's local media library).
.gitignore now blocks *.mp4/*.webm/*.mov/*.m4v/*.mkv/*.avi/*.gif outside
docs/images/*.gif (and the promo branch's Remotion inputs), so a video can
only be committed with an explicit `git add -f`.
docs/media-assets.md records the rule: what is tracked and where it is
embedded, website media (pr/website/assets, deployed separately), release
clips on the design-assets branch, and the local library layout.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The root CLAUDE.md had grown to 202 KB, all of it loaded into every
session. This lands the split drafted on 2026-10-10 (it sat uncommitted
in the shared checkout through two releases), redone on top of today's
master so nothing that landed since is lost:
- src/web/CLAUDE.md: the frontend invariants (every src/web/public/ UI
subsystem, the module notes, the XLSX preview limits, the z-index
stack). Claude Code loads it when a file under src/web/ is read; the
root file tells sessions to Read it before editing src/web/public/.
Its link targets are relative to the file so they resolve on GitHub.
- docs/releasing.md: the COM procedure (now nine steps, with the MCP
registry publish), behind a pointer in the root COM section. The
Version line stays in the root file.
- Root CLAUDE.md (130 KB): everything else, plus the split's trims: the
Core Files table, the reference-only rows of the Additional Commands
table, Data Flow and the respawn presets, whose rules already live in
the root's other paragraphs (the "Read before touching a subsystem"
line keeps the table's doc pointers).
Every other paragraph of master's CLAUDE.md lands in exactly one of the
three files, checked line by line; the paragraphs master changed since
the draft (tile grid, OSC 52, prompt uploads, file-path links and the
HTML view, markdown preview, z-index, MCP server, agent CLI and others)
are in their current form. Both new files join CLAUDE.md in
.prettierignore. Four code comments and docs/architecture-invariants.md
now point at src/web/CLAUDE.md for the moved sections.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- isUserBoundShortcutEvent skips toggleSessionSidebar (it has its own gate) and an
entry re-captured onto its own default, so ^L still reaches the CLI.
- Re-enabling a shortcut and Reset run the duplicate check and refuse when the
chord was taken meanwhile; Ctrl/Shift+Enter and Ctrl/Cmd+V are reserved with
Alt+1-9, and the Alt-digit check no longer excludes Cmd.
- Alt+[ / Alt+] keep their Alt/Option+[ labels via displayBindings.
- Behavioural tests (vm harness) replace the source-string test.
- Docs: wiki Rebinding / Why-chords-behave-oddly, architecture-invariants note.
- Small: _shortcutActions indentation, stale Alt-block comment, typeof check
instead of Object.hasOwn, full-width parentheses in zh-CN.
The 800px GIF rendered the header stats strip (CPU, MEM, 5H/7D) at ~5px
text height. The 1600px source shown at width=800 stays sharp on high-DPI
screens. New filename so GitHub's image cache serves the new file.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
One stored grid per browser shared by every Codeman window, no cross-profile
notice (BroadcastChannel is per profile), and the user-activation window that
blocks a pop-out from a drag-out held too long.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
#604 makes `~/` links clickable and passes them through unchanged, since only
the server knows the session host's home. The html-view mint read `~/x.html`
as workspace-relative and answered 404, so the preview fell back to the
source view. It now expands `~/` against this host's home, as the attachment
route does, and refuses it in a Docker case (that `~` is the container's)
with the same message as the attachment and folder routes.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Conflicts resolved against #604, #606 and #601:
- constants.js: the rooted link pattern takes html-md's `markdown` and
`html?` with #606's m4v/ogv; #604's relative pattern gets the same list
(link-provider-regex pins the two equal); #604's findFilePathLinks /
folder helpers and html-md's rendersAsPage() are both kept, and
window.CodemanFilePaths exports all of them.
- terminal-ui.js: #604's resolved `target` (relative, ~/ and folder links)
now also goes through rendersAsPage(), so every link kind routes .html to
the page preview; .md routes there through FILE_PREVIEW_EXTENSIONS.
- CLAUDE.md, api-reference, architecture-invariants: both sides' text kept.
- test/folder-grid-ui.test.ts (#604) stubs rendersAsPage() like the other
panels-ui harnesses.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Conflicts resolved against #605 (and #602's test mock):
- CLAUDE.md Prompt uploads: #606's rewrite is kept and #605's bounded
workspace probe sentence follows the remote (SSH) refusal.
- test/routes/session-routes.test.ts: the remote-pane-history and
bounded-path-probe mocks are kept beside #606's _resetPasteRateBuckets
import, and both PRs' paste-image tests are kept.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Conflict resolved in test/routes/session-routes.test.ts: #602's
remote-pane-history mock and #605's bounded-path-probe mock are both kept.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Conflict resolved in docs/api-reference.md: #607's prompt cache section and
#528's tabGroupId section are both kept.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Conflict resolved in terminal-tile.js's @dependency header: #601's
SHELL_LOAD_BASE_QUERY/SHELL_LOAD_QUERY and #527's pageKeysForGesture and
app.tabAlerts are all listed.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A remote session's local pane hosts the remote tmux client in the alternate
screen, so its history_size is always 0. #583 read that as "nothing to load"
and hid the partial-history notice, but with #602 a full=1 load reads the real
scrollback from the remote tmux. The route now leaves the field out for remote
sessions, so their notice keeps the byte-based wording and its Load full
history button.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>