Repository navigation
Releases
Codeman 1.51.0
Thanks
- @Randalix for auto-compact and auto-clear that see the whole context (#777), and for the measurements in #585 that showed why they did not.
- @JDProfresh for the report and the change that lets the File Viewer edit
.envfiles (#796, #797). - @aakhter for the Copy Markdown button in the response viewer (#810).
- @DodgyBadger for the File Viewer button that follows its setting on a phone (#759, #809).
- @timkjr for omp tool approvals that raise an alert (#798).
- @irisitymichaelgrundberg for finding why Firefox still pasted twice (#799).
What's new
Local models: a library, more models, and the coding agent you choose (#803, #804, #806, #807, #808)
Run a local model (on a Mac) now lists every model that fits instead of five, with two new ones: Muse Glimmer 30B, the first of its class a 32 GB Mac can hold, and Ornith 1.0 9B, the first model that fits a 16 GB Mac. Installed models form a library: each shows its size on disk, and you can add another, switch between them or delete one. You pick the coding agent when you start a session (OpenCode, Claude Code, Pi or DeepSeek Harness), and a missing one installs from the same screen. The codeman skill starts a local worker with the agent you name (spawn_worker <name> local:pi), and the wiki has a new Local Models page. Still experimental.
Mac app: With the Lid Closed no longer asks for a password
Codeman > Keep This Mac Awake > With the Lid Closed is a plain switch now. 1.50.1 asked for your administrator password and installed a small root helper for it. The app now does what LogoLight does: it turns off macOS's sleep-on-lid-close itself while your agents work, and turns it back on when they stop, when the app quits or crashes, and on battery. If you ticked With the Lid Closed in 1.50.1, it keeps working after the update, and the old helper does nothing any more. Remove it with Codeman > Keep This Mac Awake > Remove the Old Lid Helper… (that asks for your password one last time). If the Mac ever sleeps under the lid anyway, the status line in the same menu says until when.
Auto-compact and auto-clear see the whole context (#777)
Both compared a token counter that never counted the cached part of a conversation, so on a long session they fired far too late or not at all. For Claude sessions they now read the context size Claude Code reports, and a threshold can go up to the model's window (1M with extended context). Behaviour change: a session with auto-compact or auto-clear on fires earlier than it did, because 110k and 140k now mean the real context. Other CLIs, remote and Docker sessions keep the old counter.
jcode as a run mode (#650)
Codeman can now start jcode sessions from the Run menu, the phone overview and the API (mode: "jcode"), locally, over SSH and in Docker cases. jcode runs every session's tools in one shared background daemon, so closing a jcode tab never stops that daemon, its sessions get no Codeman agent skill, and a jcode worker's answer is read from its terminal; see docs/jcode-integration.md.
The File Viewer edits .env files (#796, #797)
A workspace .env, .env.local or prod.env opened in the preview but could never be edited. It now gets the pencil like any config file, and a save keeps the file's mode and group. Other credential files (.npmrc, credentials.json, anything under .ssh/) and Codeman's own ~/.codeman/.env stay read-only there, and downloads and attachments still refuse dotenv files.
Response viewer: a Copy Markdown button (#810)
Last Response has a Copy Markdown button. It copies the raw source of the newest answer, every part of its turn, so headings, lists and code fences survive a paste. Tool and status blocks are left out, and the full view (More) copies the same answer.
Fixes
- Firefox no longer pastes twice on Ctrl+V (#799). Firefox sent a second paste for the same key press, and some of the time it reached the terminal.
- An omp pane that asks for a tool approval alerts (#798). It raised no tab alert, no notification and no Approvals Inbox item. Behaviour change: Codeman writes a small hook file into
.claude/hooks/pre/of an omp session's folder. - Phone: the File Viewer header button follows its setting (#759, #809). Turning on File Viewer under App Settings > Header & Panels did nothing on a phone. The button now shows there once you turn it on, with a full-size touch target, and stays off until you do. Behaviour change: a desktop window or an iPad split view narrower than 600px shows the button too, where it was hidden before.
- Local model: the "still using this model" refusal names every session (#804). With a session open that an agent had started, Stop and Remove answered "Sessions are still using this model: . Close them first." Such a session has no name of its own, so the sentence now uses the name its tab shows.
- Skill: two workers in one folder keep their own answers (#807). On a Mac, where Claude Code runs zsh, two
sendmarkcalls started in the same second named the same answer file, and one worker's written answer replaced the other's. Workers in folders of their own were not affected.
Also in this release
Fixes applied while landing. Auto-compact and auto-clear decide again at the moment the command goes out, so a /clear is not sent into a conversation Claude Code just compacted itself, into a session paused on a usage limit, or after you switched the option off (#777). The File Viewer cannot reach Codeman's own .env by another spelling on a case-insensitive disk (#797). An omp alert stays up until omp says its dialog closed (#798). The test gate checks again that the File Viewer button is off on a phone nobody turned it on for (#809). The Copy Markdown button is named by the words on it, so voice control can find it (#810).
Docs and tests. The experimental API list names the new local model routes, the wiki's Local Models page walks from install to cloud plus local, and the wiki says where the File Viewer button is on a phone and what Copy Markdown copies.
Full Changelog: https://github.com/Ark0N/Codeman/compare/codeman@1.50.1...codeman@1.51.0
Codeman 1.50.1
Thanks
- @opticon454 for syncing case options and the picked case across devices, over five review rounds (#732).
- @ludovicfourrage for dictation that survives a thinking pause and the Android dictation fixes, over three review rounds (#705).
- @johoja12 for the log viewer reconnect fix (#720).
- @shenlvkang-collab for the image zoom (#608) and the Files panel delete button (#529), both carried forward in #791 and #792, and for the foldable phone report (#702).
What's new
A MacBook keeps working with the lid closed (#795)
The Codeman app for Mac has a new menu, Codeman > Keep This Mac Awake: Off, While Agents Work (and 5 minutes after the last one stops) or Always. It only acts for a Codeman running on this Mac, and pauses on battery unless you untick Only When Plugged In. On a MacBook, With the Lid Closed… keeps a closed Mac awake on its power adapter. It asks for your administrator password once and installs a small helper; unticking it removes the helper. Behaviour change: while it keeps watch for a Codeman on this Mac, closing the Codeman window hides the app instead of quitting it, so the Mac stays awake; click the Dock icon to bring it back, and quit with Cmd+Q (#800). With no server open, or one on another machine, closing the window still quits.
The lid logo breathes while agents work (#794)
The Apple logo blink from 1.50.0 now has one switch, View > Blink Apple Logo. It breathes while agents work, blinks for a yellow tab and flashes for a red one: the more it moves, the more it needs you. It now moves on the logo's own hardware fades, so a blink no longer writes a system setting. Styles you picked in 1.50.0 are kept.
The logo keeps blinking with the lid closed (#801)
While the Mac stays awake behind a closed lid on its power adapter (Keep This Mac Awake > With the Lid Closed…, or an external display), the logo goes on showing your agents, and the keyboard stays dark. macOS keeps the logo dark under a closed lid, so the app tells the logo the lid is open, the way LogoLight 1.3.1 does. A line under View > Apple Logo Blink Styles says what the closed lid did last: blinking, or why not. On battery nothing changes: the Mac sleeps when you close it.
Codeman and LogoLight take turns on the logo (#802)
With LogoLight 1.3 or later running, LogoLight steps aside while Codeman shows its agents on the logo, and takes the logo back afterwards. Until now Codeman left the logo alone whenever LogoLight ran. An older LogoLight still keeps the logo, and Codeman tells you to update it when you turn the switch on.
Dictation survives a thinking pause (#705)
A new Voice setting, Stop after silence, sets how long a pause may last before dictation stops: the provider's default, 3, 6, 15 or 30 seconds, or Manual. Claude dictation keeps going from one sentence to the next until you press Stop, and keeps your last words. On Chrome for Android, words are no longer repeated or lost at the end. Behaviour change: on iOS Safari dictation no longer stops after 750 ms without new words; it stops at the silence deadline like everywhere else.
Sync cases across devices (#732)
A new setting, off by default, keeps each case's Agent Teams and Opus 1M options on the server instead of in each browser. When you come back to a tab, the case picker follows the case you last picked on another device.
Delete a file from the Files panel (#792)
File rows in the Files panel, tree and search results, have a delete button that asks first. Symbolic links, .git, sensitive files and remote or adopted sessions are refused.
Zoom the path picker's image preview (#791)
Pinch and drag on a phone, the mouse wheel or a trackpad on a desktop, double-click for 2x, or the zoom buttons. A small image now shows at its own size instead of stretched.
Fixes
- The phone overview appears on a fold (#790). Folding a phone, or narrowing a window below 600px, left the welcome screen up when the page had loaded wide. Refs #702.
- The log viewer stops reconnecting after a startup error (#720). A refused path, a missing or too large file, the stream limit or a failed tail made the floating log viewer reconnect every few seconds.
- The local model install view no longer flashes Paused at the end. A view read while the install job finished could show the job as paused.
Also in this release
Fixes applied while landing. #720 keeps the browser's own retry after a network error before the stream connects. The Mac app's window-close change (#800) came from checking #795 against how people quit the app. #705: the green Send button now stays up for the words saved when dictation is cut off by a reconnect, and the API reference says what a voice transcript frame holds.
Docs and tests. Both READMEs have a Download for Mac button at the top. The Mac app's code was reorganised into smaller modules (#789) with no change in behaviour.
Full Changelog: https://github.com/Ark0N/Codeman/compare/codeman@1.50.0...codeman@1.50.1
Codeman 1.50.0
Thanks
- @irisitymichaelgrundberg for the Files panel following an agent into a worktree outside the session's folder, and for the rules that keep that second folder narrow (#780).
- @Randalix for keeping two tests independent of the host's locale and git ignore file (#776).
What's new
Codeman for Mac (#763)
A small native macOS app opens Codeman in its own window: it opens the Codeman running on this Mac, starts it when it is stopped, installs it when it is missing, or connects to Codeman on another machine, with that password kept in the Keychain. It is one universal app for Apple Silicon and Intel on macOS 11.3 or later, and a client of the web UI like a browser tab, so the server and the API do not change for it. Every release from this one carries it as Codeman.dmg, signed with a Developer ID and notarized, so it opens after macOS's usual question about a downloaded app (1.50.0's copy). The app keeps its own version (0.1.0) and does not update itself yet.
Your MacBook's Apple logo blinks with your agents (#781)
On a MacBook Pro with a PROLED XDR display, whose lid logo lights up, View > Blink Apple Logo gives each agent state its own rhythm: one for While Working, one for Waiting for You (a yellow tab) and one for Needs Permission (a red tab), each picked from Calm, Slow, Wink, Heartbeat, Fast and Alarm. Set Heartbeat for work, Wink for a finished turn and Alarm (three sharp flashes, then a rest) for a permission dialog, and the lid tells you from across the room which one it is. All three are off until you choose one, the menu shows only on a Mac with that logo, and no style flashes more than three times a second. It uses a private macOS setting, so a macOS update can take the menu away.
Install from the app, with no Terminal and no password (#773)
On a Mac without Codeman, the app runs the installer's no-admin route in its own window, shows the steps as a checklist and opens Codeman once it answers. If the Mac has no coding agent it offers one, and Add a coding agent (also in the app menu) adds one later without touching a running Codeman. The This Mac tab now lists every Codeman of this user already running on the Mac. The install needs macOS 15 or a tmux that is already there; on an older Mac the app offers Terminal instead. For this, install.sh gained preflight, agent <id>, --ai-cli and --progress.
The Files panel follows a worktree outside the session's folder (#780)
Since 1.49.0 the panel follows an agent into a worktree inside the session's folder. It now also follows one of the same repository beside it, such as git worktree add ../feature, when the session's own repository vouches for it, and files there preview, edit and open from terminal links like workspace files. It follows none while attachment workspace confinement is on, and none at or around a blocked or sensitive folder, in a Docker case workspace, at the home folder or above, or outside the owner's space in multi-user mode. The API stays compatible: liveWorktree and root=live keep their 1.49.0 meaning, and an outside worktree comes as the new outsideWorktree field, listed by root=live-any with absolute paths.
A coding model that runs on your Mac (#784, experimental)
On an Apple silicon Mac, Run a local model on the welcome screen opens a window that shows which local coding model fits the machine and with which agent, installs a pinned Ollama runtime and the model, checks it, and ends on an agent session that runs on it through a Custom Model Endpoint. The catalogue covers every Apple silicon memory size from 8 to 512 GB, and every model carries memory figures of its own: a 9B coding model (labelled limited) from 18 GB, Qwen3.8 27B or Qwen3.6 35B-A3B from 36 GB, Ornith 1.5 122B from 128 GB, while 8 and 16 GB get a plain sentence on why nothing fits. Recommended appears only for a pairing run on a Mac like yours, so far Qwen3.6 35B-A3B with OpenCode on an M5 Pro with 48 GB; every other figure is computed from the model's architecture and shown as an estimate. No account or API key is needed, and the session's prompts go to the model on this Mac rather than a cloud provider. On any other machine nothing is offered, and in multi-user mode only an admin can install. A weekly check in CI compares every catalogue model and the pinned runtime with what a Mac would download and opens one issue when something moved. The routes and their payloads may change in any release; the guide is docs/local-models.md.
Claude in the cloud, a model on your Mac (#784, experimental)
The codeman skill can hand work to that local model: local_model says what is installed and whether it runs, spawn_worker <name> local starts a worker on it (and the runtime, when it is stopped), and sendmark gives the worker a task and reads back the answer it writes. A Claude Code session plans and reviews while the Mac does the bulk: summaries, first drafts, files that should stay on the machine.
Ralph starts from Session Options (#783)
The start screen no longer has a Start Ralph Loop button. Behaviour change: start a Ralph loop from Session Options, Ralph / Todo. The wizard that button opened can no longer be reached.
The Codeman agent skill is on by default (#787)
New sessions get the skill where their CLI looks for skills (.claude/skills/codeman/ for Claude Code, .agents/skills/codeman/ for Codex, Gemini CLI, OpenCode, Antigravity, Grok, DeepSeek and OMP; none for Pi, GitHub Copilot or a plain shell), so an agent can start and drive workers without an install step. The copy ignores itself in git (a .gitignore of * inside it, written once and never overwritten), so it never shows up as a new file in your repository, and a symlinked reference/ folder inside it is refused. Behaviour change: every App Settings save on 1.49.0 or earlier stored this switch as off whether or not you touched it, so the first start of 1.50.0 switches a stored off on, once per data directory, and the startup log says when it did. Turn it off under App Settings, Agents & CLIs, All agent CLIs, Codeman Agent Skill: an off set after that first start stays off. Reload any tab left open from before the upgrade before you save App Settings there. Turning it off removes no copy already written; codeman skill uninstall --case <name> does.
Fixes
- No developer tools window on a Mac without Xcode (#779). There
/usr/bin/gitis Apple's placeholder, and the server ran it on the first page load, so a 1.49.0 no-admin install opened macOS's "install the command line developer tools" window right after it finished, and again after every server start. Every git the server starts now checks first and treats that placeholder as no git, and installing the tools later needs no restart. - A new agent shows up as soon as the installer adds it (#778). A running Codeman remembered a missing CLI for up to 5 minutes, so Run still said it was not installed after
install.sh agent <id>or the app had added it. The installer now touches~/.codeman/cli-installed, and the server looks again when that file changes. - The approvals list leaves a brand-new dialog alone (#782). In a dialog's first 3 seconds, before Claude Code has drawn it,
GET /api/approvalscould resolve it, which cleared its red tab on every device and left the push notification's Approve button with nothing to answer. The list now waits as long as the inbox does. - Custom model endpoints survive concurrent writes. The endpoint routes and the 5-minute discovery sweep wrote
custom-model-hosts.jsonthrough one shared temp file, so two at once could tear it or drop a record. Every write is serialized now, and a file that does not parse is refused with 409 instead of replaced. Behaviour change: the endpoint idlocal-ollamais reserved for the model Codeman runs on this Mac. - Clearing a custom endpoint relaunches on the session's own model. A selection no longer writes its launch model into the session's stored CLI config, so a cleared session starts on the model it was created with, not on the endpoint's model id against the CLI's own backend. Only API callers could reach this.
Also in this release
Fixes applied while landing. An adopted session never follows a worktree outside its folder, like a remote or Docker session (#780). The worktree test also keeps the system gitconfig away from the code under test (#776).
The Release workflow now builds, signs, notarizes and attaches Codeman.dmg (.github/workflows/desktop-dmg.yml, #785), publishes each version to the official MCP registry (io.github.Ark0N/codeman) with GitHub's OIDC token, and rebuilds the GitHub release page from this changelog. Pull requests that touch packages/desktop run cargo fmt, clippy and cargo test on macOS.
Docs and tests. The README, the Chinese README and the wiki's Installation page gained a section on the Mac app (#786), the Autonomous Loops page no longer points at the removed wizard, and docs/local-models.md covers the local model install. Two tests no longer depend on the host's locale or git ignore file (#776).
Full Changelog: https://github.com/Ark0N/Codeman/compare/codeman@1.49.0...codeman@1.50.0
Codeman 1.49.0
Thanks
- @dignfei for letting Codeman open the tmux sessions you started by hand, on this machine, in a container or over ssh (#510).
- @Randalix for the remote launch fix (#770) and the pi wheel fix (#771), both from their own reports (#760, #758), and for Edit history on remote sessions (#766).
- @opticon454 for the New folder button in Create New's picker (#761) and for Clone Repo's parent folder (#774).
- @shenlvkang-collab for a Files panel scan that no longer lets one folder use up the limit (#614).
- @irisitymichaelgrundberg for reporting that the Files panel stayed on the main checkout (#765), and for catching a
.gitopen race in the fix. - @maminmsh for reporting right-to-left text in the Response Viewer (#715).
What's new
Open the tmux sessions you started yourself (#510)
Tmux sessions you started by hand now show up on the home screen under Opened outside Codeman, and one click opens one as a tab, on this machine, in a container or over ssh. Closing the tab only detaches, so the session keeps running. Codeman did not start it, so respawn, Ralph, auto-clear, one-shot prompts and prompt uploads are refused for it, and when the session ends the tab lets go of it. Adoption is admin-only in multi-user mode. The scan runs only while the home screen is in a visible tab. Close adopted tabs before going back to 1.48.0 or older: an older server does not know a tab is adopted and drops all of those guards.
Install without administrator rights (#768)
The installer can now finish on an account without admin rights: Node.js and tmux go in your home folder, the source comes as an archive when no working git is available, and --no-admin forces this route. An install without git updates by re-running the install line, and Linux still needs make, a C++ compiler and python3.
Docker Compose starts in two commands (#573)
bash docker/Start-Codeman.sh asks three questions, writes docker/.env, starts the container and prints the URL once Codeman answers. It now waits for the server and exits 1 if it does not come up (--no-wait skips that). Behaviour change: Start-Codeman.sh and Update-Codeman.sh refuse to run while CODEMAN_PASSWORD is still the example value changeme, so a deployment on that value has to set a real password before its next restart.
Codex sessions can drive other sessions (#753)
A new opt-in setting, Allow network access (App Settings, Codex, off by default), starts new local Codex sessions with sandbox_workspace_write.network_access=true, so the Codeman skill's calls reach this server. It has a real cost: commands in Codex's sandbox can then call Codeman's API, which can start a session outside the sandbox with no approval prompt, even with a password set, so the sandbox no longer contains a prompt-injected command. It is forced off without the privileged-commands grant in multi-user mode, scheduled jobs do not use it, and it does not change Codex's sandbox mode. A local Codex 0.162 or later also starts with --no-daemon, so a shared background server no longer stops a launch on an "incompatible feature settings" dialog, and commands inside Codex see their own session's CODEMAN_* variables. Version gates in the CLI registry are now measured against each CLI's own version.
Persian, Arabic and Hebrew read right to left (#715)
In the Response Viewer and the File Viewer's markdown view, each paragraph, heading, list, quote and table takes its direction from its own first letter, so a right-to-left answer lines up on the right while an English paragraph beside it stays left to right. Code blocks, inline code and the file paths the viewer links on its own stay left to right and no longer decide a sentence's direction. The phone's Compose dialog does the same. The terminal pane is unchanged: xterm.js has no right-to-left support yet (xtermjs/xterm.js#701).
Edit history for remote sessions (#766)
The Edit history panel now works for remote (SSH) Claude sessions. It reads transcripts over ssh only while the panel is open, keeps the diffs in the same private local store and never wakes a sleeping host. An unreachable host shows the saved edits with the ssh error, and images preview on click rather than as thumbnails.
The Files panel follows the agent into a git worktree (#772, #765)
When an agent moves into a worktree part way through a session, the panel lists that worktree, follows the agent back out and shows a strip that names it, with a button to switch to the session's folder. Only a worktree inside the session's folder is followed, and file access stays confined to that folder.
One big folder no longer hides the rest (#614)
The Files panel and its search now walk folders in a per-directory round-robin, so one large folder no longer uses up the 5,000-entry limit, and search results come back shallow-first. One listing stops opening folders after reading 250,000 entries. A folder the scan stopped short of, or one that did not answer, no longer looks empty: GET /api/sessions/:id/files marks it incomplete: true (additive), sets truncated, and the panel shows a dim "Not fully scanned" row.
Fixes
- Remote sessions start when the remote home differs (#770, #760). New sessions no longer die with
tmux: command not found(exit 127). The launch line reached the local shell in double quotes, so$HOMEand$PATHexpanded on the Codeman host before ssh ran. Launches now reach the far end verbatim, and a remote session starts in the remote user's own shell. Behaviour changes: in a per-hostcommands.*override,$now expands on the far end; a bare$VARin a DockerextraCreateArgs/extraExecArgsvalue or a remote host'sextraSshOptionsis passed literally, so write the value out.commands.ompandcommands.copilotare accepted now, like every other mode. A csh or tcsh login shell starts without-i -l, which tcsh refuses, so it reads.tcshrcand not.login. - Remote file reads work on fish, csh and tcsh hosts. The Files panel, previews and Edit history failed on those login shells, because their reads were parsed by the login shell before
shsaw them. Every remote file read now crosses it as one word of text. This also ends a case where a file name holding shell syntax ran as a command on those hosts, as the same ssh user the agent runs as. - The pi mouse wheel survives a tab switch or reload (#771, #758). pi now takes the same path as Copilot: the server strips the mouse enables and remembers them, and the wheel is forwarded from that record, on the primary pane, tiles, split Pane B and phones. A drag in fullscreen pi now selects text in the browser instead of using pi's own selection, and with Wheel Scrolls Local History on the wheel does nothing there. A pi in
tuiMode: regularis unaffected. - Clone Repo's custom folder is a parent now (#774). The repository lands in
<folder>/<case name>, as it does with Create New, and the preview shows the joined path. Behaviour change: 1.48.0 cloned straight into the folder you picked, so a name the case-name rule refuses, such as/mnt/my.repo, can no longer be reached from the tab.pathonPOST /api/cases/clonestays the exact target for scripts and mount points. - New folder in the Create New and Clone Repo pickers (#761). You can make the parent folder without leaving the dialog. Asking for one directly in the cases folder is refused, and the refusal points at the right tab.
- Linked cases hold up under concurrent writes (#764). Every write to
linked-cases.jsonis serialized, so two requests can no longer claim one name or lose each other's entry, and a damaged file is refused with a clear error instead of being overwritten, which used to unlink every other case. A local case's rename racing a new link is not covered. - A session keeps its own home and account variables (#767). A session that set
CLAUDE_CONFIG_DIR,DSH_HOMEor the like keeps it when a custom endpoint selection is cleared or switched, also after a Codeman restart. With its ownCLAUDE_CONFIG_DIRit keeps both its conversation and its account.
Also in this release
Fixes applied while landing. An adopted session never falls back to a direct terminal when its wrapper cannot start, which would have run a local agent in /tmp (#510). Output from a foreign pane, container or ssh host is parsed in linear time, so it cannot stall the server (#510). A .git swapped for a FIFO or a symlink is refused at open (#772). A folder listing that does not answer is flagged instead of shown as empty (#614).
Docs and tests. Adoption, the no-admin install, the Compose first run and the new remote shell rows in the guides, wiki and READMEs, new zh-CN strings for the Allow network access warning, and the Playwright bump to 1.64.1 with the browser suite unpinned.
Full Changelog: https://github.com/Ark0N/Codeman/compare/codeman@1.48.0...codeman@1.49.0
codeman@1.48.0
Minor Changes
-
4960bee: ### Thanks
- @opticon454 for a big round: the two-way Discord bridge (#741), custom endpoint context limits, Codex and DeepSeek model selection and the model picker (#752, #755, #757), Clone Repo into a custom folder (#744), the New folder button (#745), and the wrapped
.conffile links (#735). - @Randalix for the Edit history panel (#693).
- @aakhter for relative links that follow your
cd(#740). - @JDProfresh for settings saves that say when they failed (#736), a visible press on the phone keys (#737), and two test harness fixes (#738, #742).
- @timkjr for a tab strip that keeps its shape whichever tab is selected (#748).
- @Hugo-DDT for the parallel fix to the same wrapped file link bug (#734), whose
Bash(test rows landed with the guard below.
Talk to your agents from Discord (#741). An opt-in two-way bridge gives each tab its own thread: alerts go out, and a reply from an allowlisted account is typed into that tab. An agent that needs a person can run
codeman notify "<message>" [--urgent] [--file <path>], and files travel both ways. Claude learns the command through its system prompt. Setup is indocs/discord-bridge.md.Edit history panel (#693). An opt-in header button (per device, off by default, never on phones) shows every Edit and Write a local Claude session made, subagents included, with each diff inline, plus the images a Bash call produced. It reads transcripts only when the panel asks, and keeps its 0600 per-session store only as long as the session's record.
Custom endpoints go further (#752, #755, #757). OpenCode and Codex now receive the endpoint's context window, Codex launches on the model you picked, and endpoint discovery reads each model's context size from
/v1/models, with a per-endpoint default for gateways that state none. DeepSeek Harness moves to a per-session home with a generated patch, so it runs the exact model you chose. The model picker gained a search box and marks the model one of your running sessions is using on an endpoint that cannot report it, or says plainly that nothing is known.Clone into a custom folder, and make a folder from the picker (#744, #745). Clone Repo can clone straight into a folder you pick, empty or not yet created, and registers it as a linked case. The path picker in Link Existing gained a New folder button, so a brand-new project folder no longer means a trip to a shell.
Relative links follow your
cd(#740). A relative path printed in the terminal now resolves against the directory the session's pane is in, not the folder the session started in. Only the base changes: what can be opened is the same as before. Session state carries it as the new optionalpaneCwdfield.Fixes.
- File links keep the whole name (#735).
.conffiles and parenthesised paths with spaces link as one file in the terminal and the Response Viewer, and a path wrapped over several rows stays clickable from every row. An ambiguous hard wrap tries the unspaced name first and looks up the spaced one only after a 404, on click, never on hover. - A failed settings save says so (#736). Any write the server did not store now reports the reason and keeps App Settings open, where only two kinds of refusal did before. Run mode and respawn preset writes warn too, and a failed tunnel stop no longer claims the tunnel stopped.
- Phone keys show a press (#737). Every toolbar button, the voice, attach and settings icons and the accessory keys now react on all seven skins.
- The L-shaped tab strip holds its shape (#748). A too-wide first tab is trimmed to the room beside the toolbar, so the layout no longer changes with the selected tab.
- Credential files stay out of the attachment routes.
webhook.json,custom-model-hosts.json, the generated custom-model configs and everything underbackups/could still be read through the attachment routes, which in multi-user mode means by any user. A config backup was the widest gap, since it holds copies ofusers.jsonandsettings.json. A customconfigBackupDiris outside what the blocklist can name, so keep that folder out of reach of other users. - The OpenCode Console breach notice is retired. A new install has no record of having seen it, so every new OpenCode user was still being warned about an October incident.
Fixes applied while landing.
codeman notify --filerefuses a credential file such as.envor a key under.ssh, even inside the tab's own folder, and the Discord bot token cannot be read through the attachment routes (#741). A very wide table cell in an agent's last message no longer stalls the server, and a file sent from Discord is no longer reported as something the agent produced (#741). ABash(row keeps its links, because it holds a command rather than a path, whileRead(andUpdate(rows link a spaced name whole (#735). A model id the CLI cannot launch is refused before anyone is asked to evict a loaded model, on both the swap route and quick-start (#752). A cases-folder refusal in Clone Repo now points at Clone Repo, and OpenSSL'sSSL_connecterrors classify as unreachable again (#744). Abandoning a tunnel enable records the settings baseline (#736). A session's unreachableDSH_HOMEis logged when the server's home is linked instead (#755). Clone Repo and New folder no longer risk a hang on a mount that stopped answering (#744, #745).Docs and tests. Discord setup guide and wiki page, the Edit history and
paneCwdAPI sections, the custom endpoint guide, and the architecture notes for the new subsystems. Two Docker and TUI test harnesses now pass under a root runner and on tmux 3.2a (#738, #742). - @opticon454 for a big round: the two-way Discord bridge (#741), custom endpoint context limits, Codex and DeepSeek model selection and the model picker (#752, #755, #757), Clone Repo into a custom folder (#744), the New folder button (#745), and the wrapped
codeman@1.47.0
Minor Changes
-
1ab01bb: ### Thanks
- @timkjr for five PRs: a wrapped tab strip that uses the space under the toolbar (#721), three fixes that stop Codeman reading and watching a remote session's folder on the local disk (#722, #727, #728), and a quieter build (#729).
- @kdxcxs for bodyless requests that work through Cloudflare Tunnel (#725), traced through a real Access + Tunnel hostname.
- @Hugo-DDT for a desktop dead key typed once and a Ctrl+V that stays a paste after a replay (#726), and @hedburgaren for reporting both in #716.
- @opticon454 for rendered Markdown that fills a resized File Viewer (#730).
- @JDProfresh for a middle click on a file path that opens the file (#731).
The wrapped tab strip uses the room under the toolbar (#721). When the classic header strip wraps onto more rows (automatically, or with the two-rows setting), only the rows beside the toolbar stop short of it now; every row below runs the full header width, so long tab names no longer end up one per row. A strip that fits on one row looks exactly as before, and a strip tall enough to scroll keeps the plain wrap.
Fixes.
- Bodyless requests work through Cloudflare Tunnel (#725). cloudflared forwards a POST with no body as an empty chunked request with no Content-Type, which the server refused with
415before the route ran, so actions such as opening a saved web tab failed through a tunnel. An empty, untyped POST under/api/now reaches its route exactly like aContent-Length: 0one; anything with a body or another method is still refused as before. - A desktop dead key is typed once, and Ctrl+V stays a paste after a replay (#726, #716). The soft-keyboard recovery for Android IMEs now stays off on a desktop (a fine pointer that is not Android), so a dead-key backtick no longer arrives twice. Plain-text Ctrl+V is now framed as a bracketed paste by Codeman itself, because xterm stops adding the markers once a terminal replay clears its paste mode, and a copied newline then submitted the prompt. The paste still scrolls to the bottom and clears the selection, in the main pane, grid tiles and the split pane.
- Remote sessions no longer touch the local disk at their path (#722, #727, #728). A remote (SSH) session's folder is a path on the remote host, but the Ralph
@fix_plan.mdwatcher and the image watcher watched it on this machine (loggingENOENTat every start, or watching an unrelated local folder of the same name), and the Ralph file routes read and wrote it locally. Both watchers now skip remote sessions (the Session Options image-watcher switch is hidden there), the Ralph menu's Import from File reads@fix_plan.mdon the remote host over the same ssh path the File Viewer uses, and Write to File (and the@ralph_prompt.mdwrite) is refused for a remote session instead of landing in a local folder. - Rendered Markdown fills a resized File Viewer (#730). The document kept a fixed 960px column from before the window could be resized, so it stopped reflowing once you dragged or expanded the window past it.
- A middle click on a file path opens the file (#731). In the Response Viewer and the File Viewer's rendered Markdown, a middle click on a file path or an in-document link opened the dashboard root in a new tab. It now does what a left click does; real web links keep the browser's own middle click.
- No more duplicate-key warning on build (#729). The Chinese translation table carried
Idletwice.
Fixes applied while landing. A remote session's fix plan stays authoritative as it is for a local one, so a prose line such as "All tasks completed" cannot mark every todo done and end a remote Ralph loop when it cannot end a local one (#722). The Session Options image-watcher switch flips back and says so when the server refuses the change, instead of reporting success (#727). The remote
@fix_plan.mdread uses the File Viewer's own containment check rather than a copy of it (#728). ASCII-diagram blocks in the File Viewer's rendered Markdown follow the window instead of staying 720px wide (#730). A paste marker hidden inside another one (ESC[20+ESC[201~+1~) can no longer survive the strip and end the bracketed paste early, in Ctrl+V and in the phone composer alike, and an Android device with a mouse, a trackpad cover or a stylus keeps the soft-keyboard fixes, which turned off there because Chromium reports such a pointer as fine (#726).Docs and tests. The L-shaped strip in the frontend notes and the architecture notes, the remote-session rows for the Ralph file routes and the two watchers in the remote-sessions guide and the architecture notes, and an overview of the empty-POST parser in its module.
xterm-zerolag-input@0.4.2
Patch Changes
-
de1aab9: ### Thanks
- @JDProfresh for five PRs: a phone keyboard that no longer costs Claude its transcript (#711, measured in #672), a + on each session tab that starts a session beside it (#712, shaped in Discussion #700), a tunnel that needs its own opt-in instead of the LAN one (#718, from their report #706), a settings.json that two writers can no longer tear (#719), and a DeepSeek test that passes on current Node (#710).
- @aakhter for six PRs:
codeman agent spawnin a project directory (#708), worker ids kept when the readiness check fails (#709), the offline Codex history reader (#707), experimental bounded inspection and guarded submission for agents (#694, from Discussion #695), links that follow URLs and paths across wrapped rows and table cells (#686), and file paths with spaces linked as one path (#687). - @opticon454 for the Fetch button and fetch interval in the Git status window (#714).
- @johoja12 for Cmd+K arrows that switch the CLI both ways after you type a case name (#717).
Fetch from the Git status window (#714). The Git status window has a Fetch button next to Refresh. It runs
git fetchfor the repositories it lists and shows each one's result. An optional interval runs it for you: off by default, app-wide in App Settings, Bottom bar, with a per-session override in Session Options, Git. A fetch only moves remote-tracking refs (HEAD, the index and the working tree stay as they are), it never runs for a Docker or remote session, and it is bounded in time, output and concurrency.Start a session beside any tab (#712, opt-in). Turn on New Session Button on Tabs (App Settings, Tabs) and each session tab gets a +: pick any CLI its case can run (a Docker case offers what its container has) and the new session starts in that case or worktree and that tab's group, without touching the toolbar's case or Run mode. The row menu offers the same as "New session here…" for the keyboard.
The phone keyboard no longer costs Claude its transcript (#711). Every keyboard open and close used to resize the PTY, and Claude Code answers each height change by reprinting only the tail that fits, so lines above it were lost from tmux for good (25 of 100 in five keyboard cycles). A local Claude session now keeps its rows while the keyboard is up and slides the screen so the composer stays above the keyboard. On by default as Keep Size Under Keyboard (App Settings, per device); off restores the old resize. Fullscreen Claude (mouse tracking on) still resizes as before.
Typing stays smooth in a long prompt (#713). The local echo overlay (the instant preview of what you type) rebuilt every character of the prompt on each keystroke, so on a phone-class CPU a 4,000-character prompt took most of a second per key. It now rebuilds only the line that changed, with one paint layer per line, so a keystroke costs the same however long the prompt is. Every character still sits on its terminal cell. This ships in
xterm-zerolag-inputtoo.Links survive wrapping and spaces (#686, #687). A URL or path a CLI wrapped inside a table cell or an indented paragraph now links whole instead of in fragments, URLs keep balanced parentheses (
…/Team-Space(QA)Archive/…), a full-width table divider no longer glues onto the row below, and OSC 8 hyperlinks open through Codeman's own opener after a confirmation. A file path with spaces (/mnt/c/OneDrive - Contoso/report.docx,Saved to: ~/My Docs/plan.md) links as one path in the terminal and the response viewer when the line bounds it, and a shell prompt that prints its working directory no longer turns the whole command line into one link.codeman agent spawnin a project directory (#708). Without a case name,spawnstarts the worker in the current directory, or in an existing directory given with--working-dir, throughPOST /api/v1/sessionsand the mode's start route. Named cases still use quick-start.--jsonprints{ sessionId, workingDir, created: true }plusready,readinessErrororstartupError. An empty--working-dir, a bare spawn from your home directory (it would install Codeman's hooks into~/.claude; pass--working-dir ~to mean it) and an unknown--modeare refused with exit 4 before any request.Read saved Codex conversations offline (#707).
codeman history readreads Codex's saved rollouts without a Codeman server: by file, by Codex session id, or a whole conversation with its sub-agents and forks, filtered by topic or UTC date with whole turns kept. Reads and output have separate, raisable budgets, and anything it could not read or attribute (a compressed.jsonl.zstrollout, a file still being written) is reported throughcomplete: falseinstead of failing the lookup. The codeman skill routes to it.Experimental: bounded inspection and guarded submission for agents (#694, opt-in).
codeman agent inspectreads bounded, cursor-paged evidence from another session (a local Codex session's attributed rollout records, otherwise a labelled pane snapshot), andagent stage/agent submittype one line into a verified local Codex composer and later send exactly one Enter against a hash-confirmed receipt. Off by default behind Experimental agent coordination (App Settings, Cross-session features); while off the three routes answer403 FORBIDDENnaming the setting. These routes and verbs are experimental under the versioning policy and may change in a minor or patch release. During the few milliseconds of a guarded submit, other input is held and written in order afterwards; a tagged input POST in that window answers409 CONFLICTso its sender retries, and an untagged one (the phone keys, the Stop button) is held and answered once written.Cmd+K arrows switch the CLI both ways (#717). After typing a case name in Cmd+K, plain Left and Right now both change the New session row's CLI whenever the caret is at either end of the query (only Right did before). Inside the query the arrows move the caret as usual.
Fixes.
- Security: a LAN install's acknowledgement no longer opens a public tunnel (#718).
CODEMAN_ALLOW_UNAUTHENTICATED_NETWORK(and--allow-unauthenticated-network), which the installer writes for every LAN install without a password, also let the Cloudflare tunnel start, so one click on the welcome screen's tunnel link published full terminal control to a public URL with no login and no confirm. It now covers the network bind only. An unauthenticated tunnel has its own opt-in,CODEMAN_ALLOW_UNAUTHENTICATED_TUNNEL=1orcodeman web --allow-unauthenticated-tunnel(carried bycodeman web -dandcodeman service install), which the installer never writes; if you relied on the network variable to start the tunnel without a password, set one of those. With no password and no multi-user mode, the browser now asks before every tunnel enable, using the newloginConfiguredfield ofGET /api/tunnel/status. Both acknowledgement variables and their flags are now listed as stable in the versioning policy. - settings.json can no longer be torn (#719). A quick-start's
lastUsedCasewrite was not awaited and not atomic, so it could overlap the next settings save and leave one write's bytes over the tail of the other, after which every reader saw{}. Every write to settings.json now goes through one serialized writer that writes a temp file and renames it into place, and a file that does not parse is refused with409 CONFLICTinstead of being overwritten with only the writer's own keys. A case rename checks this before it ends any session. - A worker id is never lost (#709). When
codeman agent spawncreated a worker but its readiness request failed, it exited without the new session id. It now prints the id (and--jsoncarries it) and exits 1, so the caller can inspect or delete the worker.codeman agentandcodeman mcpalso name the error code (such asECONNREFUSED) when a request fails with an empty message. - The DeepSeek transcript test passes on Node 24.22+ and 26.10+ (#710). It pinned Node's old zstd decoder, which stopped at the first frame until nodejs/node#65865.
Fixes applied while landing. The Git fetch interval field is no longer reset by a session update while you type in it, a session holding only half an override shows the app's value for the other half, reading a repository's
core.sshCommandno longer doubles the fetch timeout, aGIT_SSHin the server's environment is honoured, and the Fetch button's disabled and busy styles no longer reach other icon buttons and stop pulsing under reduced motion (#714). A + launch keeps the toolbar on its own case, and pressing the + again closes its picker (#712). The fetch scheduler no longer logs the text of a malformed settings.json on every 15-second tick (the parser's message could quote an API key; it now says the file is not valid JSON, once), and a fetch is skipped while the Docker case list cannot be read, so it can never run inside a Docker workspace (#714). A case rename answers409 CONFLICTfor a settings.json it cannot write before it ends any session (#719). The unauthenticated-tunnel warning no longer fires in multi-user mode, where the tunnel has a login in front of it (#718). Untagged input during a guarded submit is held instead of refused, and the skill's staging guide says so (#694). A shell prompt line (a spaced working directory followed by$included) and a labelled../spaced path link as they should, and a bold label or inline code before a path in the response viewer splits it as the terminal does (#687); a URL whose row soft-wraps no longer glues a trailing column onto the next path, and in a table a link in the column right of a wrapped URL stays clickable on the URL's first row (#686). The keyboard hold reads the terminal's height only while rows are held (#711). The README, the plugin's README and ...
codeman@1.46.0
Minor Changes
-
de1aab9: ### Thanks
- @JDProfresh for five PRs: a phone keyboard that no longer costs Claude its transcript (#711, measured in #672), a + on each session tab that starts a session beside it (#712, shaped in Discussion #700), a tunnel that needs its own opt-in instead of the LAN one (#718, from their report #706), a settings.json that two writers can no longer tear (#719), and a DeepSeek test that passes on current Node (#710).
- @aakhter for six PRs:
codeman agent spawnin a project directory (#708), worker ids kept when the readiness check fails (#709), the offline Codex history reader (#707), experimental bounded inspection and guarded submission for agents (#694, from Discussion #695), links that follow URLs and paths across wrapped rows and table cells (#686), and file paths with spaces linked as one path (#687). - @opticon454 for the Fetch button and fetch interval in the Git status window (#714).
- @johoja12 for Cmd+K arrows that switch the CLI both ways after you type a case name (#717).
Fetch from the Git status window (#714). The Git status window has a Fetch button next to Refresh. It runs
git fetchfor the repositories it lists and shows each one's result. An optional interval runs it for you: off by default, app-wide in App Settings, Bottom bar, with a per-session override in Session Options, Git. A fetch only moves remote-tracking refs (HEAD, the index and the working tree stay as they are), it never runs for a Docker or remote session, and it is bounded in time, output and concurrency.Start a session beside any tab (#712, opt-in). Turn on New Session Button on Tabs (App Settings, Tabs) and each session tab gets a +: pick any CLI its case can run (a Docker case offers what its container has) and the new session starts in that case or worktree and that tab's group, without touching the toolbar's case or Run mode. The row menu offers the same as "New session here…" for the keyboard.
The phone keyboard no longer costs Claude its transcript (#711). Every keyboard open and close used to resize the PTY, and Claude Code answers each height change by reprinting only the tail that fits, so lines above it were lost from tmux for good (25 of 100 in five keyboard cycles). A local Claude session now keeps its rows while the keyboard is up and slides the screen so the composer stays above the keyboard. On by default as Keep Size Under Keyboard (App Settings, per device); off restores the old resize. Fullscreen Claude (mouse tracking on) still resizes as before.
Typing stays smooth in a long prompt (#713). The local echo overlay (the instant preview of what you type) rebuilt every character of the prompt on each keystroke, so on a phone-class CPU a 4,000-character prompt took most of a second per key. It now rebuilds only the line that changed, with one paint layer per line, so a keystroke costs the same however long the prompt is. Every character still sits on its terminal cell. This ships in
xterm-zerolag-inputtoo.Links survive wrapping and spaces (#686, #687). A URL or path a CLI wrapped inside a table cell or an indented paragraph now links whole instead of in fragments, URLs keep balanced parentheses (
…/Team-Space(QA)Archive/…), a full-width table divider no longer glues onto the row below, and OSC 8 hyperlinks open through Codeman's own opener after a confirmation. A file path with spaces (/mnt/c/OneDrive - Contoso/report.docx,Saved to: ~/My Docs/plan.md) links as one path in the terminal and the response viewer when the line bounds it, and a shell prompt that prints its working directory no longer turns the whole command line into one link.codeman agent spawnin a project directory (#708). Without a case name,spawnstarts the worker in the current directory, or in an existing directory given with--working-dir, throughPOST /api/v1/sessionsand the mode's start route. Named cases still use quick-start.--jsonprints{ sessionId, workingDir, created: true }plusready,readinessErrororstartupError. An empty--working-dir, a bare spawn from your home directory (it would install Codeman's hooks into~/.claude; pass--working-dir ~to mean it) and an unknown--modeare refused with exit 4 before any request.Read saved Codex conversations offline (#707).
codeman history readreads Codex's saved rollouts without a Codeman server: by file, by Codex session id, or a whole conversation with its sub-agents and forks, filtered by topic or UTC date with whole turns kept. Reads and output have separate, raisable budgets, and anything it could not read or attribute (a compressed.jsonl.zstrollout, a file still being written) is reported throughcomplete: falseinstead of failing the lookup. The codeman skill routes to it.Experimental: bounded inspection and guarded submission for agents (#694, opt-in).
codeman agent inspectreads bounded, cursor-paged evidence from another session (a local Codex session's attributed rollout records, otherwise a labelled pane snapshot), andagent stage/agent submittype one line into a verified local Codex composer and later send exactly one Enter against a hash-confirmed receipt. Off by default behind Experimental agent coordination (App Settings, Cross-session features); while off the three routes answer403 FORBIDDENnaming the setting. These routes and verbs are experimental under the versioning policy and may change in a minor or patch release. During the few milliseconds of a guarded submit, other input is held and written in order afterwards; a tagged input POST in that window answers409 CONFLICTso its sender retries, and an untagged one (the phone keys, the Stop button) is held and answered once written.Cmd+K arrows switch the CLI both ways (#717). After typing a case name in Cmd+K, plain Left and Right now both change the New session row's CLI whenever the caret is at either end of the query (only Right did before). Inside the query the arrows move the caret as usual.
Fixes.
- Security: a LAN install's acknowledgement no longer opens a public tunnel (#718).
CODEMAN_ALLOW_UNAUTHENTICATED_NETWORK(and--allow-unauthenticated-network), which the installer writes for every LAN install without a password, also let the Cloudflare tunnel start, so one click on the welcome screen's tunnel link published full terminal control to a public URL with no login and no confirm. It now covers the network bind only. An unauthenticated tunnel has its own opt-in,CODEMAN_ALLOW_UNAUTHENTICATED_TUNNEL=1orcodeman web --allow-unauthenticated-tunnel(carried bycodeman web -dandcodeman service install), which the installer never writes; if you relied on the network variable to start the tunnel without a password, set one of those. With no password and no multi-user mode, the browser now asks before every tunnel enable, using the newloginConfiguredfield ofGET /api/tunnel/status. Both acknowledgement variables and their flags are now listed as stable in the versioning policy. - settings.json can no longer be torn (#719). A quick-start's
lastUsedCasewrite was not awaited and not atomic, so it could overlap the next settings save and leave one write's bytes over the tail of the other, after which every reader saw{}. Every write to settings.json now goes through one serialized writer that writes a temp file and renames it into place, and a file that does not parse is refused with409 CONFLICTinstead of being overwritten with only the writer's own keys. A case rename checks this before it ends any session. - A worker id is never lost (#709). When
codeman agent spawncreated a worker but its readiness request failed, it exited without the new session id. It now prints the id (and--jsoncarries it) and exits 1, so the caller can inspect or delete the worker.codeman agentandcodeman mcpalso name the error code (such asECONNREFUSED) when a request fails with an empty message. - The DeepSeek transcript test passes on Node 24.22+ and 26.10+ (#710). It pinned Node's old zstd decoder, which stopped at the first frame until nodejs/node#65865.
Fixes applied while landing. The Git fetch interval field is no longer reset by a session update while you type in it, a session holding only half an override shows the app's value for the other half, reading a repository's
core.sshCommandno longer doubles the fetch timeout, aGIT_SSHin the server's environment is honoured, and the Fetch button's disabled and busy styles no longer reach other icon buttons and stop pulsing under reduced motion (#714). A + launch keeps the toolbar on its own case, and pressing the + again closes its picker (#712). The fetch scheduler no longer logs the text of a malformed settings.json on every 15-second tick (the parser's message could quote an API key; it now says the file is not valid JSON, once), and a fetch is skipped while the Docker case list cannot be read, so it can never run inside a Docker workspace (#714). A case rename answers409 CONFLICTfor a settings.json it cannot write before it ends any session (#719). The unauthenticated-tunnel warning no longer fires in multi-user mode, where the tunnel has a login in front of it (#718). Untagged input during a guarded submit is held instead of refused, and the skill's staging guide says so (#694). A shell prompt line (a spaced working directory followed by$included) and a labelled../spaced path link as they should, and a bold label or inline code before a path in the response viewer splits it as the terminal does (#687); a URL whose row soft-wraps no longer glues a trailing column onto the next path, and in a table a link in the column right of a wrapped URL stays clickable on the URL's first row (#686). The keyboard hold reads the terminal's height only while rows are held (#711). The README, the plugin's README and ...
codeman@1.45.0
Minor Changes
-
Thanks
- @opticon454 for five PRs: renaming a case and its folder with the live sessions handled (#680), a resizable line between the tabs and the header toolbar (#689), opt-in GPU and CPU clock readings in the header (#692), and two Codex wheel fixes measured against the real CLI, a first notch that moves the transcript (#699, from #697) and a wheel that no longer moves a selection menu's choice (#698, from #696).
- @aakhter for five PRs: an agent picker on the Cmd+K New session row (#685), a login throttle that no longer locks a whole tunnel out after ten typos (#684), an SSE connect attempt that can no longer hang forever (#678), prompts that start with a hyphen (#677), and
reqmade required on the session lookup helpers so an ownership check cannot be skipped by accident (#683). - @JDProfresh for a phone swipe that follows the order the strip draws (#682) and an inline Claude tab whose history loads instead of paging the composer after a server restart (#681), both found and tested on an iPhone.
- @Randalix for the per-session agent inbox (#690), the shape agreed in Discussion #558.
- @Hugo-DDT for closing the last two ways a key binding could move a client onto another session (#688), and @christianhaberl for reporting both in #671.
- @johoja12 for remote hosts whose tmux lives in Homebrew or a per-user bin directory (#691), the follow-up promised in #645.
Rename a case and its folder (#680). The case manager has a Rename action. A case under
~/codeman-casesis renamed as a name and folder; a linked case can rename only its name or its real folder too. Live sessions that have the folder open are listed and only stopped if you agree, the folder is locked while it moves so nothing starts in it half-moved, a folder another program holds open is reported instead of forced, and Claude Code's conversation history (including the Resume list), the case order, the last used case and the default session group follow the new name.A per-session agent inbox (#690). Agents can leave each other messages without typing into anyone's pane:
codeman agent post <id> "<text>",codeman agent inbox [--wait]andcodeman agent ack <ids>, overPOST/GET /api/sessions/:id/inbox,POST .../inbox/ackandGET /api/agent-inbox/summary. A message stays until its receiver acknowledges it, so nothing is lost between a read and the ack, andcodeman agent lsshows an INBOX column. Inboxes live in memory by default; Keep agent inbox across restarts (Settings, Cross-session features, off by default) writes them to a 0600 file in the data dir, kept for 12 hours.Pick the agent from Cmd+K (#685). The palette's New session row shows the agent it will start, with arrows to change it (Left/Right while the row is highlighted). It starts on the Run button's mode, offers the same agents the Run menu offers for that case (a Docker case's container agents included), and launches once without changing the Run button.
A resizable header toolbar (#689). Drag the line between the session tabs and the header toolbar. Dragging it right narrows the toolbar, which then wraps onto a second line instead of squeezing out the tabs, and the usage readings shed their labels, then their provider names, then (in the Compact style) their percentages as it narrows; double-click or Home resets it, the arrow keys move it, and the width is remembered on the device.
GPU and CPU clock readings (#692, opt-in). GPU Stats adds GPU load, graphics memory and the GPU clock after CPU and MEM (each only when the host reports it), and CPU MHz adds the live CPU clock. Both are in Settings, Header & Panels, off by default, and nothing is read unless the browser asks. NVIDIA is read through
nvidia-smi, AMD through sysfs, and inside WSL any vendor through the Windows performance counters (no GPU clock there). The header also keeps polling its stats with no session open, so CPU and MEM no longer sit at--.Fixes.
- A tunnel no longer locks everyone out after ten typos (#684, multi-user mode). Behind
tailscale serveor a tunnel every login arrives from one address, so ten wrong passwords from anyone used to lock every user out for 15 minutes. The per-address limit is now 50, and each account allows ten failed guesses per address, both checked before the password is verified. Another address can no longer lock an account out, a burst of parallel guesses counts in full, and identical logins in flight share one check, so a reload with many tabs open is never refused. Single-user mode is unchanged. - The first wheel notch moves a Codex transcript (#699). When a CLI does not track the mouse, Codeman turns the wheel into PageUp/PageDown, and it used to send nothing until half a screen of travel had built up: 5 notches in Chrome, 7 in Firefox. The first notch now pages at once and the notches after it repay it, so the page rate is unchanged.
- The wheel no longer moves a Codex menu's selection (#698). At "Implement this plan?" one notch down used to land on "No, stay in Plan mode" and one up on "Yes, implement this plan", because those menus use the page keys. The wheel is now ignored while such a menu shows, in the main pane and in tiles, and pages the transcript again once it closes.
- History loads after a restart instead of paging Claude (#681). After a server restart, a second visit to an inline Claude tab on a phone turned every swipe into PageUp/PageDown for Claude, so the composer jumped around and old output never showed. The swipe now loads tmux's history, as the first visit does.
- A phone swipe follows the strip (#682). With the case or state layout, a sorted rail or named groups, swiping now moves to the session drawn next to the current one, not the next one in the hidden canonical order. Alt+[ / Alt+], Ctrl+Tab and Alt+1..9 keep the canonical order, matching the Alt+N badges.
- Key bindings can no longer move a client onto another session (#688, fixes #671). The tmux servers behind Docker cases and owned remote sessions keep only their send-prefix binding, as Codeman's own socket has since 1.44.0, and
codeman tui's Alt+1..9 switch only the TUI's own client: an Esc then a digit in a browser tab reaches its pane instead of switching it. - Remote tmux found in Homebrew or a per-user bin (#691). Every remote tmux call (availability check, launch, attach, discovery, capture, cleanup) now runs on one widened, quoted PATH, so a host whose tmux works only in an interactive shell links and launches, home directories with spaces included.
- Prompts that start with a hyphen (#677). Text typed into a pane that began with
-(-x hello,--help) was read by tmux as its own options and never arrived. - A connect attempt that never opens is retried (#678). After a phone resumes on a VPN or tailnet, an event stream could sit in "connecting" forever with no error to trigger a retry. Each attempt now gets 15 seconds before it is closed and retried with the usual backoff.
Fixes applied while landing. A case rename that fails half way now puts
settings.jsonback too and says where the folder is; it merges Claude Code's history into a folder a deleted case of the new name left behind instead of silently leaving it at the old name, refuses a dangling symlink at the new name before any session is stopped, refuses to move a folder while a session is still being created in it, and the dialog says plainly that stopping closes the sessions (#680). The inbox keeps the mail of sessions on the reboot-restore offer and of a detached session that comes back, prints message text with control characters escaped, and flushes after the server stops accepting posts (#690). Cmd+K's agent list follows the case's own availability rule, so a Docker case can start a CLI only its container has, and with a single choice the row keeps the Run button's mode (#685). The divider's stored width can no longer go negative and Escape no longer resets it (#689). With the toolbar narrowed, the GPU, VRAM and clock readings keep their labels, so they can still be told apart from CPU and MEM, and at Compact's rings-only step a clock with nothing left to show is hidden instead of leaving a gap (#689, #692). The stats route no longer waits on Windows' RAM probe, and a hungnvidia-smican no longer freeze the header's CPU and MEM readings: thenvidia-smiand Windows RAM probes now give up after 1.5 s (#692). A secondcodeman tuion a longer pts number can no longer remove the first one's guard, and a client that fails the guard gets its key instead of losing it (#688). A test that had started passing vacuously after the SSE change checks the connect URL again (#678).Docs and tests.
reqis now required onfindSessionOrFailandfindPersistedSessionOrFail, pinned by a test that also checks its exact type (#683). New sections for the agent inbox, the case rename, the header divider and the host sensors, the SSE connect timer next to the staleness watchdog, the login buckets in the security docs, and the remote PATH rule in the architecture notes.
codeman@1.44.0
Minor Changes
-
Thanks
- @opticon454 for five PRs: config backups you can compare and restore (#661, ten review rounds), a File Viewer you can resize, expand and walk Back and Forward through (#659), GitHub Copilot's premium-request quota in the plan-usage chip (#662), a warning when llama.cpp's parallel slots leave too little context per request (#658, from #641), and a bare
npx vitestthat can no longer write into your real~/.codeman(#660, from #640). - @JDProfresh for four PRs: the opt-in prompt-cache keep-alive (#666, step 2 of #554), Markdown links to file paths that open in the File Viewer (#665), a phone keyboard that stays up while you press accessory keys (#673), and a session swipe that no longer taps or scrolls the session you are leaving (#674), with the iPhone testing behind both phone fixes.
- @christianhaberl for four PRs:
CODEMAN_MAX_SESSIONS(#668), tmux prefix keys that can no longer move a browser tab onto another session (#669), multi-line prompts that keep their line breaks (#670), and rediscovered tmux sessions that keep their own folder (#667). Also for the earlier #224, #225, #226 and the session sidebar (#307), whose commits carried an agent identity that GitHub credits to another account. - @johoja12, a first-time contributor, for scroll batches that stay with the tab that made them, smoother trackpad scrolling and wheel scrolling in fullscreen Codex (#645), measured against the real CLI through five review rounds.
- @ludovicfourrage for touch scrolling in apps that track the mouse themselves (#664), and the careful write-up in #663.
- @aakhter for a default tab group per case (#676).
Config backups (#661). Codeman now keeps timestamped copies of the files that hold your setup: settings, CLI overrides, custom model endpoints, the webhook, linked cases and, in multi-user mode, the accounts. It takes one at startup and whenever one of them changes, into
~/.codeman/backups/configby default. App Settings → System lets you pick the folder and the retention (keep N backups, drop ones older than N days), back up now, compare two backups or a backup with what is running (credentials are never shown, only whether they changed), and restore one. A restore first saves what it is about to replace, so it can be undone, and retention only ever deletes folders Codeman made and never the newest backup.Keep an idle Claude session's prompt cache warm (#666, opt-in). Claude Code's prompt cache expires after an hour of quiet, and the next prompt then pays to re-read the whole conversation. Switch on Keep the cache warm while idle in a session's Respawn tab (or Keep prompt caches warm in App Settings → System → Automation for every new session) and Codeman sends a one-line keep-alive turn about five minutes before the cache would expire. It only does that when nothing else is going on: an empty prompt, no open dialog, nobody typing, no respawn, Ralph loop or waiting agent, no usage-limit pause. It stops on its own a while after your last prompt (Keep warm for at most, default 2 hours). A session started with it on also launches with Claude Code's own idle compaction off (Claude Code 2.1.290 or newer). The keep-alive raises no alert, push, webhook or Away-digest row, and the readout's Status line says what it is doing.
A default tab group per case (#676). Case settings has a Default session group: every new session for that case lands straight in that tab group, in the same write that creates it, so it never flashes in Ungrouped first. An explicit group on the create request and a spawned child following its parent still win. It is stored per user and survives a group rename.
A File Viewer you can resize, with Back and Forward (#659). Drag the corner grip to resize the window, or press Expand to fill the screen (remembered on this device). Following a link from one file to another builds a history that the ← and → buttons and Alt+← / Alt+→ walk through. Phones keep the full-screen viewer.
Copilot's premium-request quota in the plan-usage chip (#662). With the GitHub Copilot CLI installed and signed in, the header chip gains a Copilot row for the month's premium requests, with the counts and the reset date in the tooltip. Codeman reads it every 10 minutes from GitHub with the Copilot CLI's own sign-in token. It is on by default, like the Codex row, and turning Plan Usage Limits off in App Settings stops the request.
More (or fewer) sessions with
CODEMAN_MAX_SESSIONS(#668). The cap of 50 concurrent sessions can be set at startup, from 1 to 462. A value that is not a positive integer falls back to 50, and the per-user cap in multi-user mode follows it unlessCODEMAN_MAX_SESSIONS_PER_USERis set.Multi-line prompts keep their line breaks (#670). A prompt sent through the API with
useMuxused to arrive as one welded line (line oneline two). Its lines now go into the pane as one bracketed paste, followed by the Enter that submits them together. The senders that run unattended (cron, respawn's update and kickstart prompts, the auto-compact focus,codeman agent send, the TUI and the skill'ssendwait) stay single-line and join lines with a space, because the submit check cannot yet recognise a multi-line paste in the composer.A warning for llama.cpp slots that split the context too thin (#658). A custom llama.cpp model that runs several parallel slots splits its context between them, and four 40K-token Claude requests against a 4-slot, 131K pool all failed with "Context size has been exceeded". Discovery now records each model's slot count, and a Claude launch warns when one slot gets less than 40K tokens, naming the fix (
--parallel 1, or a context large enough for every slot).Fixes.
- tmux prefix keys stay out of browser tabs (#669). Ctrl+B then
),(,sorwin a tab switched its tmux client to another session while the tab kept the first one's name. Codeman's tmux socket now keeps only Ctrl+B Ctrl+B (send-prefix) in its prefix table, set at session start and at boot. This also meansCtrl+B dno longer detaches a terminal attached to that socket:codeman tuiandscripts/tmux-manager.shdetach with F1. - Scrolling stays with its tab, and fullscreen Codex scrolls (#645). A queued wheel batch can no longer land in a tab you switched to, trackpads keep their fractional travel instead of dropping it, the first wheel report of a tab visit goes out at once, and Codex gets wheel reports while it has mouse tracking on (measured on Codex 0.163.0, where an approval prompt's selection is unaffected).
- Touch scrolling in apps that track the mouse (#664). A finger drag and its fling now scroll a program in the pane that asked for SGR mouse reports (a TUI in a shell tab, for example) instead of scrolling a local buffer that cannot show it. Other mouse encodings are left alone.
- A session swipe only switches sessions (#674). A sideways swipe on the terminal no longer also opens a link, taps a CLI menu or toggles the keyboard on the session you are leaving. A deliberate swipe gets 500 ms instead of 300, a selection or a second finger pauses it, and a scroll that starts on a sideways thumb arc still scrolls.
- The phone keyboard stays up (#673). Arrow, Tab, Esc and the other accessory keys that act on the terminal no longer blur it for a moment, so the toolbar stops bouncing on every tap.
- Markdown links to files open in the File Viewer (#665). A link like Codex's
[label](/abs/path.json)in the response viewer now opens the file instead of a same-origin 404 tab, and its label keeps the prose font. - Rediscovered sessions keep their folder (#667). A tmux session Codeman finds again on its socket (after
mux-sessions.jsonwas lost) now gets the directory tmux reports for its pane instead of the server's own, so a respawn goes back to the right project. - Web tabs send POST bodies to dashboards that read Content-Length. Codeman's web-tab proxy now relays the browser's Content-Length, so a dashboard built on Python's
http.serveror a small Go or C server no longer sees an empty body on every POST made through a web tab.
Fixes applied while landing. A restore that fails partway now says which files it restored, which it could not and where the pre-restore copy is, re-reads what was written and refills the Settings form; backup passes list the manifests once, and a pre-restore copy equal to the newest backup is not made twice (#661). A failed keep-alive write is retried before the expiry instead of never, an unreadable
settings.jsonis logged once instead of every minute for every session, the keep-alive's own hooks stay out of the run summary, and saving App Settings re-plans keep-alives only when their settings changed (#666). The Copilot quota read checks the setting and the sign-in token before it ever probes for the CLI, so a machine without Copilot runs no login shell every 10 minutes, and drops a header the Copilot CLI itself does not send (#662). The prefix-table reset still binds send-prefix on an empty table and no longer reruns on every session for a prefix tmux lists escaped (#669). Claude worktree sessions follow the case's default group like every other CLI's (#676). The remote-history PATH change that rode along in #645 was left for its own PR. Smaller touches: the Expand button keeps its label while pressed and Alt+← / Alt+→ are listed in the shortcut overlay and help (#659); the scroll log names xterm's mouse encoding (#664); the response-viewer link test covers?queryand folder links (#665).Docs and tests. A bare
npx vitest runfrom the repo now uses the isolated CI config instead of running without the setup file, the helpers that delete test folders refuse to run outside a sandboxed HOME, and the temp-HOME teardown is bounded so a stuck writer cannot time the hook out (#660). New sections and line... - @opticon454 for five PRs: config backups you can compare and restore (#661, ten review rounds), a File Viewer you can resize, expand and walk Back and Forward through (#659), GitHub Copilot's premium-request quota in the plan-usage chip (#662), a warning when llama.cpp's parallel slots leave too little context per request (#658, from #641), and a bare