@retasc/cli published to npm, newest first. Dates are the npm publish
date, and each entry names the issue behind it. One line per change; the full notes sit
under each version’s fold.
1.55.0
- RTSC-1057 — the proxy now reports how long this machine keeps a session transcript, read from the harness’s own settings (Claude Code’s
cleanupPeriodDays), so the Dash can name the day a conversation will be gone instead of quoting a documented default at you.
Full notes
Full notes
- RTSC-1057 — the proxy now reports how long this machine keeps a session
transcript, read from the harness’s own settings (Claude Code’s
cleanupPeriodDays), so the Dash can name the day a conversation will be gone instead of quoting a documented default at you. It was saying “deleted after 30 days by default”, which is wrong by eleven months for anyone who set it to a year. A number of days, never a path and never the file — the same boundary the transcript id and the workspace already sit on: Retasc holds the id, the machine holds the conversation. It is sent only for a harness whose retention the proxy actually read, so Codex, Gemini CLI, Cursor and OpenCode send nothing and the Dash keeps the shorter sentence for them rather than borrowing Claude Code’s number. Nothing to do on upgrade, and nothing breaks on an older CLI: the field is optional, an install that never sends it is ordinary, and the panel simply does not name a day. The backend that accepts it is already deployed.
1.54.0
- RTSC-1061 — nothing asks which subscription pays for an agent any more, so
retasc planis gone andretasc bindno longer puts the question.
Full notes
Full notes
- RTSC-1061 — nothing asks which subscription pays for an agent any more, so
retasc planis gone andretasc bindno longer puts the question. Breaking if you scripted it;retasc plannow exits withunknown command 'plan'. The question was asked once per runtime to give model spend a denominator, and the one surface that was going to read the answer was canceled. Nothing consumed it after that, so every install spent a turn of its first session collecting a fact with no reader on the other end. ThePLAN_UNKNOWNsetup state went with it, along with thelist_plansandset_planMCP tools — the server is at 56 tools now, down from 58. Upgrade if you are on 1.53.1 or older. The backend functions behindretasc planare already removed, so on an un-upgraded CLI that one command fails with a rawCould not find public functioninstead of a clean message. Every other command is unaffected,retasc bindincluded: its plan step was already written to be skipped rather than to fail the bind. Answers recorded before this are no longer read and are deleted in a follow-up.
1.53.1
- RTSC-1042 — the proxy now sweeps this machine’s dead worktrees on the first claim of a session.
Full notes
Full notes
- RTSC-1042 — the proxy now sweeps this machine’s dead worktrees on the first
claim of a session. Reap used to run only when this session marked an issue
done, so an author who sent work toreviewkept the tree after the reviewer merged and closed it on another laptop.retasc tidy --prune --autodeletes local trees whose issue isdoneorcanceledand whose commits are already on trunk or fully pushed to origin, with a one-hour grace and a cap of ten per session. A branch that never landed on trunk is not deleted from origin. Nothing to do: the next claim on a machine with leftover trees starts the drain.
1.53.0
- RTSC-1014 — every tool you start in a bound folder now gets its own credential, so one can be retired without stopping the others.
Full notes
Full notes
- RTSC-1014 — every tool you start in a bound folder now gets its own credential,
so one can be retired without stopping the others. Before this, Claude Code, Grok and
Codex started in the same folder all read the same
.mcp.jsonand authenticated as one credential: retiring any of them stopped all three and cost you aretasc bind. The proxy mints the new credential at theinitializehandshake — the first moment the tool has a name — and caches it in the keystore, so it fires once per (folder × tool) rather than once per session. Nothing to do: a folder bound before this upgrades itself as each tool next starts, with no re-bind and no edit to.mcp.json. Two behaviours worth knowing. A tool retired in a folder is served nothing there and says so, rather than quietly falling back to the folder’s shared key — that fallback would have undone the retire. And a client that never sendsinitializestill gets a per-session key exactly as before, since with no client name there is no tool to name. What it is not: the folder’s workspace key stays valid, so this is fleet management, not a security boundary. An older CLI, or a tool pointed straight atmcp.retasc.comwith the key from.mcp.json, is not stopped by it.
1.52.0
- RTSC-958 — a user never names an agent, so
--agent <name>is gone frominit,bind,key mintandjoin.
Full notes
Full notes
- RTSC-958 — a user never names an agent, so
--agent <name>is gone frominit,bind,key mintandjoin. Breaking if you scripted it; those commands now exit withunknown option '--agent'. Drop the flag and you get the same agent you would have got by omitting it. The flag looked like a label and was not one. An agent’s identity was{you}'s {runtime}and the roster grouped rows by that string, so a typed variant —"Em de Vries's claude-code 2", say — did not rename an agent, it forked a second one that kept its own finished count, spend and send-back rate forever. Nothing warned anyone, and there is no rename door in the product to undo it with. The help text made it worse by advertising the exact shape to vary:(default: auto, "{you}'s {runtime}"). Every custom name in the org that found this was junk or an accident: one accidental fork of the author’s own agent, three from a test an agent ran wrong, two fixtures. No other surface names an agent either — the Dash has no naming UI, and the setup-token flow always passed an empty name.retasc plan --agent <nameOrId>is a SELECTOR, not a name, and is untouched. The server keeps ACCEPTINGagentNameand ignores it, so 1.48 and 1.51 keep minting rather than failing validation — an older client simply gets the generated name. That half is already live, so this release removes the flag rather than changing behaviour.
1.51.0
- RTSC-962 — the proxy now reports git worktrees nobody claimed, so Retasc can see work an agent started without saying so.
Full notes
Full notes
- RTSC-962 — the proxy now reports git worktrees nobody claimed, so Retasc can see
work an agent started without saying so. Retasc fenced the END of work and nothing at
the START:
donerejects on a claim mismatch,reviewdemands a handoff, but the server never sees an agent edit a file — so an agent could build thousands of lines against an issue the queue still showed as free, and a second agent would read it as untouched and duplicate or decompose it. The server still reads no git. This process does: artsc-NN/<slug>worktree with no live claim behind it is reported, and the issue gets a provisional hold — visible onget_issue, withheld fromnext_issue/next_batch, lapsing after an hour. A hold is not a lease and never refuses an explicitclaim_issue, so the agent that forgot to claim always gets its own work back. Only ACTIVE worktrees count (uncommitted changes, or a commit in the last day), so an abandoned directory cannot park an issue; git runs asynchronously and off the critical path, so the census never delays a tool call; and each unclaimed worktree is announced once, not on every call. A server without the tool simply produces no holds.
1.50.0
- RTSC-901 —
retasc plan: which subscription pays for each of your agents, listed and set one line per (agent, harness). - RTSC-901 —
bindasks the same question at setup, but only when--runtimewas STATED.
Full notes
Full notes
- RTSC-901 —
retasc plan: which subscription pays for each of your agents, listed and set one line per (agent, harness). Retasc cannot read this anywhere — no transcript field, telemetry attribute or environment variable carries it, and the only machine source sits behind the human’s own keychain — so it is asked for once and kept. The options are READ FROM THE SERVER on every run, never compiled in: a tier a vendor ships this morning is on the list this afternoon, on the build you already have. - RTSC-901 —
bindasks the same question at setup, but only when--runtimewas STATED. That flag defaults toclaude-code, which is a fine label for a row and the wrong subject for this question:retasc setupwires every harness on the machine, so asking “which Claude plan?” of someone setting up Codex records a fact about the wrong product. Left unstated, the question falls to the first MCP handshake, which knows which harness actually connected. - A non-interactive run answers nothing rather than defaulting. A plan nobody chose reads on the Agents page exactly like one they did.
1.49.1
- RTSC-879 — the proxy sends NO
Authorizationheader when it has no key, instead ofBearerwith nothing after it.
Full notes
Full notes
- RTSC-879 — the proxy sends NO
Authorizationheader when it has no key, instead ofBearerwith nothing after it. An empty bearer is not a weaker credential, it is a malformed one, and where a keyless proxy now runs that difference decides whether the thing works at all: in a Claude Code cloud container the documented way to supply a credential is an environment API credential, which Anthropic’s egress proxy injects as anAuthorizationheader after the request leaves the VM — and which also lets the request through a network allowlist that would otherwise refuse the host. Injection wants the header absent, and whether it overwrites one already present is undocumented, so sending an empty bearer staked the whole path on undocumented behaviour. With a key present nothing changes.
1.49.0
- RTSC-879 — a committed
.mcp.jsonnow namesnpx -y @retasc/cli@<version> mcp-proxyinstead of a bareretasc, so it starts on a machine that is not the one that wrote it. - RTSC-879 —
retasc bind --jsoncan now sign in from a container. - RTSC-879 —
retasc doctorno longer installs a package to check a marker. - RTSC-879 — the repo’s own committed
.mcp.json, and the marker blocks published inweb/auth.mdand the agent-skill, now show the npx form. - [no-issue] — test fix: the setup-hook test pinned
RETASC_HOMEto a temp dir.
Full notes
Full notes
- RTSC-879 — a committed
.mcp.jsonnow namesnpx -y @retasc/cli@<version> mcp-proxyinstead of a bareretasc, so it starts on a machine that is not the one that wrote it.portableLauncherused to pass an on-PATH resolution straight through on the belief that a bare binary “was at least portable”; it is portable only across machines that happen to have a global install. A container has none. Measured in a Claude Code cloud session on a fresh clone: the MCP server died atENOENT: Executable not found in $PATH: retascbefore it could do anything else. Startup on the shared marker now pays npx resolution (about 6s cold, ~1s off the cache); user-level configs, which never travel, keep the direct binary. - RTSC-879 —
retasc bind --jsoncan now sign in from a container. An agent-driven bind takes the DEVICE grant instead of the browser one, in two steps: the first call prints an approve URL and an eight-character code and exits, the human approves on any device, and running the same command again resumes the same grant and finishes. Previously an agent got the browser door, which redirects to127.0.0.1on the machine running the CLI — unreachable when the human is somewhere else, which in a cloud container they always are. New continuable outcome stateSIGN_IN_PENDINGso an agent can tell “waiting on a click” from “nothing has started” and does not issue a second code that invalidates the one its human is reading. CI andRETASC_NO_BROWSERstill refuse immediately: neither has anyone to approve anything. - RTSC-879 —
retasc doctorno longer installs a package to check a marker. For an npx marker it probesnpx --versionrather than executing the pinned package spec, which was a registry fetch on every run and reported “your agent CANNOT start Retasc” for a healthy marker whenever npm was unreachable. Its remedy line is corrected too: a global install can no longer change whatbindwrites into a shared marker. - RTSC-879 — the repo’s own committed
.mcp.json, and the marker blocks published inweb/auth.mdand the agent-skill, now show the npx form. They were the bare binary, which is the exact thing this release stops emitting. Those hand-written blocks say@latestrather than a pinned version on purpose:release:clipublishes frommainAFTER a merge, so a committed marker pinning the version being released would 404 for every fresh clone in the window between the two — trading this release’s ENOENT for an E404.bindstill writes the pinned form, which is correct because it only ever names a version that already exists. - [no-issue] — test fix: the setup-hook test pinned
RETASC_HOMEto a temp dir. It fell through to the real home directory, so it passed on a clean CI runner and failed on any machine that had actually runretasc setup.
1.48.1
- RTSC-878 —
retasc doctorno longer condemns the entryretasc setupwrites.
Full notes
Full notes
- RTSC-878 —
retasc doctorno longer condemns the entryretasc setupwrites. Its machine-global check dated from RTSC-91, when every top-levelmcpServers.retasccarried a key or a workspace id and so routed every unbound folder to one org; presence alone was a correct test for that. RTSC-780 then made one global entry mandatory, the keylessautomarker, which carries no identity at all, and the check was never taught the difference. Doctor therefore printed✗ GLOBAL Retasc server registeredat the marker and offeredclaude mcp remove -s user retascas the fix, which strips Retasc from every folder without a binding of its own. It cost a customer a day. - The check now reads the entry’s identity:
RETASC_WORKSPACE=autowith no key resolved is reported as correct and named, so someone who just ransetupcan see that what it wrote is what belongs there. Every other shape stays illegal, including a keyless entry that names a realws_workspace, which still routes every unbound folder to one binding. - The exemption is not granted on the sentinel alone.
parseServerEntryreadsRETASC_WORKSPACEbefore it looks for a key in anAuthorizationheader or inRETASC_MCP_KEY, so an entry carrying both theautosentinel and a real credential parses as an innocent keyless marker; judging the parse alone would have exempted a live machine-global registration pointing every unbound folder at that key’s org. The raw entry is examined too, and anything carrying credential material or aurlof its own stays illegal whatever itsenvclaims.
1.48.0
- RTSC-859 —
retasc key mint --hosted: a key now says at mint what it is for.
Full notes
Full notes
-
RTSC-859 —
retasc key mint --hosted: a key now says at mint what it is for.workspace(the default, and what every bind door says explicitly) expects the local watchdog;hostedis for a cloud agent or CI that will never have one. Why: a workspace key sent raw to the server with no proxy is two things at once and the server cannot tell which, a hosted agent working as documented or a laptop whose config went stale. Both got the same advice on every claim, runbind, which a hosted agent cannot do. Withkindon the row, a hosted key is told the one true thing (renew your own leases) and shows “no folder (hosted)” on the Agents page as a fact rather than a gap; a workspace key with no runner gets the firm remedy, because for that row it is true. A key that said nothing, which includes every key minted before this and any barekey mintsince, keeps the old hedged text, since nothing on the row can say which it is.--hostedand--installare refused together: one wires a local watchdog, the other says there will never be one.retasc mcp install --no-watchdogis not deprecated (it writes exactly a hosted deployment’s config) but now says, once, that a key used that way should be minted--hosted.
1.47.0
- RTSC-864 —
retasc key mintnow prints every remote-key config block a hosted agent can paste, including the TOML one that did not exist.
Full notes
Full notes
-
RTSC-864 —
retasc key mintnow prints every remote-key config block a hosted agent can paste, including the TOML one that did not exist. A key is shown once, and until now that was allkey mintprinted. Anyone wiring a host that cannot run our proxy (a claude.ai connector, Codex Cloud, CI) had to invent the config, and for two of the six harnesses it was not inventable:tomlBlockemitted only the stdio proxy shape, so Codex and Grok users had nothing correct to paste at all. The newtomlHttpBlockfills that in, and all three blocks now print next to the key while it is still on the screen. The two TOML dialects are separate on purpose, and the reason is the dangerous part. Verified against both real binaries: Codex reads[mcp_servers.retasc.http_headers]and Grok reads[mcp_servers.retasc.headers], and each loads the other’s file without a warning while ignoring the header. The result is a server that reports itself enabled and configured, and returns UNAUTHORIZED on the first tool call. The blocks also say, next to themselves, that a key belongs in a user-scope config or a platform secret store and never in a tracked.mcp.json, which the repo’s pre-commit hook refuses anyway. Where a container DOES have an environment, the proxy withRETASC_MCP_KEYset is still the better door: it renews leases for you.
1.46.0
- RTSC-855 —
retasc doctorandretasc setupnow say whether the Retasc Agent Skill is installed on this machine, and print the one command that installs it.
Full notes
Full notes
-
RTSC-855 —
retasc doctorandretasc setupnow say whether the Retasc Agent Skill is installed on this machine, and print the one command that installs it. Wiring the MCP server gives an agent the ability to claim work. The skill is what tells it what a lease is, that a claim needs its own worktree, what a checkpoint is for, and how a handoff into review works. Nothing connected the two, so an agent could be fully wired and still have the tools without the manual, and no surface anywhere would mention it. The server cannot fill the gap: MCP carries a bearer token and no filesystem, so only something running on the machine can look. The hard part is not finding the file, it is not being wrong about it. A false “not installed” shown to somebody who followed our own instructions teaches them to distrust everything elsedoctorsays, so the check knows all three routes a skill really arrives by: global (~/.claude/skillsand each harness’s equivalent), project (theskillsinstaller’s DEFAULT scope, which lands in the working directory), and, for Claude Code, an installed plugin’s own folder, since/plugin install retasc@retascis one of the routes our public README offers and it writes none of the above. It honoursCLAUDE_CONFIG_DIR,CODEX_HOMEandGROK_HOMEfor the same reason. The printed command carries-gso it installs where the check looks. A harness whose convention we cannot verify is skipped rather than accused, one harness holding the skill silences the nudge for the rest, absence is reported withℹrather than✗, and neither command changes its exit code over any of it.
1.45.0
- RTSC-862 — a binding now covers every git worktree of the repo it was made in.
Full notes
Full notes
-
RTSC-862 — a binding now covers every git worktree of the repo it was made in.
findBindingByPathwalks up from the current directory looking for a bound folder and stops at the first.git, which is what stopsretasc bindin~from silently binding every project beneath it. But.gitis a FILE at the root of every worktree, so that stop fired on the first step inside one: every worktree resolved to nothing, with no error and no hint, and the tools were simply absent. Repos whose workflow creates a worktree per task (this one included) hit it constantly, and the rational workaround — paste a raw key into a config that works everywhere — silently costs the watchdog, session rows, transcripts and the folder name. “Same repository” is decided by git’s common dir, the one directory every worktree shares, read from disk rather than by shelling out to git. A sibling repo checked out inside a bound directory still resolves to nothing, so the cross-org property RTSC-91 exists for is untouched. Binding a worktree deliberately still wins over its repo’s binding.retasc doctorsays when a folder resolved this way, instead of the old warning that the id “was bound at a different folder” — advice which, for a worktree, would have minted a second key and a second agent for one repo.
1.44.0
- RTSC-861 — the proxy now tells Retasc which CLI version it is.
Full notes
Full notes
-
RTSC-861 — the proxy now tells Retasc which CLI version it is. It rides on
mint_session_key, the one call every proxy already makes at startup, as an optionalcliVersionargument, so an older build that sends nothing still mints exactly as before. Why it matters: the update notice (RTSC-520) fires from apostActionhook onretasc <command>, and someone whose only contact with the CLI is the proxy their harness spawns runs no commands and never sees it. Three live setups were found on builds older than 1.41.0 with no way to find out. The server can now say so in the tool result, which reaches every harness, and with this version it can name the exact gap instead of inferring one from behaviour.
1.43.0
- RTSC-799 -
tidy,doneandclaimnow work out which branch is this repo’s trunk instead of assuming it is calledmain.
Full notes
Full notes
- RTSC-799 -
tidy,doneandclaimnow work out which branch is this repo’s trunk instead of assuming it is calledmain. Until this releasetidycompared every branch againstorigin/main, a name written into the source with no flag, no config and no way to see it. In a repo whose trunk ismasterthat comparison does not fail into view:git merge-base --is-ancestorexits 128 for an unreadable ref, the code tested only for 0, and so a broken lookup and an honest “not merged” produced the same word. Every branch readmerged: no, nothing was ever reapable, and becauseclaimcreates a worktree per issue and onlytidyremoves one, the worktrees accumulated with nothing printed to say why. The team who reported it had thirty of them, built up over months, and could not tell from the outside whether the tool was wrong or their setup was. The trunk now comes fromorigin/HEAD, which is whatgit clonealready records and whatgit fetchre-records when it goes stale. Override it per repo withgit config --local retasc.base origin/develop, or per run with a new--baseontidyanddone. Read at--localscope on purpose: a plaingit config --getalso sees~/.gitconfig, and one machine-wide value would have quietly redefined the trunk in every repo on the box and outranked each repo’s ownorigin/HEAD. When the trunk cannot be worked out at all, that is an error naming the ref and every way to set one, because a command that cannot tell what merged means must not go on to report that nothing did. Ancestry now has three answers rather than two. “Git could not tell” is carried through as its own state, prints as?, and is never deleted, not even under--force: that flag means “unmerged, but I know the work landed elsewhere”, which is a judgement about a branch git actually reported on. Every run also prints the trunk it measured against, which is the line that would have turned this into a one-minute diagnosis, and a shallow clone warns, since missing history produces the same uniform “no”. Care taken with the sharp edges, because this turns a command that deleted nothing in those repos into one that deletes:- A stale
origin/HEAD, which outlives the branch it names when a remote renames its trunk and which git before 2.45 never repairs, falls through to the next candidate with a note rather than refusingclaim,tidyanddonein a repo that is otherwise healthy. donestill closes the issue when the trunk cannot be resolved. The control-plane close is the durable half and a CI checkout legitimately has noorigin/HEAD; the teardown is what needs a trunk, so that is what reports.- The first
--pruneafter upgrading asks once before deleting five or more branches, since it may be clearing months of work a team believed this command never touched. Scripts and the MCP auto-reap never see the question, and--yesskips it. claimfetches before it proves the base exists, so a just-pushed base still works, and resolves before taking the lease, so a claim is never held for a worktree that cannot be created. It also prints the trunk it branched from.- A bare repository is refused rather than operated on (the old path resolved to its parent directory), a detached HEAD no longer defeats the “that’s your current branch” guard, and the watchdog now logs a non-zero exit from an auto-reap instead of swallowing it.
- A stale
1.42.1
- RTSC-832 — the model now actually appears.
Full notes
Full notes
- RTSC-832 — the model now actually appears. 1.42.0 read it from the SessionStart
hook’s
modelfield, and Claude Code 2.1.261 does not send one: a captured payload issession_id,transcript_path,cwd,hook_event_name,sourceand nothing else. The row therefore filled in only after a/modelswitch, which is backwards. Claude Code does write the model on every assistant message in the transcript, so the proxy reads it from there instead, and every session gets one. - The read is bounded to the last 64KB: transcripts reach megabytes and this runs on a
throttle for the whole session. Reading backwards from the end also means a
/modelswitch is picked up by the same read, with or without the hook. - Only the model STRING is ever sent. The transcript path stays on the machine that wrote it, and nothing else from the file leaves it.
1.42.0
- RTSC-821 — a session now reports WHICH MODEL ran it.
Full notes
Full notes
- RTSC-821 — a session now reports WHICH MODEL ran it. The MCP handshake carries the
client’s name and version only, which is the CLI build and not the model, so this could
never have come from the connection:
retasc hook session-startnow passes the SessionStart payload’smodel(plusagent_typeandagent_idwhen the session is a subagent) alongside the transcript id, and the Dash’s session panel names it. - A second hook,
retasc hook model-switch, is wired onPostModelSwitch, so changing model mid-conversation reaches the Dash and it can say what the session started on.retasc setupwires both in one write. It deliberately does NOT touch the record’s timestamp: that is the window that stops an old record being adopted by a later session in the same folder, and a switch an hour in must not make an hour-old record look new. - The proxy keeps watching for a model change after the id is recorded, under the same bounded budget it already had, so a session that switches model on every turn still cannot make it talk to the server on every turn.
- Absent stays ordinary. Claude Code omits
modelfrom some payloads and Codex, Gemini, Cursor and OpenCode have no session hook at all, so a junk or missing model is dropped rather than raised, and never costs the transcript id it travelled with.
1.41.1
- RTSC-812 — no runtime change.
Full notes
Full notes
- RTSC-812 — no runtime change. Two comments in
cli/srcsaid project deletion did not exist:bindcalled an unwanted empty project something “that cannot be deleted (org-granularity delete only)”, and theimportconfirm said “there is no per-project delete”. An owner can delete a project from the Dash now, so both were wrong, and the import one sat on the last screen before an irreversible write.
1.41.0
- RTSC-825 — every workspace now carries the name of the folder it is bound to.
Full notes
Full notes
- RTSC-825 — every workspace now carries the name of the folder it is bound to. The
server never receives a path, so the name can only come from the machine that has one:
retasc bindsends it when the key is minted, and the watchdog proxy re-sends it at every session start, so a folder bound before this existed is named the next time an agent runs there. Only the folder’s own name travels, never the path above it, and it is the folder the BINDING names, so a session opened in a subdirectory still reports the bound folder rather than renaming the row to whatever directory it started in. The Dash shows it asworkspaceon the Agents page and on the Connect page, and shows nothing at all where a workspace has not reported one; a key retired before this shipped can never report one, so it stays blank.
1.40.0
- RTSC-820 — every session now tells Retasc which conversation it is.
Full notes
Full notes
- RTSC-820 — every session now tells Retasc which conversation it is.
retasc setupwires a Claude CodeSessionStarthook (retasc hook session-start) into~/.claude/settings.json, idempotently and beside whatever hooks you already have; the hook leaves the session’s id in the keystore dir, and the watchdog proxy picks it up and records it on its session key through a newrecord_sessiontool. Grok needs no hook: the proxy readsGROK_SESSION_IDat startup. The Dash’s Agents page then ends each session’s panel with the line that reopens it on the machine that ran it,claude --resume <uuid>. Only the NAME of the transcript is stored, never its contents and never a path. A session started beforesetupre-ran shows “none recorded” and names the missing hook.
1.39.4
- RTSC-810 —
retasc unbindrevokes the key it says it revokes. - RTSC-810 —
retasc bind --org-id X --project-id Ylearns the project’s prefix. - RTSC-810 — a key is named after the folder it was bound in, not after the project.
Full notes
Full notes
- RTSC-810 —
retasc unbindrevokes the key it says it revokes. It had two faults in one lookup, and each on its own was enough to leave the credential live: it destructured{ keys }offlistKeys, which returns a bare array, and it derived the folder’s key prefix with a 12-character slice while the server stores 14. An exact compare between a 12-character string and a 14-character one is never true, so every run sinceunbindshipped (RTSC-721) printed “not found server-side (already revoked, or the org is gone)” and moved on. The length now mirrors the server’s owndisplayPrefixOf, and the test reads that file, so the two cannot drift apart again. A session child key can no longer be the one revoked either: those are minted in memory by the proxy and never reach the keystore, so a match on one would mean revoking a key this folder does not own. - RTSC-810 —
retasc bind --org-id X --project-id Ylearns the project’s prefix. The provisioning form skipped every branch that looks a project up, so nothing knew the prefix: the key went out nameless, the keystore entry was written withoutprefixororgName, and the receipt card printed an empty one. It now resolves the project the same way the interactive pickers do. - RTSC-810 — a key is named after the folder it was bound in, not after the project.
The Keys list is the folder map (
client-a→ENG), which is what tells you which machine a credential belongs to;ENG keyon every row told nobody anything. Naming is the server’s job now, so no door can store a nameless key: the Dash mint form with the name left blank andretasc key mintwithout--nameboth fall back to the project’s own name rather than leaving the Dash to print “Unnamed key”.
1.39.3
- RTSC-801 — (security)
save_attachment_fileno longer reads a workspace’s own secrets, and no longer follows a file swapped in after it was checked.
Full notes
Full notes
- RTSC-801 — (security)
save_attachment_fileno longer reads a workspace’s own secrets, and no longer follows a file swapped in after it was checked. The proxy reads attachments on the agent’s behalf, which is what keeps the API key away from the model, and the cost of that is a read the harness never prompts on: whatever this path allows, an agent can upload to an issue every org member can read. Containment to the attach root was doing all the work and it was never the boundary it looked like, because the files worth stealing are not outside a workspace, they are in it..env.local, a legacy inline-key.mcp.jsonand.retasc/all live inside a normal root, so a prompt-injected “attach the config” was confined to exactly the secrets. Anything hidden below the root is now refused, dotfiles and dot-directories alike, along withsecrets.mdand, whereverRETASC_DIRputs it, the keystore itself. A root that contains your home directory (~or/, both previously accepted) is refused outright rather than carved down, since it makes every credential on the machine attachable, including every other workspace’s key. Those rules all judge a name, so a file with more than one hard link is refused too: path resolution follows symlinks but not links, andln .env.local notes.txtwould otherwise hand the check a name it has no reason to refuse while the bytes stay the same. The one carve-out is.retasc/attachments/, which is where the proxy writes files fetched byget_attachment_file: refusing that would be the proxy declining to read a file the proxy itself wrote, and downloading from one issue to attach to another is a real thing agents do. Anything hidden deeper inside it is still refused. The second half is a race: the path was resolved and stat’d, a fullprepare_attachment_uploadround trip went to the server, and only then was the file opened by path, so aln -sfin that window was followed on the read. The read now opens the fileO_NOFOLLOWand non-blocking, and proceeds only if the descriptor’s device, inode and size are the ones that passed the check. Opening non-blocking is not a detail: amkfifoin that same window would otherwise have blocked the proxy’s event loop outright, stopping every heartbeat it owes and stranding every lease it holds. Legitimate attachments, screenshots, logs and documents, are unaffected: none of them are hidden files.
1.39.2
- RTSC-808 —
retasc setupno longer writes OpenCode’s config into your real home whenRETASC_HOMEsays otherwise.
Full notes
Full notes
- RTSC-808 —
retasc setupno longer writes OpenCode’s config into your real home whenRETASC_HOMEsays otherwise. That variable exists so anything exercising the harness module cannot reconfigure the machine it runs on, and every other harness honours it; OpenCode readXDG_CONFIG_HOMEfirst and so ignored the override wherever that variable is set. The precedence is now override, then environment, then default, andXDG_CONFIG_HOMEis still honoured when no override is in play, because OpenCode really does read it. This is also why CI had been red onmainfor five consecutive merges. macOS does not setXDG_CONFIG_HOMEand GitHub’s Linux runners do, so the test guarding this passed on every developer machine and failed on every CI run, and no PR in the repo could show a green build.
1.39.1
- RTSC-800 — (security) a keystore-resolved key now travels only to the keystore’s own url, whether the competing url arrives in the
.mcp.jsonentry or in the environment.
Full notes
Full notes
- RTSC-800 — (security) a keystore-resolved key now travels only to the keystore’s own
url, whether the competing url arrives in the
.mcp.jsonentry or in the environment. 1.6.0 made this promise for the entry, which coveredclaim/tidy/donebut not the proxy: the proxy is the one caller that ever reads a committed marker, and it passes no entry at all. The harness copies the marker’senvblock into the spawned process, so aRETASC_MCP_URLplanted next toRETASC_WORKSPACEin a repo’s committed.mcp.jsonarrived as an environment url, outranked the keystore, and every teammate’s proxy sent its real workspace key to that host on the next start, during session-key minting, with no prompt. An environment url is now honored only alongside an explicitRETASC_MCP_KEY, where the key and the url share a trust domain. Nothing legitimate loses a path:bindalready stores the deployment’s url into the binding, so a self-hosted url is in the keystore before the proxy asks for it. This closes the url, and only the url. A committed marker also chooses thecommandthat runs and can set any other variable, so a marker you do not trust is code execution by the MCP config format’s own design, and the harness’s project-trust prompt is the boundary for that. What this removes is the one variant that reads as ordinary configuration in review.
1.39.0
- RTSC-793 —
retasc setupnow wires Cursor, OpenCode and Gemini CLI too, bringing it to six harnesses.
Full notes
Full notes
- RTSC-793 —
retasc setupnow wires Cursor, OpenCode and Gemini CLI too, bringing it to six harnesses. Until this release those three could be installed and running on your machine andsetupwould say nothing about them: it only ever named harnesses it already knew, so an unsupported one was not reported as skipped, it was invisible, and the receipt read as complete. That is the same silent half-install the previous release existed to end, one harness over. Each was admitted the same way the first three were, by checking a real installation rather than a config format from memory. The check that decides it is whether the harness starts its MCP server in the project directory, because the entry we write names no project and works out the folder for itself; one that started somewhere else would resolve every folder to the same wrong place with no symptom. All three passed. Cursor is wired by editing~/.cursor/mcp.jsondirectly, and carefully: that file is named .json but Cursor accepts comments in it, so we splice our entry in textually and leave every comment, every other server and everything else exactly where it was. OpenCode and Gemini are wired through their ownopencode mcp addandgemini mcp add, which is better than a writer of ours when a harness ships one that works: their file format stays their business. Note for Cursor users: it iscursor-agent, the agent, that gets the tools. Thecursorcommand is the editor launcher and is a different program. Also fixed: the setup receipt could run a path into the word beside it, printing~/.codex/config.tomlupdated, which read like a corrupted path in the one place whose job is to say plainly that everything worked.
1.38.2
- RTSC-789 —
bindkeeps this folder’s key instead of minting a new one on every run.
Full notes
Full notes
- RTSC-789 —
bindkeeps this folder’s key instead of minting a new one on every run. The guard meant to prevent that (RTSC-262) read the--org-id/--project-idflags, so it only ever fired for a provisioning script. The canonicalnpx @retasc/cli@latest bindleaves both undefined and could never reach it: pick the same org and the same project from the menu and it minted anyway, leaving the old key live. The check now runs where the target is known, after the pick, so how you got there stops mattering. A different org or project still mints, as it must. A kept key is resolved against the server before it is kept.bindclears a binding only when the server answersUNAUTHORIZED, so a folder can reach the reuse branch holding a key whose health is unknown: a 5xx, a proxy sign-in page, a refusal whose wording drifts. Keeping one of those would have stranded the folder for good, sincedoctorsends that exact state back tobind. It falls back to minting instead, which is the self-healing the old mint-every-run was providing by accident.
1.38.1
- RTSC-780 follow-up —
retasc initnow sets a folder up the same way every other door does.
Full notes
Full notes
- RTSC-780 follow-up —
retasc initnow sets a folder up the same way every other door does. 1.38.0 taughtbind,joinandbind --setupto wire every harness on the machine, butinitkept its own copy of that work: it minted a key and wrote a key-bearing entry for Claude Code and nothing else. So the one command named onboarding was the one that still left Codex with no Retasc tools, which is the exact failure 1.38.0 exists to end. Fixed by deleting the duplicate rather than teaching it the same trick. Everything after the org is nowbind’s job, which also meansinitwrites the keystore binding anautomarker resolves against, guards a folder that is already bound instead of overwriting it, and prints the same receipt.--scopeand--no-watchdogare gone frominit: both described the shape of an entry it no longer writes.-y/--yesand--no-installare there instead, matchingbind.
1.38.0
- RTSC-780 —
retasc setupwires Retasc into every MCP harness on the machine, once, andretasc bindnow runs it for you. - RTSC-781 —
--runtimenow says what it does.
Full notes
Full notes
-
RTSC-780 —
retasc setupwires Retasc into every MCP harness on the machine, once, andretasc bindnow runs it for you. Until this release the CLI could wire exactly one harness: it spawnedclaude mcp add, and if that worked it stopped. Codex, Grok and anything else got nothing, which is why an agent bound to the same project as two working Claude Code sessions could sit there unable to claim a single issue. The entry we write names no project and carries no key. The watchdog proxy works out which project it is in from the directory it was spawned in, so one line in a global config is correct in every folder, and the folder still decides the org exactly as before. Adding a harness is one entry in the registry; Claude Code, Codex and Grok ship today, each verified against a real installation rather than a config format from memory. A folder you have not bound yet is now an ordinary state rather than a broken install, so it gets a real answer: the tool call comes back naming the folder and telling you to runretasc bindin it. Previously a keyless call surfaced as an authentication or network failure while the CLI’s own login was global and still fine, which reads as “the Retasc server is down” and sends you to check a server that is serving everyone else. The server cannot name your folder; the proxy runs in it, so it can. Which folder counts is bounded by the repository: a subdirectory resolves to its repo, and a repo checked out inside a bound directory resolves to nothing. Binding a directory must not quietly bind every unrelated project underneath it. Existing markers are untouched: one naming a workspace id keeps resolving through that id, and keeps priority over the folder. -
RTSC-781 —
--runtimenow says what it does. It sets the agent’s label in the Dash, and it never chose where config was written, but it is offered on the commands that install MCP config and documented with a list of harness names, sokey mint --runtime codex --installnamed Codex, wired Claude Code, and said nothing. The help text says label, and the commands that mint a key and write a key-bearing entry now say plainly that they write for this folder only, that a key never belongs in a machine-wide config, and thatretasc setupis what wires the harness you named.
1.37.0
- RTSC-749 —
retasc triagereads and approves work filed from outside your org.
Full notes
Full notes
- RTSC-749 —
retasc triagereads and approves work filed from outside your org. Work that arrives through a GitHub or GitLab connector is written by whoever can file on that repo, and since RTSC-746 no agent can pick it up until a person has read it and approved it. This is that decision from the terminal:retasc triagelists what is waiting,retasc triage RTSC-42prints the full body and then asks. It is deliberately hard to automate, because the CLI runs where coding agents run: there is no--approveflag, the command refuses to run without an interactive terminal, and confirming means retyping the issue id rather than pressing y. Saying no is as cheap as saying yes (typereject) — the safe answer must never be the expensive one. The Dash stays the recommended surface: an agent that can drive a real PTY on your machine could drive this command too, and only logging the CLI out takes that away.
1.36.1
- RTSC-645 —
retasc gate installno longer throws away your edits.
Full notes
Full notes
- RTSC-645 —
retasc gate installno longer throws away your edits. It rewrites the commit-msg hook and the Action on every run, so a gate you had customized (say, one that also checks the branch number) used to vanish behind a green ”✓ Updated” with nothing saying so. Generated files now carry a hash of their own contents, so a later run can tell “still exactly what we wrote” from “someone changed this”. A changed file is copied to.bakfirst, keeping its permissions, and the run tells you where the copy went; a second round of edits goes to.bak.2rather than overwriting the first. Untouched files are replaced silently as before, including when you re-key the gate to a different prefix, so the common path gained no prompts and no flags.
1.36.0
- RTSC-520 — the CLI now says when it is out of date.
Full notes
Full notes
-
RTSC-520 — the CLI now says when it is out of date. There was no version check
anywhere in
cli/, so a global install went stale silently and stayed that way for as long as the machine lived — and a stale CLI does not merely lack features, it lies: its copy describes SERVER behaviour, so 1.11.0 kept telling people a decline “covers the whole org, including later migrations” long after RTSC-507 made that false, and 1.10.0 had no Google door, so it sent Google-only humans through GitHub and minted them a second identity. After any login-gated command an outdated build now prints one line naming both versions and asks whether to update:Notify then ask, never a silentnpm i -g: interactive terminals only (no TTY prints the notice and nothing else, so scripted runs are unchanged), at most once a day with a decline remembered, and a failed install — EACCES on a root-owned prefix is the common one — reports itself and namesnpm i -g @retasc/cli@latestwithout ever failing the command you actually ran. A successful update says it applies from your next command and that agents need restarting to pick up the new MCP server. The MCP proxy never prints it. The published version is resolved server-side from the npm registry, cached hourly, and handed down onmanage:me— a call every login-gated command already makes, so checking costs no round trip and no shared rate limit, and no release step can forget to update it. An optionalRETASC_CLI_MIN_HONESTmarks the oldest version whose copy still matches the server; below it the notice says so plainly, because “a newer version exists” and “what this build just told you may be false” are different problems.
1.35.2
- RTSC-743 — the last CLI replies that answered a person with a machine shape now answer in sentences.
Full notes
Full notes
- RTSC-743 — the last CLI replies that answered a person with a machine shape now
answer in sentences. A failed MCP request used to paste 200 characters of the raw
response body after the status, which on that endpoint is either a JSON-RPC envelope or,
when the failure lands at Cloudflare rather than in Convex, a page of HTML; it now says
what the status means and what to do about it, and reads the body for a message rather
than printing it. A reply that is not JSON at all (a proxy error page, a captive portal)
named a JSON parser’s position; it now names what actually answered.
retasc loginstringified GitHub’s whole OAuth payload into its error, buryingerror_description, the one field in it written for a person.whoamianddoctorcould surface a bare parser complaint fromresolveBinding, which is a poor answer to “what is broken?” from the two commands you run when something already is. Andretasc importprinted the summary with the wire payload’s own field names as labels —issuesCreated,commentsInserted,attachmentsRehosted— where it now prints Issues created, Comments and Attachments copied. Along the way,doctorandwhoamistop telling you to re-runretasc bindwhen the thing that answered was a proxy rather than Retasc: that failure carries no verdict on your key, and re-binding to fix it mints a new one for nothing.
1.35.1
- RTSC-478 — a network failure now names its own cause.
Full notes
Full notes
- RTSC-478 — a network failure now names its own cause. Node reports every failed
fetchas the literalfetch failedand puts the diagnosis onerr.cause.code, which the CLI read past, soretasc loginon a machine whose TLS trust store Node cannot read died on✗ fetch failedand nothing else. It now prints✗ fetch failed (UNABLE_TO_GET_ISSUER_CERT_LOCALLY)— a searchable string naming the real problem.cli/README.mdgains a troubleshooting entry keyed on that code, covering both causes: a corporate TLS-inspecting proxy, and a Homebrewopenssl@3keg that lost its CA symlink (the confusing one, sincecurlandnpmkeep working).
1.35.0
- RTSC-709 —
retasc issue showandretasc issue listread the queue from a terminal. - RTSC-709 —
retasc checkpointandretasc check-claimclose the claim lifecycle. - RTSC-709 —
donereads the issue back before it closes it. - RTSC-709 —
cli/README.mdnow records which MCP tools are deliberately Dash-and-MCP-only, and why, so their absence from the CLI reads as a decision rather than an oversight.
Full notes
Full notes
- RTSC-709 —
retasc issue showandretasc issue listread the queue from a terminal.tidyanddoneboth reason about issue status, and until now a human asked to accept their verdict had no way to see that status without opening the Dash. Both default to the currentrtsc-NN/branch’s issue,listtakes the same filters the MCP surface does (status, priority, label, author, assignee, SLA, limit), and both take--json. - RTSC-709 —
retasc checkpointandretasc check-claimclose the claim lifecycle.claim,next,releaseanddoneall existed, so a human could take work, hand it back and finish it, but could not record progress on it or answer the questionworkflow.mdsays to settle at runtime: is anything actually renewing my lease?check-claimprints the last renewal time and exits non-zero when you do not hold the issue, so a script can branch on it. - RTSC-709 —
donereads the issue back before it closes it. It was one word that closed an issue with no read path to confirm first, and it closed one whose PR was still open and unreviewed. It now prints the id, the title, the status transition and whether the branch is merged, and asks before closing on a TTY.--dry-runshows the readback and the teardown plan without touching anything,-yskips the prompt, and a non-TTY still closes, so scripts are unchanged. - RTSC-709 —
cli/README.mdnow records which MCP tools are deliberately Dash-and-MCP-only, and why, so their absence from the CLI reads as a decision rather than an oversight.
1.34.1
- RTSC-741 — a rejected write no longer costs you the lease.
Full notes
Full notes
- RTSC-741 — a rejected write no longer costs you the lease. The watchdog decided
when to stop heartbeating an issue by looking at the request you sent, never at whether
the server accepted it. So a
save_issuethat came back an error still dropped the issue from the heartbeat map while you were still holding it. Nothing renewed it after that, it ran out its half hour, and the reclaimer handed your work to another agent while you were in the middle of it, with no sign anything had gone wrong. Every drop now requires the call to have actually succeeded. The trigger is the new server-side rule that moving an issue intoreviewmust carry a handoff: a rejection on that write is the expected first attempt for any agent that has not learned the field yet, so a rare edge became a common one.
1.34.0
- RTSC-731 —
bindstops asking whether you want to join an org you are already in. - RTSC-731 — the invite questions hand back a value your agent can actually use.
Full notes
Full notes
- RTSC-731 —
bindstops asking whether you want to join an org you are already in. A teammate given access to a second project was shown “Join Retasc, or start your own workspace?”, with the second option one keystroke away from creating a duplicate organization that cannot be deleted from the terminal. Invites that only add projects to a membership you already have are no longer treated as onboarding, and no longer suppress the single-org shortcut. Your agent still hears about them, andsetup_statusnow asks about them in its own words, naming the project and the organization so “Retasc the org” and “Retasc the project” can’t be confused. - RTSC-731 — the invite questions hand back a value your agent can actually use.
Both onboarding questions told the agent to pass the chosen answer to
accept_invite’sorgflag, then offered “join” as that answer — so an agent doing exactly what it was told got “no invite to join is waiting for you”, while one that ignored the instruction and read the prose succeeded. The accept option now carries the organization itself.
1.33.0
- RTSC-722 — the setup questions arrive as a matrix your agent can actually render.
Full notes
Full notes
- RTSC-722 — the setup questions arrive as a matrix your agent can actually render.
1.32.0 sent three of the four as free text, and a picker cannot draw a question with no
options, so the whole set collapsed back into the numbered list in prose that RTSC-720
existed to remove. They now carry defaults derived from the folder you are standing in:
in
~/the eggyou getThe Egg,The Egg,EGG, and the folder confirm, four clicks instead of three typed answers. Every question keeps a “Something else” escape. Folders that name nothing about the work (/Users, your home directory,src, a dotfile, anything too long for the server to accept) suggest nothing and fall back to text, because a plausible wrong default is worse than no default when what you are confirming is which folder gets connected. Picking a project in an org that has more than four is a picker too now, instead of an unrenderable list of every project.
1.32.0
- RTSC-720 — when
bind --jsonstops to ask, it hands your agent the exact questions as data: what to call the workspace, the first project, its prefix, and a confirmation naming the precise folder about to be connected — with the flag each answer fills. - RTSC-721 —
retasc unbindexists. - RTSC-721 —
bindheals a dead binding instead of interrogating you about it.
Full notes
Full notes
- RTSC-720 — when
bind --jsonstops to ask, it hands your agent the exact questions as data: what to call the workspace, the first project, its prefix, and a confirmation naming the precise folder about to be connected — with the flag each answer fills. Your agent presents them instead of paraphrasing a status line, which is the difference between being asked “what should we call it?” and being told “you have no organization” by an agent waiting for you to notice. - RTSC-721 —
retasc unbindexists. It puts a folder back the way it was beforebind: the keystore entry, the MCP entry in either location it can live, and the agent key — revoked server-side when your session can, named for the Dash when it cannot. Until now undoing a binding meant hand-editing five places, one of them keyed by an id nothing surfaces, with the key left live throughout. It confirms before removing anything, names the absolute folder, and leaves your sign-in alone —retasc logoutis still its own decision. - RTSC-721 —
bindheals a dead binding instead of interrogating you about it. Come back months later, after the workspace was deleted or the key revoked, andbindused to ask “Replace it?” about a binding that no longer worked — a confusing question at the exact moment you were least equipped to answer it. It now says the binding is no longer accepted, clears it, and reconnects. Only on the server’s own refusal: a network failure still lands on the cautious path, because clearing a healthy credential to fix a problem your machine does not have would be worse than asking.
1.31.1
- RTSC-715 — setup no longer finishes by wiring a
retasccommand that is not there.
Full notes
Full notes
- RTSC-715 — setup no longer finishes by wiring a
retasccommand that is not there. Run asnpx @retasc/cli@latest bind, the CLI asked whetherretascwas on your PATH and got yes, because npx puts its own cache directory on the PATH of whatever it runs. So the answer was true whilebindran and false the moment it exited, and your agent started withENOENT: Executable not found in $PATH: "retasc"after a setup that had reported success. It now checks that the command it found will still resolve afterwards, and falls back to a global install or a pinnednpxlauncher when it will not.
1.31.0
- RTSC-713 — your agent can set Retasc up for you.
- RTSC-713 —
bind --jsonreports what it did and what it still needs, one JSON object per line, and prints the approve URL the moment it exists rather than at the end. - RTSC-713 — a setup that paused is no longer dressed as a crash.
- RTSC-713 — sign-in no longer refuses merely because nothing is attached to a terminal.
- RTSC-713 — every outcome names the absolute folder it is about to connect, so a wrong one can be caught before anything is written.
- RTSC-691 —
retasc loginopens your browser instead of asking you to retype an eight-character code. - RTSC-691 — the code path stays for the places a browser round trip cannot work: inside a container, and over SSH, where the redirect would target
127.0.0.1on whichever machine opened the link and so could never reach the CLI waiting on the remote host. - RTSC-691 —
retasc release <RTSC-NN> --claim-token <token>exists. - RTSC-691 —
retasc bindprints “restart your agent” whether or not a human is watching. - RTSC-691 —
bindclears the credential-less bootstrap entry that would otherwise shadow the binding it just wrote, when the two land in different scopes.
Full notes
Full notes
- RTSC-713 — your agent can set Retasc up for you. It runs
binditself now, so nothing asks you to open a terminal and type a command: you paste one line into the chat, click Approve in the browser that opens, and restart your agent. The command it runs isbind --json, the door built for a machine to drive. - RTSC-713 —
bind --jsonreports what it did and what it still needs, one JSON object per line, and prints the approve URL the moment it exists rather than at the end. Your agent posts that URL to you as a link, which is what makes this work on a machine where the browser does not open by itself. - RTSC-713 — a setup that paused is no longer dressed as a crash. “Signed in, but you
have not said which project this folder is for” exits 0 and says exactly that; only a
real dead end exits non-zero. It used to exit 1 with
✗ UNAUTHENTICATED, and an agent reading that reasonably concluded setup had failed and stopped, one question short of done, holding a session that had actually worked. - RTSC-713 — sign-in no longer refuses merely because nothing is attached to a
terminal. It asks whether a browser can be reached, which is the thing that actually
matters. SSH, containers and CI still refuse, and still refuse fast: over SSH the
approve link targets
127.0.0.1on whichever machine opened it, so it could never reach the CLI waiting on the remote host. - RTSC-713 — every outcome names the absolute folder it is about to connect, so a wrong one can be caught before anything is written. A wrong folder has no symptom otherwise: the agent still calls in and the Dash still looks healthy.
- RTSC-691 —
retasc loginopens your browser instead of asking you to retype an eight-character code. Click Approve once and you are signed in, and you pick GitHub, Google or a passkey in the Dash where you are usually signed in already, instead of answering that question in the terminal. The device flow is still there and still works; it is the fallback now rather than the only door. - RTSC-691 — the code path stays for the places a browser round trip cannot work:
inside a container, and over SSH, where the redirect would target
127.0.0.1on whichever machine opened the link and so could never reach the CLI waiting on the remote host.RETASC_NO_BROWSER=1forces it everywhere. - RTSC-691 —
retasc release <RTSC-NN> --claim-token <token>exists. Two error messages inretasc claimhad been telling people to run it for a while, and it was not a command. The token is the one printed when you claimed; the server fences on it, which is what stops one agent releasing another’s work. Releasing leaves your worktree and branch alone —retasc tidyis what reaps those. - RTSC-691 —
retasc bindprints “restart your agent” whether or not a human is watching. It was suppressed when output was not a terminal, which is exactly when an agent is the one reading it and the one that has to pass the message on. - RTSC-691 —
bindclears the credential-less bootstrap entry that would otherwise shadow the binding it just wrote, when the two land in different scopes.
1.30.0
- RTSC-681 — your agent can read a file you attached to an issue.
- RTSC-681 — downloads land under
.retasc/attachments/in your workspace, one folder per attachment, never overwriting anything and never following a symlink, in a directory that ignores itself so a customer’s certificate cannot be committed by accident.
Full notes
Full notes
- RTSC-681 — your agent can read a file you attached to an issue. Uploading has
been one call since 1.24.0; reading one back needed an API key the model does not
have and is told not to go looking for, so a certificate attached for an agent to
verify was something it could see the name of and nothing else.
get_attachment_filecloses it: name the attachment id, the proxy downloads it with the credential it already holds and hands back a path to read. Any size, and the bytes never pass through the model’s context. - RTSC-681 — downloads land under
.retasc/attachments/in your workspace, one folder per attachment, never overwriting anything and never following a symlink, in a directory that ignores itself so a customer’s certificate cannot be committed by accident. There is no destination argument on purpose: a write the proxy performs skips the prompt your harness would otherwise show you, so it only ever writes to the one place it owns. Copy the file where you want it and your normal tools ask you first, which is the point.
1.29.0
- RTSC-672 — every command we hand out now says
npx @retasc/cli@latest. - RTSC-672 — a first-run failure names the build that produced it, so “it still doesn’t work” and “you’re running last week’s CLI” stop looking identical.
Full notes
Full notes
- RTSC-672 — every command we hand out now says
npx @retasc/cli@latest. npx caches by spec, so a barenpx @retasc/clican keep serving whatever version you first ran — which meant the people most likely to re-run a command, the ones who hit a bug and were told it was fixed, were exactly the ones liable to be served the broken build again.@latestis a tag, not a pin: it re-resolves every time and can never go stale, where a version number written into docs absolutely can. - RTSC-672 — a first-run failure names the build that produced it, so “it still doesn’t work” and “you’re running last week’s CLI” stop looking identical.
1.28.0
- RTSC-676 — signing in opens your browser.
- RTSC-676 — the finish screen’s closing lines are flush left, and it ends with a blank line instead of welding the shell prompt to the last thing you read.
Full notes
Full notes
- RTSC-676 — signing in opens your browser. It used to print a URL and an
eight-character code and leave you to switch windows, navigate, and retype it. Now the
page opens for you, pre-filled when the provider supplies RFC 8628’s complete URL. The
URL and code are still printed first and always: there is no browser inside a container
or over SSH, which is where
bindruns most, so the browser is a convenience layered on top and never the only way through. A missingxdg-openchanges nothing.RETASC_NO_BROWSER=1turns it off. - RTSC-676 — the finish screen’s closing lines are flush left, and it ends with a blank line instead of welding the shell prompt to the last thing you read.
1.27.0
- RTSC-673 —
bindends by telling you what to do, not by dumping config.
Full notes
Full notes
- RTSC-673 —
bindends by telling you what to do, not by dumping config. It used to close on fourteen lines of MCP JSON plus “(Claude Code CLI not detected)”: a block instructing you to paste something we had just written to disk for you, and a note that reads like a fault on a screen whose whole content is that everything worked. Between them they buried the one thing a new owner needed. Now it prints a receipt card — org, project, where the key went, what landed in your repo — and then says to start your agent. The closing lines follow the project: an empty one invites you to describe what you’re building, a project with work in it tells you to say “next issue”. The JSON still prints when the marker could not be written anywhere, which is the case it exists for.
1.26.0
- RTSC-670 —
retasc bindcan sign you in again. - RTSC-671 — errors name the command you actually ran.
Full notes
Full notes
- RTSC-670 —
retasc bindcan sign you in again. It has opened with the device flow since 1.20-era, but a leftover session guard in the command wrapper exited first, so on a machine that had never signed in — the only state a new owner is ever in —bindprinted “Not signed in” and stopped. Owner onboarding dead-ended at its first documented command, on every release for three weeks. The guard was correct when it was written and became redundant the momentbindgrew its own sign-in; nothing noticed because no test ran the CLI with no session. Four now do. - RTSC-671 — errors name the command you actually ran. Told to
npx @retasc/cli bindand then answered with “Runretasc loginfirst”, you were pointed at a binary that invocation never installs — a recoverable stumble turned into a dead end. Every “run X first” message now rendersnpx -y @retasc/cli@<version> …orretasc …to match how you started it.
1.25.0
- RTSC-669 — the invite project picker takes several projects.
Full notes
Full notes
- RTSC-669 — the invite project picker takes several projects. 1.24.0 shipped it
single-select, which left “two of these four” expressible nowhere: the workaround —
repeating
--project-id— needs ids that nothing in the CLI lists, which is the gap the picker existed to close. Answer2,4(or2 4) and the invite grants exactly those. Naming every project collapses to all projects, so the grant follows the org as it grows rather than freezing today’s list.1) All projectscan’t be combined with individual ones: that’s a contradiction about the widest grant there is, so it re-asks instead of guessing which half you meant.
1.24.0
- RTSC-667 —
retasc members inviteasks instead of demanding ids. - RTSC-666 — the PROJECTS column in
retasc members listcomma-joins, so two projects read asXTRO, XTRO Marketingrather than running together. - RTSC-664 — invite someone to one project, not the whole org.
Full notes
Full notes
- RTSC-667 —
retasc members inviteasks instead of demanding ids. It used to require--org-id, and the new--project-idmade that worse: nothing in the CLI lists project ids, so a scoped invite meant fetching one from the Dash. Run it with no flags in a terminal and it asks which org (only the ones you can actually invite into) and which projects, with All projects as the first option rather than the thing you get by not answering. It asks nothing when there is nothing to choose — one eligible org, or fewer than two projects — and a script with no TTY behaves exactly as before. The flags still work and still win. - RTSC-666 — the PROJECTS column in
retasc members listcomma-joins, so two projects read asXTRO, XTRO Marketingrather than running together. - RTSC-664 — invite someone to one project, not the whole org. Membership was org-level,
so anyone you invited read every project you had.
retasc members invitenow takes--project-id <id>, repeatable, and the invitee lands scoped to exactly those projects. Omitting it still grants every project, so an existing script keeps its behaviour untouched and an org that never scopes anyone never notices this shipped.retasc members listgains a PROJECTS column naming what each code confers, withAllfor the unscoped ones — an unscoped invite is the WIDEST grant, and a column that rendered it as a dash would read as “none”. Enforcement is server-side at every door, agent auth included: a key whose project leaves its principal’s scope stops authenticating on its very next call.
1.23.0
- RTSC-660 — the proxy attaches files for you.
Full notes
Full notes
- RTSC-660 — the proxy attaches files for you. Attaching a file was the one Retasc write
an agent could not finish on its own: the server handed back an upload URL and told the
caller to POST the bytes with “your API key”, which under MCP lives in the proxy, not in
the model. Agents were resorting to reading the key out of
~/.retasc/bindings.json, and harnesses were blocking that as credential harvesting. The proxy now servessave_attachment_file(issue, path, title?)itself: it reads the file and uploads it with the key it already holds, so nothing about the credential reaches the model and the bytes never pass through its context. Readable paths are confined to a root —RETASC_ATTACH_ROOTif set, otherwise the proxy’s working directory — compared after resolving symlinks on both sides, with.gitand non-regular files refused, because reading a file on the agent’s behalf skips the harness’s own file-access prompt. Every accepted read is logged to stderr with its resolved path. Calls that passcontentBase64instead are forwarded to the server untouched.
1.22.0
- RTSC-646 — the watchdog now says when it is not renewing a lease.
Full notes
Full notes
- RTSC-646 — the watchdog now says when it is not renewing a lease. Its lease set is
in-memory and built only from claim traffic this proxy saw, so a claim made in another
terminal, over direct HTTP MCP, or by a previous proxy before a harness restart was renewed
by nobody — silently, until the reclaimer took the issue away mid-build. Touching such a
lease now prints a warning naming the issue and what to do about it (
release_issueis exempt: it ends a lease rather than needing one). A heartbeat rejected asUNAUTHORIZEDis also called out loudly, once: that means the session’s credential died, not the lease, so every claim stops renewing at the same moment and each lapses at its own expiry. The proxy keeps tracking and keeps trying, because re-minting the key inside the TTL recovers all of them. Themcp install --watchdogtext no longer stops at “no per-claim heartbeats” — it names both bounds: the proxy must be running, and it only renews claims it saw this session make.
1.21.1
- RTSC-643 —
retasc gate installkeys the gate to this folder’s project, not the machine-wide default.
Full notes
Full notes
- RTSC-643 —
retasc gate installkeys the gate to this folder’s project, not the machine-wide default. It used to readdefaultProjectPrefix(stamped by whichever project you last ranretasc initfor), so in a bound folder it could install a commit gate keyed to a different project — rejecting every valid commit — while reporting success. It now asks the folder’s own binding first (whoamiover the workspace key, or the keystore’s cached prefix offline; a subdirectory run checks the git toplevel too), prints where the prefix came from, warns when the global default disagrees, and only uses the global default when the folder is genuinely unbound. Bound-but-unresolvable fails loudly instead of guessing.
1.21.0
- RTSC-527 — the re-import warning dates the last import in your timezone.
Full notes
Full notes
- RTSC-527 — the re-import warning dates the last import in your timezone. The day
was formatted from
toISOString(), which rolls back one east of Greenwich: at UTC+7 an import made five hours ago read as yesterday’s, which is the opposite of useful for a line whose job is to say how long ago it was. The Dash gained the same date in the same shape in this release, and moved onto the same durable per-source history the CLI already read, so the two surfaces now describe one import the same way.
1.20.0
- RTSC-561 — the org gained an admin role, and the CLI stopped refusing it.
Full notes
Full notes
- RTSC-561 — the org gained an admin role, and the CLI stopped refusing it.
retasc billinggated onrole !== "owner"client-side, so it would have refused an admin locally for a call the server allows. Owner-only copy inbindand the command help now names both roles.
1.19.0
- RTSC-495 —
retasc bind --setup <code>sets a folder up with no sign-in and nothing to answer, so an agent can do it on behalf of someone who does not use a terminal. - RTSC-532 — the agent says which folder it is in, and the key remembers.
Full notes
Full notes
-
RTSC-495 —
retasc bind --setup <code>sets a folder up with no sign-in and nothing to answer, so an agent can do it on behalf of someone who does not use a terminal. The Dash’s connect step now hands over a block you paste to your agent, with this command inside it. Everything the interactivebindwould ask was already answered in the browser, and the code carries those answers across. An agent’s shell is not a TTY, so the ordinary path refuses it outright at the first prompt.The code is single-use and lives ten minutes. The alternative — pasting a real API key into the prompt — needed no backend at all, but would have left a long-lived credential in an agent’s conversation history forever. A folder that is already connected is refused rather than silently replaced, and the refusal happens BEFORE the code is spent, so a mix-up costs nothing. -
RTSC-532 — the agent says which folder it is in, and the key remembers.
Binding the wrong folder used to look exactly like success: the agent still called in, so
the Dash went green, while the folder you actually work in had no Retasc in it. The prompt
now asks the agent to report its full path and wait before it runs anything, and the
confirmation names the real path instead of “This folder”.
The key it creates is named after that folder, so the Keys page shows which folder each
key belongs to (
client-a) instead of naming them all after the project (ENG key).
1.18.0
- RTSC-530 — setting up from scratch now asks where your work comes from, and imports it in the same command.
Full notes
Full notes
-
RTSC-530 — setting up from scratch now asks where your work comes from, and imports it
in the same command.
retasc bindused to offer one thing at the project step: name a new project. So someone arriving from Jira had to invent a project they didn’t want, runretasc importafterwards to get the one they did, and leave the empty one behind — and projects can’t be deleted individually.Pick a tracker and the import runs right there, then the folder binds to the project it created. Pick “start from scratch” and it behaves exactly as before. This is the same fork the Dash has always offered; importing isn’t a separate errand, it’s one of the ways a first project comes into existence. Only when the org has no projects — binding a second folder in an existing org is still just picking from the list. Declining at the import confirmation falls back to naming a project rather than abandoning setup: you still asked to bind the folder.
1.17.0
- RTSC-529 — the column mapping is a numbered picker, like every other prompt.
Full notes
Full notes
-
RTSC-529 — the column mapping is a numbered picker, like every other prompt.
It was the only one that made you type a word. Picking an org, a project, a source, a
list, a reviewer, a sign-in door or whether to install globally are all numbered lists
reading
Choose a number— and the reviewer picker appears two lines below this one, so a single import taught two input styles within four lines of output.Enter still takes the suggestion, now marked in the list rather than described beside it. Typing the word still works for anyone who has learned the vocabulary; it just isn’t what the prompt advertises.
1.16.1
- RTSC-528 — two things the first real
retasc importrun turned up.
Full notes
Full notes
-
RTSC-528 — two things the first real
retasc importrun turned up. The progress bar never appeared. It only started drawing once it had seen the run reported as running, and a 15-issue import finishes before that is ever observed, so the output went straight fromImporting…to✓ Imported.with a silent gap. It now draws the moment the run starts, sweeping while it waits for counts and switching to the real bar once they arrive. Still silent without a terminal and underNO_COLOR. The column prompt didn’t say what to do. It readto do [todo] (todo / doing / done / canceled):, where nothing is a verb, so the first person to run it had to guess that you type one of the words. Now:The suggestion is no longer repeated among the alternatives, which is what made the old line read as four equal options behind a mysterious bracket.
1.16.0
- RTSC-526 —
retasc importcatches up with the Dash on four things.
Full notes
Full notes
-
RTSC-526 —
retasc importcatches up with the Dash on four things. It warns before a second import. Re-importing does not duplicate anything, but it does re-sync: status, labels, title and body are replaced with whatever the source says now. Import from Jira, spend two weeks moving issues along in Retasc, re-import to pick up new tickets, and those two weeks of changes snap back. You now get told, with the date of the last import, before the confirmation. The run shows progress, as a bar that fills while it works, rather than a silent wait that looks like it has hung. The run is server-side, so pressing Ctrl-C out of boredom never stopped it anyway. The column list is grouped under your own tool’s sections (Not started, Active, Done, Closed) instead of arriving flat. On a twenty-column board that is the difference between scannable and a wall. Columns that were not mapped are named. If a column appears between the moment you set the mapping and the moment the import runs, its issues land intodo. They used to show as a number; now they are listed, with what to do about it.
1.15.0
- RTSC-524 — new command:
retasc import.
Full notes
Full notes
-
RTSC-524 — new command:
retasc import. Bring a Linear, Jira, Asana, ClickUp or Shortcut project across without opening a browser. This was the last thing the terminal could not do. Everything else — sign in, make or join an org, create a project, wire the folder, pull work — already worked end to end, but importing meant stopping and finishing in the Dash.It walks you through the source, your credentials, which team or project to take, and then what each of your columns means. That last part is the point, and it is asked rather than guessed: a tool lets its users name their own columns, so the only honest way to know what one means is to ask you. Pressing Enter accepts a suggestion derived from the column’s type in your tool, never its name — a column called “Rejected” that is really an in-progress lane maps todoing, notcanceled. A column mapped toreviewneeds a named reviewer, chosen per column, because two “awaiting acceptance” columns can belong to different people. Columns holding work nobody has started cannot be mapped toreviewat all, and the CLI says why rather than letting the server refuse it later. Your source token is never an argument. There is no--token, because anything passed that way lands in shell history and inpsoutput. Secrets are typed with echo off, or taken fromRETASC_IMPORT_<FIELD>for scripted runs. The run is confirmed before anything is written, and afterwards you are offered the imported identity the migration just created for you, through the same promptretasc joinuses.
1.14.0
- RTSC-523 — setup asks before installing anything on your machine.
Full notes
Full notes
-
RTSC-523 — setup asks before installing anything on your machine.
retasc bindandretasc joinare one command you paste and answer, and somewhere in the middle they rannpm install -g @retasc/cli. It said so, but it never asked. That is the only step in a folder-scoped command that changes the machine rather than the folder, and a shared npm prefix is exactly what plenty of developers keep clean.Both answers leave the folder bound identically. Option 2 is not a per-project install: nothing is written to the folder, so it needs nopackage.jsonand cannot fail for want of an npm project. Your answer is remembered, because it is a question about the machine and the machine has not changed by the time you bind a second folder. You are only asked when it would actually happen. Ifretascalready works, there is nothing to decide and nothing is said. Without a TTY it installs, exactly as before. That is deliberate rather than a leftover: when an agent runs setup on someone’s behalf, that person never typesretasc, but their agent starts the MCP server every session, and the on-demand route would cost them seconds and a network dependency every single time.--no-installonbindandjoindeclines without a TTY, for a developer whose own agent is doing the setup.
1.13.1
- RTSC-522 — the changelog is public, and five releases that were never written down now are.
Full notes
Full notes
- RTSC-522 — the changelog is public, and five releases that were never written down now are. It used to be unreachable by anyone who installs the CLI: it did not ship in the tarball, the README never mentioned it, and the source repo is private so the npm repository link 404s for the public. It is now at docs.retasc.com/changelog, and ships in the package. 1.1.0, 1.1.1, 1.1.3, 1.2.1 and 1.2.2 were published and never described. They are reconstructed here from their release commits and the issues they reference, so every version on npm now has an entry. Each one carries its publish date. Also fixed two npm-facing details: the package description still said “sign in with GitHub”, which stopped being the whole truth at 1.11.0, and the bug-report link pointed at a private repository that 404s for everyone npm showed it to.
1.13.0
- RTSC-521 — five commands stopped answering you with a JSON dump.
Full notes
Full notes
-
RTSC-521 — five commands stopped answering you with a JSON dump.
whoami,org create,project create,key listandmembers listprinted the raw payload.whoamiis the one people actually noticed, because it is the command you run to find out who you are:The one fact you wanted was a bracket to parse, next to a document id that means nothing. Now:key listandmembers listare aligned tables, and state reads as words: a revoked key saysrevokedrather than an epoch, and a spent invite shows no expiry date because the date stopped meaning anything. Auto-minted session keys are folded into a count instead of drowning the keys you can actually manage. Ids follow one rule: shown when a command takes them, dropped when nothing does. Soorg creategives you the org id and names the command that wants it, and never mentionsownerMemberId.--jsonon all five, emitting exactly what they printed before. Anything scripted against the old output keeps working by adding the flag.whoami’s binding block is unchanged. It was already the useful half.
1.12.0
- RTSC-519 —
retasc bindnow tells you it finished, and what to do next. - RTSC-507 — “none of these are me” now covers the tools you were asked about, not the whole org forever.
Full notes
Full notes
-
RTSC-519 —
retasc bindnow tells you it finished, and what to do next. It used to end on the last thing it did (“This folder is bound to org Acme / project ACM”) and stop. So the person who set up their own org was left reading a status line and guessing whether anything else was required, while the invited teammate, who arrives throughretasc join, was told. Both commands now end the same way:The restart half matters:.mcp.jsonis read when an MCP client starts, so an agent already open on that folder won’t see Retasc until it restarts — andbindis routinely run from inside a session that’s already there. The sentence lives in the tail both commands share, rather than a copy in each, so neither can lose it again. -
RTSC-507 — “none of these are me” now covers the tools you were asked about, not the
whole org forever.
Declining wrote one org-wide flag, checked before the list of imported people was even
read. So the January answer “I was never in ClickUp” — correct, and the cheapest possible
answer to give — meant that when the org migrated off Jira in June, where you did have
an account, you were never offered your placeholder. Not by
retasc identity, not byretasc join, not by the Dash, not ever. Your Jira authorship, comments and assignments stayed on a placeholder permanently, and only an owner could repair it. Claiming was already tracked per source, so someone who claimed their ClickUp identity was correctly re-asked at every later migration. Declining being the more final of the two was backwards. The decline row now names what it covers:andretasc identitysays so when nothing is left:That replaces wording saying the answer “covers the whole org, including later migrations” and pointing at an owner. It existed only to describe this bug. Needs the matching backend deploy. The copy above is a promise the server keeps, so publish this only afterconvex deployandmigrations:backfillDismissedSourceshave run. Against an older backend the CLI would say a later import will ask again, and it would not.
1.11.0
- RTSC-508 — you can now sign in with Google, not only GitHub.
Full notes
Full notes
-
RTSC-508 — you can now sign in with Google, not only GitHub.
Google sign-in shipped for the web Dash first, which left a one-way street: an account
created through that door reached the Dash and nothing else, because every login-gated
command here sat behind a GitHub-only device flow.
retasc loginwould start a GitHub device flow for an account GitHub had never heard of. That blockedbind,init,key,members,billingandidentityoutright — including the sign-in step insideretasc bindandretasc join, so a teammate invited through the web could not finish setting up their folder at all. With no flag,loginnow asks which door you use:After a successful sign-in the door is remembered, so later logins offer it back and Enter takes it:A default only ever appears once it is a recorded fact about you. On a first login there is none, and Enter is not an answer — because the wrong door is not a mistake you correct next time (see below). The remembered door is a default, not a lock: the other one is still one keystroke, and a typo re-prompts rather than being read as “the usual”.retasc login --google/--githubskip the question. A non-interactive run is unchanged: no prompt, GitHub, exactly as before. The same question appears insidebindandjoinwhen they sign you in for you. Signing in through the wrong door is not a typo you correct on the next run. Google and GitHub are deliberately separate identities — doors are linked only on a provider’s own immutable account id, never on a matching email address, because email is an account-takeover vector. So a Google sign-in by someone who already has a GitHub account here creates a second identity with its own membership, and the CLI cannot merge them back. That is why the question is asked rather than guessed, and why a non-answer re-prompts instead of falling through to a door. NeedsAUTH_GOOGLE_DEVICE_ID/AUTH_GOOGLE_DEVICE_SECRETon the deployment (operations/runbooks/google-device-client.md). Where they aren’t set, the CLI says so in one line and names GitHub as the way in meanwhile, rather than failing opaquely.
1.10.0
- RTSC-477 — new command:
retasc identity.
Full notes
Full notes
-
RTSC-477 — new command:
retasc identity. It shows the people a migration carried into your org and asks which one is you — the same questionretasc joinasks, on demand.joinasks this once, at the moment you accept an invite. Placeholders arrive with every migration, though, and claiming is per source tool rather than per person: the backend is built for “claim your ClickUp one now, your Jira one in six months”. So a team that onboarded by CLI a year ago had no terminal path to a later import’s history at all, and had to open the Dash or leave it on placeholders. Three narrower casesjoinskips on purpose are covered too:--yes, a non-interactive run, and--no-bind. It asks the question, so it needs a TTY and refuses without one rather than exiting 0 in silence. There is deliberately no--yesand noidentity claim <name>: linking someone pulls their authorship and their dispatch lane onto your account, irreversibly, with no CLI way back, so it is never answered on a script’s behalf. It also names the ending, whichjoindoes not. “Nothing waiting for you” and “you’ve already said none of these are you” are the same empty list from the inside and mean opposite things — the second is permanent and org-wide, so it still applies after a later migration that really did carry you across. That case now says so, and points at the owner, who is the only one who can undo it.
1.9.0
- RTSC-492 —
retasc joinis now the whole of an invited teammate’s setup, in one command run from the folder their agent will work in. - RTSC-498 —
retasc doctornow says which platform the CLI is actually tested on.
Full notes
Full notes
join: retasc join <code> used to redeem an
invite and stop. It now also sets up the folder you run it in — mints a key, writes a
binding, wires the MCP marker. --no-bind reproduces the old behaviour exactly, same
output and same exit code. Every other command is unchanged.join also no longer exits 1 telling you to run retasc login first. It starts the device
flow itself when there is no session, and refuses with the same message bind uses when
there is no TTY to run one in.-
RTSC-492 —
retasc joinis now the whole of an invited teammate’s setup, in one command run from the folder their agent will work in:It signs them in (device flow, only when there is no session), redeems the invite, offers them any identity a migration carried across, picks the project, makesretascdurable, mints a key, binds the folder and wires the MCP marker. It used to be three commands with an ordering trap in them, and the first of those three wasretasc login— which is not something you can tell someone who has installed nothing yet. The target case is that an invited teammate never opens the Dash at all. With no imports and one project, the only thing they type is the GitHub device code: every prompt is conditional on there being a real choice.- Takes a full invite link or a bare
rtscinv_…code. The code is what the server matches, so unwrapping a paste belongs at the edge that accepts typed input, not in the mutation that grants membership. - A member is never offered a project they cannot create (
createProjectis owner-only), and an org with no projects names what to ask an owner for instead of failing opaquely. - Imported placeholders are offered once per source tool, each behind an explicit
confirm, in the same words the Dash uses.
--yesskips that question and never answers it: claiming another person’s history is irreversible and has no CLI path back. --no-bindkeeps the old redeem-only behaviour for anything scripted against it.
bindandjoinnow share one implementation of the folder half — the project pick, the launcher ladder, the mint, the binding and the marker — so the fix that landed in 1.8.0 cannot drift back out of one of them. - Takes a full invite link or a bare
-
RTSC-498 —
retasc doctornow says which platform the CLI is actually tested on. Nothing in the product stated one: the READMEs never mentioned platforms andpackage.jsondeclares onlyengines.node, so someone hitting a problem on Linux or Windows had no way to tell their own mistake from a bug from a platform we never targeted. macOS is the only platform we run end to end. It’s a note indoctorrather than a line in the README on purpose. A README is read by everyone, and for the majority on macOS a standing disclaimer about platforms they aren’t using is noise they read before they’ve even installed.doctoralready knows which machine it’s on, so the people the limit applies to are exactly the people who see it, and on macOS nothing is printed at all. The note claims a limit, not a blockage: much of the CLI is plain Node and should work fine, andpackage.jsonstill carries noosfield, so installing is never refused anywhere Node 18+ runs. Windows and Linux are named as platforms we intend to support properly; anything else is told it’s untested without being promised a roadmap it isn’t on.
1.8.0
- RTSC-493 — the MCP marker no longer names a command that may not exist.
Full notes
Full notes
-
RTSC-493 — the MCP marker no longer names a command that may not exist. It
used to hardcode
retasc, which is only on PATH after a global install — but the Dash tells people to runnpx @retasc/cli bind, and npx unpacks into its own cache and installs nothing. So a bind printed every success line, really did bind the folder, and left an agent that could not start the Retasc MCP server at all. The failure surfaced later, somewhere else, as a broken server rather than a failed setup.bindnow resolves a launcher and proves it by running it before writing anything: it uses an existingretascif there is one, otherwise installs the CLI globally, and if that install lands where PATH cannot see it, the marker names the binary’s absolute path instead. Only when none of that works does it fall back to a version-pinnednpx, which is slower and needs the network — and if even that will not start, it says so outright rather than reporting success.retasc doctornow checks the same thing, so a folder bound by an older version reports why its agent cannot start and names the repair.
1.7.2
- RTSC-297 —
retasc bindno longer strands a new org silently.
Full notes
Full notes
- RTSC-297 —
retasc bindno longer strands a new org silently. It creates the org server-side before the project picker runs, so aborting at the project step (reachable by a typo since 1.x’s picker gives up after 3 bad answers) left an org behind with no project, no key, and no local binding — invisible from the CLI and quietly accruing on the billing rail. Bind now names the org and prints the exact resume command (retasc bind --org-id <id>) when it aborts before the workspace is bound. Selecting a pre-existing org and then aborting is untouched — nothing is reclaimed.
1.7.1
- RTSC-321 — the liveness watchdog now stops heartbeating an issue the moment it moves to
review(RTSC-257): the server releases the lease there, so the proxy no longer pings a dead lease until the next heartbeat fails.
Full notes
Full notes
- RTSC-321 — the liveness watchdog now stops heartbeating an issue the moment
it moves to
review(RTSC-257): the server releases the lease there, so the proxy no longer pings a dead lease until the next heartbeat fails. It is treated as a release, not a close — the branch/worktree is preserved for the review + PR (never reaped). The reviewer’s send-back (review → todo) still self-heals via the failed-heartbeat path, since it can’t be told apart from adoing → todoedit by request args alone.
1.7.0
- RTSC-306 —
retasc claim/retasc nextnow pull lane-scoped by default: only issues assigned to your principal or left unassigned, never another human’s work.
Full notes
Full notes
- RTSC-306 —
retasc claim/retasc nextnow pull lane-scoped by default: only issues assigned to your principal or left unassigned, never another human’s work. The old--mineflag is retired — that behavior is the default now. The new--all-lanesflag opts back into the whole ready pool when you need to pick up an absent teammate’s work. When your lane is empty but ready work is stranded in another lane, the CLI says so and points you at--all-lanesinstead of reading as “nothing to do”.
1.6.3
- RTSC-266 — README now links the setup page, the docs quickstart, and the parallel-agents guide instead of only the bare homepage.
Full notes
Full notes
- RTSC-266 — README now links the setup page, the docs quickstart, and the parallel-agents guide instead of only the bare homepage. npm package pages are a real entry point and only re-render on publish, so this ships as its own patch release. No code changes.
1.6.2
- RTSC-269 —
retasc bind’s org/project picker no longer treats a typo as “create new”. - RTSC-269 — the picker gives up after 3 invalid answers instead of looping, and a closed stdin (Ctrl-D, or a pipe running dry) now exits with an error rather than hanging.
Full notes
Full notes
- RTSC-269 —
retasc bind’s org/project picker no longer treats a typo as “create new”. Answering1)(a fumbled1) used to select nothing and fall straight through to creating a new org/project, which then hit the owner gate and surfaced as a redacted Server Error. Invalid input now re-prompts; only the explicit trailing option creates. The answer must be plain digits, so the non-canonical formsNumber()happily parses (0x4,4e0,+4,4.0) can’t reach the create branch either. - RTSC-269 — the picker gives up after 3 invalid answers instead of looping,
and a closed stdin (Ctrl-D, or a pipe running dry) now exits with an error
rather than hanging.
readline.question()never settles at EOF, so any prompt inbindcould previously wedge the CLI with no output and no exit.
1.6.1
- RTSC-263 — owner/member permission denials now print a readable reason and the next step instead of an opaque
Server Error. - RTSC-263 —
formatErrornow strips U+0085, U+2028 and U+2029 in addition to the ASCII control characters.
Full notes
Full notes
- RTSC-263 — owner/member permission denials now print a readable reason and the
next step instead of an opaque
Server Error. Hitting an owner-only command as a member reports “Owner role required.” with “Ask<owner>to create a project.” on its own line. The backend change does the work; the CLI already read the structured payload (1.5.0), so this release carries only the hardening below. - RTSC-263 —
formatErrornow strips U+0085, U+2028 and U+2029 in addition to the ASCII control characters. All three are mandatory line breaks, so a server message interpolating a user-controlled name could previously forge extra lines in terminal output.
1.6.0
- RTSC-262 —
doctorandwhoamino longer report “not bound” for a folder whose Retasc MCP is registered in Claude Code local scope (theclaude mcp adddefault — stored in Claude’s own config, not./.mcp.json). - RTSC-262 —
claim/tidy/doneresolve the key through the same entry selection, so the CLI can no longer say ”✓ bound” in one command and “No Retasc MCP key found” in another for the same folder. - RTSC-262 — the illegal-global-server check is now presence-based: a hand-added user-scope entry is detected in every shape (including keyless), and an unreadable
~/.claude.jsonreports “cannot verify” instead of a false all-clear. - RTSC-262 — honest failure modes: server-unreachable (timeouts, 5xx, rate limits) is no longer reported as a rejected key,
whoami/doctorrequests are bounded by a 10s timeout, and server-derived strings are stripped of control characters before printing. - RTSC-262 —
bindhardening: re-binding to the same org/project is an idempotent success (no key churn for provisioning scripts); replacing a different binding non-interactively without--yesnow fails loudly with exit 1 instead of silently succeeding as a no-op; a cloned repo’s committed marker no longer triggers the replace prompt (minting your own key under it is whatbindis for). - RTSC-262 — (security) a keystore-resolved key now only ever travels to the keystore’s own URL — a hostile
RETASC_MCP_URLplanted next to a committed secret-free marker can no longer redirect a teammate’s real key.
Full notes
Full notes
- RTSC-262 —
doctorandwhoamino longer report “not bound” for a folder whose Retasc MCP is registered in Claude Code local scope (theclaude mcp adddefault — stored in Claude’s own config, not./.mcp.json). The binding lookup now reads both legal per-folder locations, and when both exist the local-scope entry wins, matching Claude Code’s documented precedence (local > project) — doctor names the org the agent actually uses, and warns when a differing./.mcp.jsonmarker is being shadowed. - RTSC-262 —
claim/tidy/doneresolve the key through the same entry selection, so the CLI can no longer say ”✓ bound” in one command and “No Retasc MCP key found” in another for the same folder. - RTSC-262 — the illegal-global-server check is now presence-based: a hand-added
user-scope entry is detected in every shape (including keyless), and an unreadable
~/.claude.jsonreports “cannot verify” instead of a false all-clear. - RTSC-262 — honest failure modes: server-unreachable (timeouts, 5xx, rate limits) is
no longer reported as a rejected key,
whoami/doctorrequests are bounded by a 10s timeout, and server-derived strings are stripped of control characters before printing. - RTSC-262 —
bindhardening: re-binding to the same org/project is an idempotent success (no key churn for provisioning scripts); replacing a different binding non-interactively without--yesnow fails loudly with exit 1 instead of silently succeeding as a no-op; a cloned repo’s committed marker no longer triggers the replace prompt (minting your own key under it is whatbindis for). - RTSC-262 — (security) a keystore-resolved key now only ever travels to the
keystore’s own URL — a hostile
RETASC_MCP_URLplanted next to a committed secret-free marker can no longer redirect a teammate’s real key.
1.5.0
- RTSC-261 — backend failures you’re meant to act on now print what actually went wrong instead of
✗ Server Error.
Full notes
Full notes
-
RTSC-261 — backend failures you’re meant to act on now print what actually went
wrong instead of
✗ Server Error. Convex masks any plain server throw in production, so every precondition — a consumed invite code, an expired one, a suspended membership — reached the terminal as the same opaque string.retasc joinwas the worst case: an invited teammate hit an unreadable wall at the very first step. Errors now carry a machine-readablecode, a readablemessage, and an optionalhintprinted on its own line:This release covers invite redemption; the remaining surfaces (auth/key problems, not-found lookups, billing gating, import/restore) follow. Internal invariants stay masked deliberately — those are our bugs, not yours, and their messages describe server state. Upgrade before your teammates redeem invites: an older CLI can’t read the new payload and prints it as raw JSON.
1.4.0
- RTSC-279 — new
retasc billingcommand: the org’s whole billing picture in the terminal instead of only in the Dash. - RTSC-279 — (server-side, no CLI change) the MCP usage meter now reports two clearly-named figures instead of one misleading
wouldBeBillUsd:lifetimeMeteredEstimateUsd(all-time activity repriced at today’s rate card — a diagnostic, not an amount owed) andpendingUsd(what is actually owed right now, the same figure the Dash shows).
Full notes
Full notes
- RTSC-279 — new
retasc billingcommand: the org’s whole billing picture in the terminal instead of only in the Dash. Prints the subscription and spending caps, what’s owed right now, and the charge + confirmed on-chain payment history — both org-scoped across every payment link the org has ever used, so changing payment link no longer hides prior history. Owner-only (it reuses the same owner-gated functions the Dash renders; the client-side role check is UX, the server still gates).--org-idselects the org when you belong to more than one,--jsonemits the raw payload. Payments are a live read of Xenarch’s authoritative records and degrade to a note rather than failing the command. - RTSC-279 — (server-side, no CLI change) the MCP usage meter now reports two
clearly-named figures instead of one misleading
wouldBeBillUsd:lifetimeMeteredEstimateUsd(all-time activity repriced at today’s rate card — a diagnostic, not an amount owed) andpendingUsd(what is actually owed right now, the same figure the Dash shows). A newbilling_summaryMCP tool exposes the full billing detail to agents whose human principal owns the org.
1.3.2
- RTSC-250 — serialize
patchConfigunder a cross-process advisory lock so concurrent CLI/MCP processes can’t lose an update.
Full notes
Full notes
- RTSC-250 — serialize
patchConfigunder a cross-process advisory lock so concurrent CLI/MCP processes can’t lose an update. Previously a lock-free load-modify-save meant adefaultOrgId/defaultProjectPrefixwrite racing the hourly token refresh could write back the old single-userefreshToken, breaking the next refresh and forcing a device re-login a non-interactive context can’t perform. The lock re-reads the freshest config inside the critical section and stamps a nonce so a stolen-from holder never deletes the new owner’s lock. Also sweeps orphaned.config.json.<uuid>.tmpfiles left by a hard kill, age-gated so a concurrent writer’s in-flight temp is never touched.
1.3.1
- RTSC-179 — atomic config write (temp file + rename) so a reader never sees a truncated
config.json; addsRETASC_DIRsupport. - RTSC-178 — token refresh now classifies transient backend errors vs a genuinely expired refresh token, so a one-off backend blip no longer drags a valid session through a full device re-login.
1.3.0
- Auto-reap branches on MCP close: when the watchdog proxy observes a session’s own claim close terminally and successfully, it removes that issue’s clean, merged
rtsc-NN/*worktree and branch out-of-band (retasc tidy --prune --only <id>), instead of orphaning them until a human ranretasc tidy.
Full notes
Full notes
- Auto-reap branches on MCP close: when the watchdog proxy observes a session’s
own claim close terminally and successfully, it removes that issue’s clean,
merged
rtsc-NN/*worktree and branch out-of-band (retasc tidy --prune --only <id>), instead of orphaning them until a human ranretasc tidy. Exposestidy --only <RTSC-NN>.
1.2.4
- RTSC-170 — credential-file permission hardening:
config.json,bindings.json, and the fallback.mcp.jsonare written0600(dirs0700) with no world-readable creation window.
1.2.3
- RTSC-150 — watchdog
isClaimLostfix: no longer drops a live lease when a payload field merely contains the stringCLAIM_LOST.
1.2.2
- RTSC-148 —
retasc claimtakes the issue as a positional argument, and never silently falls through tonext_issue.
Full notes
Full notes
-
RTSC-148 —
retasc claimtakes the issue as a positional argument, and never silently falls through tonext_issue.retasc claim 143,claim RTSC-143andclaim rtsc-143all resolve to that issue; a bare number expands against the workspace’s prefix, resolved over the workspace key rather than global config. Excess arguments now error loudly instead of being dropped by Commander, which was how “claim this specific issue” quietly became “claim whatever is next”.
1.2.1
- RTSC-143 — one tolerant tool-result parser, and a loud failure when the claim fence is off.
Full notes
Full notes
-
RTSC-143 — one tolerant tool-result parser, and a loud failure when the claim fence
is off.
The proxy and
claimeach had their own silent copy of the parser; they are now one (lib/toolresult.ts), which recovers the leading JSON value when a footer trails the payload, refuses to recover from anisErrorresponse or concatenated JSON, and warns on stderr when it degrades so a shape regression is never silent. Session-key minting retries once with a 5s timeout and checksres.ok. On a double failure it still fails soft, but says loudly that the per-session claim fence is OFF, and the proxy appends that notice towhoamiso the agent sees the degraded state rather than it sitting in an MCP log file nobody opens.
1.2.0
- RTSC-137 — org-membership commands:
retasc members invite|list|revokeandretasc join.
1.1.3
- RTSC-131 —
retasc --versionreadspackage.jsoninstead of a frozen literal.
Full notes
Full notes
-
RTSC-131 —
retasc --versionreadspackage.jsoninstead of a frozen literal. It was hardcoded to1.1.1, so the published 1.1.2 still reported 1.1.1. The version is now read at runtime relative to the compiled file, makingpackage.jsonthe single source of truth.
1.1.2
- RTSC-130 — republish the bind auto-wire fix that had changed CLI source without a version bump (npm versions are immutable).
1.1.1
- RTSC-98 —
claim,tidyanddoneresolve the keystore key through the same resolver the proxy uses.
Full notes
Full notes
-
RTSC-98 —
claim,tidyanddoneresolve the keystore key through the same resolver the proxy uses. After 1.1.0 moved keys out of the repo, a secret-free.mcp.jsonwas understood by the proxy but not by those three commands, which still only knew the legacy inline-key path and bailed with “No Retasc MCP key found”. The two resolvers had drifted, so they are now one (resolveConninlib/keystore.ts): explicitRETASC_MCP_KEY, then a legacy inline key, then the canonical secret-free marker. Legacy markers keep working.
1.1.0
- RTSC-92 — workspace keys move to a home keystore, and the folder marker becomes secret-free.
Full notes
Full notes
-
RTSC-92 — workspace keys move to a home keystore, and the folder marker becomes
secret-free.
Secrets no longer sit in a project tree. The key lives in
~/.retasc/bindings.json(mode 0600), keyed by an opaque workspace id rather than a path, so nothing leaks a home directory and a checkout stays portable across a team. What lands in the repo is a marker carrying only that id, which is why./.mcp.jsonis safe to commit.doctorreports whether a binding is keystore-backed or legacy, and flags a workspace id already bound at a different folder. A cloned repo whose marker has no key on this machine is reported as such rather than as broken.
1.0.0
- RTSC-89 — initial npm publish as
@retasc/cli(bin staysretasc).