- Sagi: clicking the pet opens its chat window directly (PetChat + SagiInfo
status strip, Needs you, Mute / Clear alerts); SagiPanel removed.
- Chat view answers Claude's unnumbered folder-trust prompt (parseBareMenu).
- pty-attach: resize/write after a Windows attach exited, and node-pty's pipe
errors, no longer throw out of the WebSocket handler.
- restart-helper: the server started by an update logs to
data/agenthub-server.log instead of discarding its output.
- update-scheduler: default interval 1 h (DASHBOARD_UPDATE_CHECK_INTERVAL_MS and its 60 s floor kept);
a scheduled tick with no /ws client is skipped, and the next browser to connect gets one catch-up
check when the last one is stale (websocket.js onConnection). Manual check unchanged.
- db-retention.js: shared session purge (used by POST /api/settings/cleanup too), opt-in
AGENTHUB_RETENTION_DAYS applied by the hourly maintenance in 25-session transactions with yields
(max 5000/run), bounded incremental_vacuum when the freelist is large, and a manual Compact
(VACUUM in a worker, converting to auto_vacuum=INCREMENTAL).
- db.js: new databases are INCREMENTAL; an existing one up to 32 MB is converted at startup.
- GET/PUT /api/settings/retention, POST /api/settings/compact (confirm: true); Settings → Data →
Session cleanup gets the Automatic cleanup control and Compact now (en + vi).
- Session sync leaves a transcript alone while hooks feed its session live
(active, newest event a hook's, touched within DASHBOARD_SYNC_LIVE_HOOK_MS,
default 5 min) and catches it up once quiet; a hook-created session (which
importSession skips anyway) is only snapshotted, never parsed.
- Hook writer keeps a per-transcript mark (applied after commit): an
unchanged TranscriptCache result skips token/compaction/API-error/turn
writes, a grown one walks only the entries after the last one handled.
- Codex usage: one stamp query per pass instead of one row per journal;
between full passes (first + every 5 min) only the newest day folders and
journals written in the last hour are statted; fork parents resolved from
the table or a full walk.
- Cursor/Antigravity polls back off to 60 s after idle passes
(server/lib/backoff-poll.js); lane sync runs only while another dashboard
shares the data dir (checked every 30 s).
- Plugin bootstrap: a failed npm install, a Node older than 22.5 or a failed UI
build is recorded in runtime/last-failure.json; the next SessionStart prints
it once as a systemMessage naming the log and /agenthub-doctor (a different
failure is reported again; a successful bootstrap clears it). The foreground
pass checks the Node version itself and spawns no worker on an old Node.
- ReDoc: the standalone bundle (redoc 2.5.4, MIT, licence files kept) is
vendored under server/vendor/redoc/ and the `redoc` dependency dropped —
a runtime install (npm ci --omit=dev --ignore-scripts) goes 126 MB -> 45 MB.
vendor/ is excluded from the header audit and prettier.
- git missing from PATH: lane git actions answer 503 EGITMISSING with the
install command instead of a bare ENOENT.
- package.json engines: node >=22.5.0 (node:sqlite), matching MIN_NODE.
- Docs: INSTALL.md is the one install/setup guide (SETUP.md merged in and now a
pointer); no VS Code extension claim, one client-install hint, no
windows-build-tools, better-sqlite3 notes scoped to checkouts, new
"Plugin bootstrap never comes up" troubleshooting entry.
- ConversationView: an ended session (SessionDetail, SessionReplay pass
`ended`) polls its transcript every 60 s instead of 3 s and stops
rescanning sub-agents; new_event, reconnect and show still fetch at once.
- Workspace: GET /api/run follows run-moving WS messages (lane run
columns, session created/status change, runs_interrupted) with a 30 s
fallback, instead of a blind 5 s poll.
- StatusBar: session counts re-read only when a session's
status/waiting/archived state changes (60 s fallback); costs re-read at
most every 30 s while work is happening and every 2 min otherwise.
- Dashboard recent activity: 60 s safety poll (was 10 s) plus remote
import messages; WS still prepends new events.
- New lib/sessionChange.ts matcher with tests.
- Chat view: an attached image's path is pasted on its own after the text
(promptForPane). claude turns a paste that is only an image path into
[Image #n], but left a Windows path inside a paste of text as a plain path.
Other files and @-mentions stay in the text as before.
- Plugin bootstrap: depsHash covers only what npm installs (no release
version), so a version bump no longer reinstalls runtime deps; the client's
installed tree is kept while its manifests are unchanged (no npm ci per
update); the user-side build runs vite only (tsc -b cost ~25 s / ~900 MB);
clientBuild is recorded only after a build that did not fail, so a failed
one is retried; npm output goes to runtime/npm-install.log.
- Server: a port held by another program ends with a clear message and exit 1
instead of an uncaught 'error' stack trace.
- Client: the onboarding wizard is lazy and rendered only before onboarding;
usePrefersReducedMotion moved to hooks/ so PetSettings no longer pulls the
Sagi chat/pane stack into the entry chunk (884 KB -> 431 KB, gzip 268 -> 133 KB).
- Settings → Git → Your git identity: SSH keys are one tab per host kind
(GitHub · GitLab, AWS CodeCommit, More keys, Other hosts); opens on the
AWS tab when only an RSA key exists.
- Artifacts: a file type the sandboxed preview cannot show (Office, zip,
PDF) offers Download only, never a blank Preview.
- Artifacts search: `%`/`_`/`\` in a query match literally (LIKE ... ESCAPE).
- Skill frontmatter rewrite replaces a key with its continuation lines and
quotes values YAML could misread.
- Plugin marketplace.json is read with a 1 MB streaming cap.
- Artifact lists look each owner up once.
- Files: right-click a sidebar workspace (Open, Copy path) or home (Open,
Open Trash), a path crumb (Open, Download as zip, Paste into, Copy path),
a Trash row (Restore, Copy path, Delete forever), the Trash area (Refresh,
Empty Trash) and an admin's per-user Trash folder (Open, Empty Trash).
- Users: row menu (Edit + Open home in Files for an admin, Copy username/email).
- Artifacts: card menu repeating its buttons, plus Copy link for a page.
- Git identity: named SSH keys beside the default ones (id_<type>_<name>,
max 10, DELETE ?id=); SSH logins per alias (`ssh://<alias>/` →
`ssh://<user>@<host>/`, so several AWS CodeCommit accounts share a host),
each optionally tied to one key (`agenthub.<from>.sshKey`) — a clone of
that URL offers only that key and persists it. Terminal sshCommand follows
the keys. Settings → Git: "More SSH keys" + account name/key in the AWS and
other-host forms. Docs/API.md, OpenAPI updated.
/users becomes /admin (redirected), a tab shell over the existing Users view
and a new Server tab backed by GET /api/host (server/lib/host-stats.js):
hostname/OS/uptime, CPU and load, memory and swap, every real disk with
HDD/SSD, NVIDIA GPUs, and each user's live share from two /proc samples —
attributed by the member's Linux uid (S3) or, for host processes, by the
inherited AGENTHUB_LANE_ID's workspace owner. Read-only, staff-only (/host
in STAFF_ONLY_PREFIXES), comm names only. Members' tmux card moves to the
Server tab.
- Files → Trash: ONE sidebar entry. An admin's opens on a folder per user's
Trash (My Trash first, item counts from GET /api/homes/trash, an unreadable
one showing its error); a folder opens that user's Trash (path bar
Trash › user, Up back to the folders). An admin may restore/purge in
another user's Trash (audited); purging asks first. The merged "All users"
list is gone from the UI.
- A home's Trash is its user's whole recycle bin (home store + host store,
items tagged `store`).
- `agenthub server setup` installs one Linux user per account on Linux by
default (`--no-system` opts out); install-system messages drop `sudo`.
- Settings → Git: the author email suggests <username>@<AGENTHUB_EMAIL_DOMAIN>.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A member's tmux server keeps the version it started with until their last
pane closes, but the dashboard asked it with TMUX_BIN, the newest tmux: a
3.8 client on a 3.6 server spun it at 100% CPU (three members needed a
manual kill on 2026-10-15).
- /opt/agenthub/libexec/tmux-member (install-system, in sudoers): runs a
member's tmux call with the binary of THEIR running server
(/proc/<pid>/exe, found from the socket in /proc/net/unix), else
TMUX_BIN. It runs as the member and execs only a process they own.
sudoArgv uses it once installed (linux-accounts readConf), TMUX_BIN
until then.
- Users → Members' tmux (GET /api/users/tmux): each member server's version
beside the installed one, sessions, agents working. An admin restarts one
(POST /api/users/:id/tmux-restart) or every idle outdated one
(POST /api/users/tmux-restart-idle), with their password again, audited
per member; a server that will not stop answers 409 ETMUXSTUCK naming
its pid for root.
- server-s3-system.test.js: `delete` is a provision action since Delete
user, so the "unknown action" case now uses `purge`.
Operators: run `sudo agenthub server install-system` once.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A tmux 3.8 installed under a running 3.6 server left PATH's 3.8 client
asking the 3.6 server, which spun at 100% CPU; the dashboard's
synchronous `has-session` on it had no limit and froze every page, hook
and terminal for five minutes (14:07–14:12 on the shared server).
- Every call on our own server now has a 5 s limit and the member's
one-minute back-off (`host: tmux server not answering` meanwhile), so a
stuck server costs the event loop one timeout per minute, not one per
poll.
- Every call on a running server runs that server's own binary
(`/proc/<pid>/exe`, found from its listening socket in /proc — asking
tmux would be the very call that hangs), re-read every 10 s; PATH's
tmux only starts a server or answers `-V`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AWS CodeCommit logs an SSH key in by its IAM SSH key ID (APKA…), so a
plain `git clone ssh://git-codecommit.<region>.amazonaws.com/v1/repos/x`
was refused as the Linux account name. The account can now save an SSH
user per host — PUT/DELETE /api/me/git/ssh-user, listed as `sshUsers` —
written as `url."ssh://<user>@<host>/".insteadOf "ssh://<host>/"` in its
own ~/.gitconfig (as the member under S3), so the plain URL works in a
pane, in Clone and in the git bar. Only rules of exactly that shape are
listed or removed; any other insteadOf is the user's and left alone.
Settings → Git → Your git identity now shows the SSH keys one section
per kind of host, each with only its own numbered steps: GitHub · GitLab
· Gitea · Bitbucket (ED25519) and AWS CodeCommit (RSA: copy → upload in
IAM → paste the key ID and pick the region, then a "Ready" clone line),
plus a collapsed "Other SSH hosts (advanced)". The shared key-type
picker is gone: each section has its own Generate/Replace/Delete.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Stop (a tab's or pane's X, Close tab) now archives the session it held
(DELETE /api/run/:id?archive=1); the new Sleep (moon left of the X, and in
the tab, pane and session right-click menus) stops the pane but keeps the
session listed to resume later. Shared endRuns in client/src/lib/stopSession.ts.
- Git identity (#82): an account keeps an ED25519 AND an RSA key (AWS
CodeCommit takes only RSA), every ssh git offers both, and a member's
~/.gitconfig gets core.sshCommand so a git typed in a terminal uses them.
- Update dialog: Auto fix starts a Claude Code session on the install
folder with the failed update's error.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The chat renderer's paragraph collector never stopped at a table header,
so a table right after a line of text was shown as raw pipes. A table now
interrupts a paragraph as in GFM, and the divider accepts single dashes.
Closes#83
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Server tests on Windows no longer reach the user's real psmux: psmux
ignores TMUX_TMPDIR (and 3.3.x PSMUX_DATA_DIR), so quit.test.js's Quit and
the runner's kill-server ended every live lane pane — the pre-commit hook
included. scripts/test-server.js now takes tmux off the suites' PATH there.
- Wheel scrolling on Windows: psmux never turns mouse tracking on for its
client, so xterm.js never reported the wheel and a pane could not scroll.
A Windows attach is told {type:"wheel"} and the browser sends the SGR wheel
report itself; psmux scrolls or forwards it to the pane's app.
- tmux.upgradeAdvice(): the oldest tmux AgentHub asks for and how each
platform upgrades (psmux 3.4.0 -> winget upgrade marlocarlo.psmux; tmux 3.7
-> brew upgrade tmux / build the release on Linux). Used by the doctor,
GET /api/run/tmux ({available, version, upgrade}), `agenthub doctor`, and a
sticky toast on the Workspace page. Advice only: nothing installs tmux.
Committed with --no-verify (user's call): the pre-commit hook runs the full
backend suite, which has ~378 pre-existing failures on Windows (S3/Linux-only
tests: sudo, /proc, systemd, members). Every test touching this change passes:
pty-attach, tmux, run, plugin-doctor-tmux, TerminalView, Workspace, and the
client tests related to the changed files; tsc and the header audit are clean.
- Artifacts hub: upload a file from the computer; make a skill by uploading a
Markdown file, files, a folder or a .zip/.skill, or by writing it in the
dialog; add plugins by picking from the list a marketplace link answers
(POST /api/artifacts/plugin/inspect); Settings → AI tools → Artifacts Hub.
- Console tabs are combos of up to four split panes (ConsoleTabs, PaneGrid).
- Accounts: an own avatar (PUT/DELETE /api/me/avatar, raster only, ≤ 1 MB,
<data dir>/avatars/), shown with name and role at the sidebar's foot and on
the workspace owner groups (GET /api/users/:id/avatar, owner_avatar_at).
- Users page: per-user storage (GET /api/users/storage, measured in a worker)
and account-pool spend/tokens per account (server/lib/pool-usage.js).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A new workspace takes the default AI tool (Settings → AI Tools, the
account's own pick first); each session still picks its own AI on the
workspace home.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Artifacts (/artifacts): claude.ai pages sessions publish (captured from the
Artifact tool's hook), pinned workspace files, skills and plugins, each
kept as a snapshot; shared ones appear in a Hub and a skill or plugin
installs into the viewer's own account (server/lib/artifacts.js,
/api/artifacts, docs/plans/artifacts/).
- Workspace extra folders: clone one or more related repos beside the
workspace and add them in one step (POST /api/lanes/:id/sources/clone).
- A pane that ended by itself while tmux kept running is no longer offered
for resume (tmux.serverStartedAt in reconcileOrphans).
- Changes panel: a folder that is not a git repo opens on Files, and its
files open from there.
- Plus the parallel sessions' work in this tree: File Explorer button in the
panel header, user delete, RSA SSH keys, chat/terminal and pet fixes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- File Explorer (Files in the sidebar, /files; also from a workspace's Files
tab, portalled so no panel clips it), laid out like GNOME Files: places
(Home, workspaces, Trash), Back/Forward/Up, path bar, search, icon grid with
image thumbnails or list, labelled New/Upload, selection action bar, hidden
files behind Ctrl+H, right-click menus and the usual keys.
Make, rename, move, copy (within a workspace, between workspaces, home ↔
workspace), delete into a per-account trash restorable for 7 days, streamed
upload of files and whole folders (≤ 500 MB a batch, Replace / Keep both /
Skip on a taken name), download a file or a zip of anything.
server/lib/file-explorer.js, /api/lanes/:id/fs/*, /api/homes/:who/fs/*.
- The user's home: every dot entry at its top stays hidden and refused
(also via a symlink, download, zip or as a copy source); an admin may view
other users' homes read-only, audited.
- write-as learns move/copy (re-run `sudo agenthub server install-system`).
- Hardening: a write to a workspace re-checks its owner by the live role;
S3 keeps its server.conf if the file stops reading and a tmux call never
falls back to the host's server; the AI Proxy gateway marks what it relays
and the dashboard refuses it; a NUL in a pane's argv/env is refused.
- OpenAPI for the new routes (server/openapi-extra/files.js); docs (API,
SERVER-MODE, CLAUDE.md) updated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Gathered from the parallel sessions' uncommitted work on main, at the
owner's request (the session that wrote #78/#79/#80 was stopped mid-task):
- #78/#79/#80: Files tab upload/download (GET /:id/git/download, POST
/:id/git/upload, server/lib/lane-file-transfer.js) and a non-git tree
(git-diff.js walkFolder); pinned sessions (sessions.pinned_at, pin/unpin in
the session menu, pinned first); text size setting (lib/fontSize.ts,
Appearance).
- Git identity and clone over HTTPS/SSH (server/lib/git-identity.js,
routes/git-identity.js, GitIdentitySettings, AddLaneModal clone).
- pets.js FEATURED list and view().
Verified before commit: client `tsc -b` clean; related server tests 175/175
(lane-file-transfer, git-clone, api, server-s3-git, git-ops-merge,
server-s3-review2); related client tests 587/587. Committed with --no-verify:
the pre-commit full server suite has 9 failures that also fail on 0c2f498
(lane-sync merge: no git identity on this host; read-pool; resolveHost;
codex-usage 1 ms flake).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Fix: an errored session alerted on every update, and Clear alerts only
dropped it in memory, so its next update (or a reload) brought the alert
straight back. An error now alerts on the transition into error only;
cleared sessions are remembered (agenthub.pet.dismissedErrors) and stay
quiet until they recover and fail anew.
- Quips, greetings, notifications and Ask answers move to i18n (EN/VI);
Ask understands Vietnamese keywords and names the sessions it counts.
- The pet goes by the worn pet's name; click it in the panel to rename
(agenthub.pet.names, synced to the account).
- Bubbles name the session they are about, with an Open button (never a
resume); a burst of the same event coalesces into one count.
- Moments: a new session waves, a finish hops, a subagent peeks, a wait taps,
an error flinches — on Sagi, Codex sprites and still images. Idle fidgets,
a once-per-session greeting, a "Needs you" list, an amber waiting dot.
- Pat (heart button, Ask, or stroking the pet) reacts on the pet itself, so
it shows while the panel or chat is open.
- Panel drops Run Claude / Activity / Sessions / Errored.
- Ask hands off to a chat window (PetChat) on the default AI tool
(Claude/Codex): transcript as bubbles, follow-ups and CLI menus through an
off-screen attached terminal; no new server route.
Verified on HEAD + this diff in a clean worktree: tsc -b, the full client
suite (1334/1335; the one failure, ConversationView.follow, is flaky under
load and passes 3/3 alone) and server me-prefs.test.js.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
UI
- No animation runs forever: Sagi moods, the custom pet sprite, status dots
(pulse-dot, pulse-slow, ping) and the chat shimmer play a few cycles and
rest. An infinite animation kept the browser drawing 60 frames a second.
- useSagiBrain: frames that only move lastActivityAt by <1 s keep the old
state; the 1 s tick re-renders only when the mood changes.
- ConversationView and MessageList are memoized and PaneChat passes stable
callbacks: typing in the chat box no longer re-renders the conversation.
- The chat's 700 ms menu poll reads plain text first and scans the terminal
cell by cell (reusing one cell) only when a row could be a menu cursor row.
Server
- GET /sessions/:id/transcript?after=N skips lines <= N before JSON.parse.
- GET /sessions/:id/outline is cached until the session's events change.
- broadcastLane uses the cached tmux.liveSessions(); tmux.hasSession answers
"yes" from the fresh shared list instead of a synchronous spawn (50-150 ms
per psmux call on Windows, blocking terminal echo).
- pane-mode polls every 150 ms; writeHourly writes only changed hour buckets.
- /api/metrics: agenthub_event_loop_delay_seconds{quantile}.
Hooks
- PreToolUse/PostToolUse run with "async": true (settings installer,
plugin.json, S3 managed settings): Claude Code no longer waits a Node start
before and after every tool call.
Committed with --no-verify at the owner's request: the pre-commit full server
suite fails on 9 tests that fail identically on 0c2f498 (lane-sync merge: no
git identity on this host; read-pool; resolveHost; codex-usage 1 ms flake).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Workspace keeps panes of other workspaces and tabs mounted (display:none),
and every one of them kept following the live stream as if shown.
- useOnScreen (IntersectionObserver): ConversationView, the outline and the
700 ms menu scan skip while their pane is hidden and catch up once on show.
- A new_event refetches the tail at most every 1.5 s (leading + trailing).
- MessageList: WorkGroup/MessageRow/EditedFiles compare only their own blocks
and results, so a tail append no longer re-renders every row.
- A terminal under the chat is moved off the viewport with a transform, so
xterm pauses drawing without a resize.
- PaneChat and TerminalView are memoized; LaneConsolePane passes a stable onExit.
- RunningStep's clock and the outline poll skip unchanged or hidden updates.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Users page: one Edit user form (display name, email, role, active, a new or
generated password, workspaces given or taken back, sign out everywhere),
validated as a whole before anything is written (PATCH /api/users/:id,
GET /api/users/:id); users.display_name/email added migration-safe.
- Settings → Account for every signed-in user: profile, own password (the
current one required, this login kept), sign out other devices
(/api/me/account, /api/me/password, /api/me/sign-out-others; login cookie
only, never a pane token).
- Display names wherever a person is named (sidebar, workspace owner groups,
Users page and audit log); owner_display_name / reader_display additive.
- Users page: admins add and remove Claude/Codex pool accounts.
- Folder browser: an admin with their own Linux account opens in their home;
the "Server folder" tick opens the host's (never remembered).
- AI Proxy: "Config 9router" beside Add profile when 9router is installed,
opened on the dashboard's own host (GET /api/ai-proxies/9router).
- Terminal: a tmux selection reaches the clipboard over plain HTTP too
(writeClipboard's textarea fallback, focus handed back).
- Chat: a file the session touched outside the workspace previews
(GET /api/sessions/:id/file).
- install-system: `!requiretty` only when visudo accepts it (sudo-rs on
Ubuntu 25.10+ rejects the setting).
- openapi.yaml regenerated; docs (API, SERVER-MODE, LANES) updated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Decisions, environment quirks and pitfalls learned while working on AgentHub
(docs/claude-memory/, indexed by MEMORY.md). Notes holding personal account
details are left out.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Panes were keyed by slot alone, so slot 0 of the next workspace reused the
previous one's pane: every switch disposed its terminals and attached new
ones (a WebSocket each, the whole screen replayed). The live panes of the
last 4 workspaces left now stay mounted as hidden siblings in the same
grid, keyed by paneKey (lane x 10 + slot), so going back is instant.
Measured on 3 workspaces x 2-3 shell panes, switching back to one already
opened: script 210 -> 52 ms, main thread 370 -> 120 ms, long tasks
120 -> 0 ms, terminal re-attaches 2-3 -> 0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
xterm.js has no drop handling of its own, so dropped text was lost; the pane
now pastes it as a local terminal does, with a "Drop to paste" hint.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Folder browser (the Browse fallback for a remote browser): back/forward/up,
a clickable breadcrumb that becomes a path field (Ctrl+L), Places (Home,
the user's workspaces, recent picks), a filter, Name/Modified columns,
Show hidden and New folder. A click selects; a double-click or Enter
opens a folder or picks a file; Backspace goes up; typing jumps to a name.
- GET /api/lanes/browse: `hidden=1` (never the dot entries at the top of a
non-admin's own folder), each entry's `mtime`, the answer's `home`.
- POST /api/lanes/browse/mkdir: one plain folder name inside an existing
folder; a non-admin only in their own folder, none in server mode without
one; under S3 a member's folder is made as the member.
- scope.ownFolder falls back to server.conf's USERS_ROOT under S3, so a
settings file without AGENTHUB_USERS_ROOT no longer opens the host's home
to every developer.
- Passwords: any non-empty password is accepted (no 8-character minimum).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Chat: an AskUserQuestion is its own card (AskCard in MessageList.tsx), not
part of the collapsed work line — each question with the option picked or
the text typed, "declined" when refused. The transcript route passes the
answers from Claude Code's toolUseResult (askAnswers, beside diff).
- Chat: the activity panel keeps the user's open/close per session for the
tab, and opens by default only once the session has an output.
- Workspace home: the sent prompt's draft is dropped even though opening the
session unmounts the home.
- Terminal: Ctrl+V with text on the clipboard pastes the text; only an empty
clipboard still sends ^V.
- AGENTS.md / CLAUDE.md: run only the tests a change touches while iterating,
the full suite once before committing.
- A menu the CLI asks with (AskUserQuestion — one question or several,
multiSelect —, a permission or trust prompt, Codex's approval, a
first-start login menu) is read off the terminal under the chat
(`parsePaneMenu`/`readRunMenu`) and shown in the prompt box's place as a
card of buttons. A pick presses its digit (picks it, or ticks its box),
Claude's unnumbered Submit row is reached with the arrows and Enter, and
Cancel presses Esc. "Type something" opens a field in the card: its text
goes in by the arrows, Ctrl+U over anything already typed there, a
bracketed paste and Enter. That row presses no key — a second press of
its digit typed the digit into the CLI's field ("44444…"). Keys verified
on Claude Code 2.1.296 and Codex 0.161. AskUserQuestion fires no
Notification, so a menu on screen also counts as waiting (live line, tab
badge). Client only: no new route.
- #74: Esc before the model wrote anything puts the prompt back in Claude
Code's input box and writes no "[Request interrupted by user]" line, so
the transcript ended on the prompt and the chat read "Thinking…" for
15 min. The chat's Stop now ends the live line until a newer transcript
line arrives (matched by line, not by clock).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
macOS's own Vietnamese Telex types into xterm's textarea with no
composition events: a letter is an `insertText`, every later key of the
word an `insertReplacementText`, each keydown (keyCode 229) arriving after
the change. v2.7.4 forwarded the replacements, but a capital typed with
Shift still vanished — xterm drops any `input` that lands while a key is
held — and its 229 fallback could resend an edit. Replayed from a real
Chrome trace, "Abc xin chào" reached the pane as " x c".
lib/imeInput.ts now owns those edits: capture phase on xterm's element,
each one sent as DELs plus the new tail, the IME's input and 229 keydowns
hidden from xterm. Keys xterm sends from keypress (Space) and real
compositions (CJK) stay xterm's. Verified against xterm 5.5 in headless
Chrome: Telex → "Abc xin chào"; a plain keyboard sends the same bytes
as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- GET /api/settings/info for a developer: no DB path, no hooks file path,
and no transcript-cache keys — those were EVERY user's transcript paths
(their folders and session ids). GET /api/updates/status: no repo_root.
Test: server-mode-leaks.
- Also in this release (earlier commits): a member's missing workspace
folder is made as them at start; --allow-dangerously-skip-permissions only
for an account that accepted the bypass warning or a bypass run.
Full suites: server 2889/2889, client 1250/1250, tsc -b.
--allow-dangerously-skip-permissions (bypass in the pane's shift+tab cycle)
made Claude Code show its Bypass Permissions warning on any account that had
not accepted it yet — every new member's first session, which the Chat UI
cannot answer, though nobody asked for bypass. Now passed only when the run
starts in bypassPermissions (asking is consent to see it) or the account's
user settings already hold skipDangerousModePermissionPrompt (pty-run
bypassAccepted; a member's read owner-checked from their home). The host,
which accepted long ago, keeps the flag. Test: pty-run.
v2.7.3's ENOCWD left a new member no web path to a first project: their
home is no workspace (EFOLDER) and a not-yet-existing folder could not
start. run-as.makeMemberFolder: mkdir -p through write-as, AS the member,
only inside their own home (never the home itself, never a host folder,
never for a member with no account). Test: server-s3-lanes.
- Changes (#72): a file git reports `MM` whose working copy equals HEAD again
(a staged change since undone on disk) is no longer listed — JetBrains'
GitChangesCollector drops it the same way. Mode-only changes stay listed.
statusCounts (the dirty-tree safety checks) is unchanged.
- Chat (#73): Claude Code runs no hook before a folder is trusted, so a new
pane's session has no row; the chat now says the session has not started,
offers Open terminal, and asks before typing a message or /model //effort
into the pane (an Enter would pick the trust prompt's "No, exit").
- Terminal: Safari + macOS's own Vietnamese Telex replaces the whole word on
each key (insertReplacementText), which xterm.js ignores — only each word's
first letter reached the pane. The edit is now sent as DELs + the new tail.
- Also: Ctrl+V pastes a screenshot into the terminal as a file path; the
folder browser fallback lists files for a file field (`files=1`); the macOS
native picker opens in front of the browser; a hidden tab is marked while a
chat waits or once a turn ended; chat live line shows running calls, turn
time and tokens, and "Done in …".