agent-skill-manager (asm) — a TypeScript CLI plus ink/React TUI that manages
Agent Skills installed for Claude Code, Codex, Gemini, and OpenClaw.
npm install # postinstall no-ops when CI or ASM_SKIP_POSTINSTALL is set
npm run build # tsx scripts/build.ts -> dist/ (gitignored)
CI=true npm test # unit suite — the command of record
npm run test:coverage # v8 coverage for src/ — measurement only, no fail gate
npm run typecheck # tsc --noEmit
npm run lint # eslint over src/
npm run lint:site # eslint over website-src/src
npm run test:e2e # tests/e2e/ — NOT covered by `npm test`
npm start # run the TUI from sourcenpm test is vitest run src/, and that argument is a substring filter on the
test path, not a directory — website-src/src/__tests__/ matches it too, so
npm run test:site is a subset of npm test, not a separate leg. Only
tests/e2e/ is excluded. Measured timings and evidence: docs/AGENT_ENVIRONMENT.md.
npm run test:coverage is vitest run --coverage src/ with
@vitest/coverage-v8 (5.x, matching current vitest). It reports line and
branch percentages for src/ product files only (test files excluded). There
is no coverage threshold and no CI fail gate — measurement before
improvement (F-TEST-003 / #438). Vitest 5 remaps V8 coverage via AST, so the
denominators below are not comparable to the vitest-4 #438 baseline; keep
coverage.include.
Coverage baseline (2026-09-12, src/, v8, CI=true npm run test:coverage,
2800 tests):
- Lines: 82.69% (8740/10569)
- Branches: 73.74% (5393/7313)
src/commands/ measures 63.74% lines (#673): src/cli-*.test.ts dispatches
runCLI() in-process via src/cli-test-harness.ts instead of spawning tsx
children that v8 could not
attribute (the layer previously read 10.53%). Still subprocess-bound by
design: the runInlineTs readLine tests (stdin pipes need a real child), the
cross-process borrow-lock test under asm get --path, and one bundle export
no-overwrite case whose process.exit sits inside a catch that would
swallow the in-process sentinel. toggle.ts (disable/enable) stays low
because nothing exercises it — a real gap, not an attribution artifact.
M3's coverage target is bound to max(60%, baseline + 20pp):
- Lines:
max(60%, 102.69%)= 100% (formula saturates at 100) - Branches:
max(60%, 93.74%)= 93.74%
Node and npm must satisfy package.json engines — node ">=22 <27", npm
">=9".
bin/agent-skill-manager.ts— entry point: args go tosrc/cli.ts, none to the TUI.src/cli.ts— argv dispatcher routing to thecmd*handler modules insrc/commands/; all output throughsrc/formatter.ts.src/index.tsx+src/views/— the ink/React TUI.src/*.ts— one module per domain (scanner, installer, auditor, skill-index, …), each with its*.test.tsbeside it.data/skill-index/— committed per-repo index JSON; generated, never hand-edited.website-src/— site source;website/— its published output.scripts/— build, preindex, catalog generation.- Detail:
docs/ARCHITECTURE.md,docs/DEVELOPMENT.md.
- YOU MUST NOT run
npm run preindex,npm run build:website, ornpm run refresh:repo-bundlesas a probe. They rewrite tracked files underdata/skill-index/andwebsite/. Run them only when regenerating the catalog is the point of the change, then review the diff. - IMPORTANT:
npm run preindexalso rewrites the developer's real~/.config/agent-skill-manager/skill-index/— a mutation no git diff shows. - Unit tests sandbox user state.
src/test-setup.ts(vitestsetupFiles) setsHOME,USERPROFILE, andASM_CONFIG_DIRto a temp dir.getConfigDir()insrc/config.tsreadsASM_CONFIG_DIR(fallback~/.config/agent-skill-manager). Do not remove that setup — without it the suite writes the real user config. - IMPORTANT:
CI=truedoes not itself isolate the suite; hermeticity is the env override + lazygetConfigDir(), not theCIflag. - Never commit
dist/ornode_modules/. Most ofwebsite/is gitignored, but its*-stats.jsonandrobots.txtare tracked — commit those only on a deliberate regeneration. - Never delete or rewrite untracked scratch files at the repo root; other sessions own them.
- Conventional Commits; branch from
mainas<type>/<issue>-<description>; PR intomain.
- Iterate with the narrowest runner —
npx vitest run src/<module>.test.ts— and runCI=true npm testonly before pushing. - Run
npm run typecheckafter a series of edits; do not wait for the commit hook. - Change
src/<name>.tsand itssrc/<name>.test.tstogether. - Install both hook stages; a plain
pre-commit installsilently skips pre-push:pre-commit install --hook-type pre-commit --hook-type pre-push. - Prettier runs on commit — do not hand-format markdown, TS, or JSON to match it.
- Keep changes minimal and scoped to the task; do not opportunistically refactor.
- Never re-read files you just wrote or edited. You know the contents.
- Never re-run commands to "verify" unless the outcome was uncertain.
- Don't echo back large blocks of code or file contents unless asked.
- Batch related edits into single operations. Don't make 5 edits when 1 handles it.
- Skip confirmations like "I'll continue..." Just do it.
- If a task needs 1 tool call, don't use 3. Plan before acting.
- Do not summarize what you just did unless the result is ambiguous or you need additional input.