Skip to content

feat: scc launch, the scc-cli npm name, and an entry file that tells the truth per harness - #13

Merged
protonspy merged 4 commits into
mainfrom
feat/launch-and-scc-cli
Aug 4, 2026
Merged

feat: scc launch, the scc-cli npm name, and an entry file that tells the truth per harness#13
protonspy merged 4 commits into
mainfrom
feat/launch-and-scc-cli

Conversation

@protonspy

Copy link
Copy Markdown
Owner

Four surfaces, one release. Each commit builds and tests green on its own.

scc launch <harness>

Resolves the workspace, picks the harness it was scaffolded for, starts that agent from the workspace root — through Headroom's compression proxy when it can.

scc launch                     # the harness this workspace has, via headroom
scc launch codex               # name it when there is more than one
scc launch --no-headroom       # bare agent
scc launch --dry-run           # print the command, run nothing
scc launch claude -- --resume  # everything after `--` goes to the agent

Headroom is the default, which is the deliberate opposite of how RTK is wired. RTK edits a file the user owns and changes how every later command is typed, so it stays opt-in. Headroom wraps one process for one session and touches nothing on disk — so it degrades instead of failing: missing binary, declined install, unattended run, or a harness Headroom does not wrap all end in the agent starting bare with a warning saying why.

This is the one command that does not obey the 0/1/2 exit-code contract — it returns whatever the agent returned. A launcher that flattened the status of what it launched is unusable in a script. scc's own failures still report 1, and all happen before anything starts.

scc-cli on npm

npm i -g scc-cli, and the command is still scc. The bare scc on npm has belonged to an unrelated project since 2013; npm resolves the package name and installs the bin name, and those never had to match.

@protonspy/scc stays published from the same source so earlier installs keep receiving versions. Since one shim serves both names, it now reads its own package.json for SCC_PROG — a hardcoded spelling would tell half the users to re-run under a package they never installed.

Launchers moved to npm/dist/launchers/. That is load-bearing, not tidy: publishing walks dist/scc-*/ first and dist/launchers/*/ second, and a second launcher at the top level would be swept into the platform glob and reach the registry ahead of the binaries its optionalDependencies name.

The entry file, per harness

Claude Code loads .claude/rules/*.md at launch with the same priority as CLAUDE.md. So an entry file telling that agent to "read the rule when the concern is live" describes a mechanism that already ran: it asks for a re-read that puts the same ~26KB in context twice, and it leaves the one document the agent is meant to trust wrong about its own environment.

paths.Harness gains PreloadsRules; entry.md branches on it. The trigger lists stay one shared copy — two copies would diverge the first time somebody edited a trigger, and Codex and Claude would then follow silently different methodologies. Codex and opencode keep the read-it-yourself instruction, since there rules/ is scc's own directory and nothing loads it.

Same pass: each rule gets its own trigger line instead of four running together in a sentence. project.md most of all — it was the third item of a prose list, and a build command that did not come from it is a guess.

Also corrects paths.RulesSeg, which claimed "no harness loads it on its own". True for two of three.

Verified

  • Every commit builds and tests green in isolation.
  • build-packages.mjs run against synthetic artifacts: 8 packages, correct publish order, both launchers npm publish --dry-run clean, each resolving its own name.
  • Upgrade path exercised by building the previous binary from main and running the new update against workspaces it created.

Known, not addressed here

scc update never rewrites the entry file — it is Owned: true, and that check short-circuits before the manifest comparison, so even a provably untouched CLAUDE.md is kept. --force does not reach it either. Deleting the file and re-running update recreates it correctly, but nothing in the output says so. The repo's own convention says the manifest is what distinguishes pristine from edited; the Owned branch discards that distinction. Worth a follow-up.

🤖 Generated with Claude Code

https://claude.ai/code/session_01J54qbk8RpC2tZH8LBz6T2b

protonspy and others added 4 commits August 4, 2026 00:49
…proxy

`scc launch [harness]` resolves the workspace, picks the harness it was
scaffolded for, and starts that agent from the workspace root — through
`headroom wrap <slug>` when Headroom is available.

Headroom is the default rather than a flag, which is the deliberate opposite
of how RTK is wired. RTK edits a file the user owns and changes how every
later command is typed, so it stays opt-in. Headroom wraps one process for
one session and changes nothing on disk, so defaulting costs nothing when it
is absent: a missing binary, a declined install, an unattended run, or a
harness Headroom does not wrap all degrade to starting the agent bare with a
warning naming the reason. `--no-headroom` forces that path.

This is the one command that does not obey the 0/1/2 exit-code contract: it
returns whatever the agent returned. A launcher that flattened the status of
what it launched would be unusable in a script. scc's own failures still
report 1, and they all happen before anything starts.

internal/headroom keeps the agent-slug table and the install path (uv, then
pip — never npm, which ships the SDK and no CLI), so a third party's
vocabulary ages in one package instead of in the dispatcher.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J54qbk8RpC2tZH8LBz6T2b
`npm i -g scc-cli` is now the documented install, and the command it puts on
PATH is still `scc`. npm resolves the package name and installs the bin name,
and those never had to match — the bare `scc` on npm has belonged to an
unrelated project since 2013.

@protonspy/scc stays published from the same source so earlier installs keep
receiving versions. Both launchers ship one shim, so the shim now reads its
own package.json for SCC_PROG instead of naming a package: hardcoding either
spelling would tell half the users to re-run under a package they never
installed.

Launchers are emitted under npm/dist/launchers/ rather than beside the
platform packages, and that is load-bearing. Publishing walks dist/scc-*/
first and dist/launchers/*/ second; a second launcher at the top level would
be swept into the platform glob and reach the registry ahead of the binaries
its optionalDependencies name, which is a broken install for anyone in that
window.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J54qbk8RpC2tZH8LBz6T2b
…it already has

Claude Code loads .claude/rules/*.md at launch with the same priority as
CLAUDE.md. An entry file telling that agent to "read the rule when the
concern is live" therefore describes a mechanism that already ran: it asks
for a re-read that puts the same ~26KB in context twice, and it leaves the
one document the agent is meant to trust wrong about its own environment.

paths.Harness gains PreloadsRules, and entry.md branches on it — the trigger
lists stay a single copy shared by both arms, because two copies would
diverge the first time somebody edited a trigger and Codex and Claude would
then follow silently different methodologies. Codex and opencode keep the
instruction, since there rules/ is scc's own directory and nothing loads it.

The same pass gives each rule its own trigger line instead of running four of
them together in a sentence. project.md most of all: it was the third item of
a prose list, and a build command that did not come from it is a guess.

The test asserts the two lead-ins are mutually exclusive rather than merely
present — a template shipping both would satisfy a contains check while
contradicting itself in the file.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J54qbk8RpC2tZH8LBz6T2b
Corrects a claim that was load-bearing and false: paths.RulesSeg said "no
harness loads it on its own", which holds for Codex and opencode but not for
the harness the project is named after. Confirm per harness with /context.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J54qbk8RpC2tZH8LBz6T2b
@protonspy
protonspy merged commit 0282627 into main Aug 4, 2026
4 checks passed
@protonspy
protonspy deleted the feat/launch-and-scc-cli branch August 4, 2026 04:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant