fix: Claude Code plugin path to workspaces — headless `run` hang, first-run skills, unsent memory
Summary
These are fixes for the gaps found by walking the whole path from the Altimate Code plugin in Claude Code to an Altimate workspace. Each was reproduced against a real tenant first:
- Install the plugin and the CLI.
- Sign in, then
altimate-code link. - Publish a workspace skill.
- Ask Claude Code questions that need the workspace.
- Teach it a rule and come back in a new session.
What changed
1. run no longer hangs on an idle stdin.
- Problem: Claude Code's Bash tool, like a Node
spawnwith default stdio, gives the child a stdin it never writes to or closes.runawaitedBun.stdin.text()on it, so every task the plugin handed over hung before it started. In the e2e run, Claude found the stuck process after about 10 minutes and retried it with</dev/null. - Fix: the new
readRunStdinreads a regular file in full. It reads any other stdin only if the first chunk arrives within 3s, and then to EOF. - Without input: it prints one line and continues.
- Verified: an idle socket on stdin times out on 0.12.7 but finishes on this branch. Piped text, a slow pipe,
/dev/nulland a file all behave as before.
2. The first skill added to an empty workspace reaches the next run.
- Problem: a turn waits for the skill sync only when a skill snapshot exists. A workspace linked while it had no skills has no snapshot, only the empty-workspace record. Each
runis a fresh process, so the next run named the new skill in its workspace prompt, but the skill tool answered "not found". - Fix: the gate now also waits when that record exists.
emptyRecordPathmoves to its own module, so the gate doesn't loadskill-sync. - Verified: with this branch, the first run after the skill was published uses it.
3. run says when memory stayed local.
- Problem: the first memory create can take longer than the 15s request timeout. A
rundoesn't retry, and the TUI andservepoll butrundoesn't. So the block stayed on the machine, and onlyworkspace statusshowed it. - Fix:
runnow ends with "N memories saved here are not in the workspace yet. Runaltimate-code workspace sync…". The count is the same oneworkspace statusreports, and it is checked only when the run saved memory.
4. Sign-in and link messages name a command that works from a shell.
- Sign-in:
linkandworkspacenow sayaltimate-code auth login -p altimate-backendinstead of "run the TUI and sign in". - Non-TTY
link: the error names--workspace <id or name>and--create, which is what an agent's shell needs.
5. Docs. using-with-claude-code.md covers:
- installing the plugin;
- using a workspace from Claude Code (sign in, link, check, ask);
- the namespaced
/altimate-code:altimatecommand.
The page's description no longer promises MCP content it doesn't have.
Test plan
- New tests:
test/cli/run/run-stdin.test.ts: file, pipe, slow pipe, empty, and open-with-no-data (times out and releases the stream).test/session/prompt.test.ts: with only the empty-workspace record, the sync lands before the turn's message is written. This test fails without the gate change.test/altimate/workspace/memory-sync.test.ts: a failed mirror is counted until the block is sent.
- Suites:
bun test test/altimate/workspace test/cli test/session/prompt.test.ts test/skill: 3424 pass, 4 fail, 9 skip.- The 2
mcp addsubprocess failures pass when run on their own. - The 2
--time-budgettests injson-output.test.tsfail the same way withmain'srun.tson this machine.
- The 2
-
bun typecheck, oxlint (no errors),analyze.ts --markers --strict. - End to end, real tenant, sandboxed install: Claude Code 2.1.300 with the plugin, on 0.12.7 and on this branch, covering the hang, the first-run skill, the memory upload and the messages.
Later commits
workspace list, and a sign-in command that works without a terminal. These came from testing in an interactive Claude Code session. From Claude Code's!prompt,auth login -p altimate-backendwaits at its method picker, andlinkrefuses without a TTY.SIGN_IN_COMMANDnow includes--method "Altimate LLM Gateway". The newaltimate-code workspace list [--json]lets Claude show the user's workspaces and link one withlink --workspace. Both were verified end to end inside Claude Code.- Review follow-ups. The unsent-memory notice now uses
workspace status's pending count rather than an in-process failure set.workspace listruns without opening a project. The stdin tests have wider margins. The docs note that re-linking needs--yes.
🤖 Generated with Claude Code
https://claude.ai/code/session_011chv9Rmu7jQXokum1WNcs7
Summary by cubic
Fixes the path from the Claude Code plugin to an Altimate workspace: headless run no longer hangs on an idle stdin, the first skill added to an empty workspace reaches the next run, and failed memory uploads are announced instead of silently staying local.
runreads files and shell pipelines to EOF; a socket stdin — what an agent's shell tool hands a child — is waited on for only 3 seconds, and only whenrunalready has a message or--command(otherwise stdin is the prompt and is read to EOF).ALTIMATE_RUN_STDIN_WAIT_MSchanges the wait.- The per-turn skill gate now also waits on a linked workspace that had no skills at the last sync, so the first skill published lands before the next
runnames it. - After a run that saved memory,
runprints the number of memories on this machine not yet in the workspace (checked within 5 seconds, and again within 1 second on a signal exit), pointing ataltimate-code workspace sync; when it can't confirm, it says so and points atworkspace status. The upload target is recorded before the memory-setting lookup, so an exit while that lookup is pending still gets the check. - Sign-in messages name
altimate-code auth login -p altimate-backend --method "Altimate LLM Gateway", which skips the method picker so it works where stdin is not a terminal; the non-TTYlinkerror offers--workspace/--create; newaltimate-code workspace list [--json]shows the workspaces an account can link to, without opening a project. - Docs:
using-with-claude-code.mdnow covers plugin install, workspace sign-in/link/status, and the/altimate-code:altimatecommand.
Summary by CodeRabbit
- New Features
- Added
workspace listto view available workspaces in text or JSON format. altimate-code runnow accepts piped input and reports when workspace memory remains unsynced.- Expanded the Claude Code guide with plugin setup, workspace linking, and instructions for using workspace skills and memory.
- Added
- Bug Fixes
- Improved sign-in guidance for workspace linking and listing.
- Claude Code prompts now wait for workspace skill syncing, including for workspaces with no skills yet.