git clone https://github.com/mmmprod/claude-eta.git
cd claude-eta
npm install
npm run build
claude plugin marketplace add ./
claude plugin install claude-eta --scope local- Make changes in
src/ npm run build(TypeScript →dist/)npm run test:unitnpm run test:integration
After code changes, rebuild and restart Claude Code for hooks to pick up changes.
npm run test:unit # Unit tests only
npm run test:integration # Local integration tests (spawn hooks/CLI, may touch legacy v1 data path)
npm test # Unit + local integration
npm run test:remote # Live Supabase contract testUnit tests avoid spawned hook/CLI processes and do not require .git.
Integration tests (plugin-package.test.js, stop-hook.test.js, prompt-hook.test.js, etc.) spawn real processes and exercise filesystem behavior.
The remote test hits the public Supabase backend and is intentionally separated from the default contributor loop.
- Tests are plain JS using
node:test+assert/strict - Tests import from
dist/(build first!) - One test file per module:
tests/{module-name}.test.js - Test names:
describe("moduleName") > it("does specific thing")
- No
existsSync— always try/catch - PostToolUse is hot path — no heavy I/O, no stats computation
- New fields on
ActiveTurnStateorCompletedTurnmust have defaults in normalization - Pure functions go in dedicated modules (no I/O). Hooks orchestrate.
- Loop detector improvements:
src/loop-detector.ts - Classifier improvements:
src/classify.ts - New insights:
src/insights/ - Bug fixes: check issues tagged
good first issue
npm run build && npm run test:unitmust passnpm run lintmust pass (tsc --noEmitstrict)- Update tests for changed behavior
- Commit
dist/(required for plugin distribution)