Task — engineering-spec@1

Rename the public CyberOS CLI bin from `cyberos` to `cs`

doneTASK-IMP-130
module improvement · class product · priority p0 · created 2026-07-22 · shipped null
depends on none · blocks TASK-IMP-131, TASK-IMP-132, TASK-IMP-133, TASK-IMP-134, TASK-IMP-135

TASK-IMP-130: Rename the public CyberOS CLI bin from cyberos to cs

Summary

The npm-published CyberOS CLI exposes itself as the bin command cyberos, which collides on $PATH with an unrelated internal tool that happens to already claim that name. This task renames the public bin to cs, updates every place the CLI describes its own invocation, and folds in a stale-domain fix discovered in the same files.

Problem

brew install --cask cyberos followed by brew trust installs the Homebrew-packaged CLI correctly, but running cyberos -h afterward showed an unrelated 39-subcommand BRAIN-store CLI instead of the Homebrew-installed one. Root cause, confirmed by direct repo inspection (docs/plans/PLAN-cli-module-namespacing-2026-07-22/plan.md §2): the npm-published @cyberskill/cyberos package (tools/install/build.sh:341-347) declares its bin as cyberos (tools/install/cli/bin/cli.mjs), and a completely separate, PyPI-unpublished internal package (modules/memory, cyberos-memory) independently declares a console-script entry also named cyberos (modules/memory/pyproject.toml:29). Whichever one lands later on $PATH (in the reported case, a local/dev pyenv install of modules/memory) wins, and there is no error — just the wrong tool answering to the name, silently.

cyberos-memory is confirmed internal-only with no plan to publish (plan §2), so it was never actually the thing that needed to change to solve the founder's goal, which is "the only public command is cs" (plan §4). Renaming the public bin directly delivers that and needs no coordination with the internal package's own naming.

Proposed Solution

Change the npm package's bin field (generated by build.sh:341-347) from { "cyberos": "cli/bin/cli.mjs" } to { "cs": "cli/bin/cli.mjs" }, keeping the package name @cyberskill/cyberos unchanged (see Alternatives Considered). Update every place the CLI's own text describes its invocation — cli.mjs's top comment and usage() output, help.sh's "Channels" section, the plugin's help.md, docs/index.md's "same eight commands" line, and the npx cyberos ... examples in tools/install/README.md — to read cs instead of cyberos. Add a CHANGELOG entry calling out the rename as breaking, per the plan's explicit instruction not to ship it as a silent swap (plan §7). While editing cli.mjs, help.sh, and help.md for the rename, also correct the stale domain string https://cyberos.cyberskill.world/docs found in all three to the canonical https://os.cyberskill.world/docs already in use elsewhere in the repo (e.g. README.md:7) since PR #107.

Alternatives Considered

Success Metrics

Scope

In scope: build.sh's package.json generation (bin field only — name stays), cli.mjs's dispatch/usage text, help.sh, the plugin's help.md, docs/index.md, the npx cyberos ... examples in tools/install/README.md, a CHANGELOG entry, and the three stale-domain instances found in the same files touched for the rename.

Out of scope / Non-Goals

Dependencies

None blocking — this is the root task the other four in this batch depend on. Touches the OIDC trusted-publishing pipeline in release.yml (plan §7): a bin-name change should go through the normal release flow and be re-tested end to end by TASK-IMP-134, not verified in isolation here.

Relationship to TASK-IMP-076 (done). That task shipped the original install/uninstall/version/status/help root CLI surface and the mcp/gates verbs inside cli.mjs — the exact dispatch table and usage text this task renames. It established the "three channels cannot drift" design (plugin slash commands, help.sh, cli.mjs mirror the same command set 1:1) that this task's doc sweep must preserve under the new name, not just the bin field itself.

AI Authorship Disclosure

1. Description (normative)

2. Acceptance criteria

3. Edge cases

Audit

§1 — Verdict summary

Seven §1 clauses, seven ACs, five edge cases including one security-class row. All seven clauses trace 1:1 to an AC via traces_to; TRACE-006 (verb-vs-assertion) review found one real gap (AC 4) which is now fixed. The most consequential finding was a test-file convention mismatch that would have pointed the implementer at a file structured the wrong way to receive these tests.

§2 — Findings (all resolved)

ISS-001 — AC 4 tested only the absence of the old string, not the presence of the new one (TRACE-006)

Clause 1.4 demands the doc files "read cs in place of cyberos" — a positive replacement. The original AC 4 asserted only that a grep for cyberos <command> returned zero matches. A test asserting the negative alone would pass on an implementation that deleted the CLI examples from the docs entirely rather than updating them, which satisfies "zero matches" while failing the clause's actual demand that the reader now sees cs. Material: would have passed a test that didn't prove the clause. Resolved: AC 4 now requires both the positive replacement text be present in each of the three files AND the old pattern be absent.

ISS-002 — the cited test file uses the wrong convention for a file::test_name citation

All seven ACs originally pointed at tools/install/tests/test_channels.sh using ::t_name citations. Reading that file showed it is a flat sequential script (ok()/bad() calls with string labels), not a file of named test functions — the citation convention this contract requires (per test_install_hygiene.sh's actual t01_gitignore_managed_block()-style functions, which is what TASK-IMP-129 cited correctly). Citing test_channels.sh::t_bin_renamed_to_cs would have pointed an implementer at a file that cannot host a function by that name without restructuring it first, and conflated this task's rename-specific assertions with test_channels.sh's actual purpose (proving every manifest-declared delivery channel works, per its own header comment). Resolved: introduced a new dedicated file, tools/install/tests/test_cli_rename.sh, using the named-function convention, and all seven ACs now cite it.

ISS-003 — new_files omitted the test file entirely

Following directly from ISS-002: the original frontmatter's new_files: [(none)] was wrong on its own terms even before the file-choice fix — every AC required a new test, so at least one new file was always going to be needed, and the frontmatter didn't say so. Resolved: new_files now lists tools/install/tests/test_cli_rename.sh.

ISS-004 — related_tasks named TASK-IMP-076 but the body never said why

related_tasks: [TASK-IMP-076] was present in the first draft, but nothing in Problem, Proposed Solution, or Dependencies explained the relationship — the same class of gap TASK-IMP-129's own audit (ISS-004 there) flagged as material when a related task is listed but unexplained. TASK-IMP-076 shipped the exact dispatch table and usage text this task renames, and established the "three channels cannot drift" design this task's doc sweep must preserve. Resolved: added an explanatory paragraph to Dependencies.

ISS-005 — Success Metrics lacked a timeframe (QA-004-adjacent)

Both metrics had a baseline and a target but no deadline, which QA-004 treats as a vanity-metric risk even when the target itself is concrete. Resolved: both metrics now anchor to "the next CyberOS release after 1.0.9."

ISS-006 — an edge case asserted a specific npm bin-symlink behaviour that was not actually verified

The original edge-case bullet stated a user's old cyberos invocation "will silently stop resolving" after the package upgrades to the new bin name — presented as settled fact, but npm's handling of a changed bin field on an existing global install (clean removal vs. a dangling stale symlink) was never independently checked in this authoring session; it is version- and install-method-dependent. Asserting a specific mechanism without having verified it is exactly the kind of unsourced technical claim the anti-fabrication discipline exists to catch. Resolved: reframed as an open question that TASK-IMP-134's clean-machine regression test must observe directly, rather than a claim this task asserts as already known.

§3 — TRACE-006 semantic sufficiency (per clause)

ClauseVerb demandCited test assertsVerdict
1.1 MUST declare bin+namegenerated config literally contains both fieldsAC 1: scratch-build package.json has bin.cs and unchanged namesufficient
1.2 MUST refer to invocation as cspositive text present AND old text absent in --help outputAC 2: asserts both halves against actual stdoutsufficient
1.3 MUST describe npm channel as npx cssame shape as 1.2, against help.sh outputAC 3: asserts both halves against actual stdoutsufficient
1.4 MUST read cs in docspositive replacement present, not just old string absentAC 4 (revised): asserts both halves per filesufficient after revision (was insufficient pre-revision — ISS-001)
1.5 MUST correct domain stringpositive new domain present AND old domain absentAC 5: asserts both halvessufficient
1.6 MUST gain CHANGELOG entrypositive content present in top entryAC 6: asserts three required substringssufficient
1.7 MUST NOT modify modules/memorydiff scope excludes the path — a "preserve" style checkAC 7: asserts git diff touches no file under modules/memory/sufficient

§4 — Resolution

Six findings, all material or TRACE-006-material, all resolved in the audited revision. Score = 10/10.

Status transition draft -> ready_to_implement is authorised by this verdict per STATUS-REFERENCE.md §1.1. The two human-acceptance gates in /ship-tasks (review acceptance, final acceptance) are unchanged and remain recorded human verdicts — this audit clears the spec-correctness gate only.


End of TASK-IMP-130 audit.