This repository is an OpenCode plugin written in TypeScript. The guidance below is for agentic coding tools that will modify or run code here.
- Source code lives in
src/. - Tests live alongside sources in
src/**/*.test.ts. - Build output goes to
dist/. - Hooks configuration lives in
hook/hooks.md(YAML frontmatter). - Agents, commands, and skills are loaded from
agent/,command/, andskill/. - Skills are discovered by
skill/<name>/SKILL.md.
- Requires Node.js 18+.
- Install dependencies with:
npm install
There is no dedicated lint script or ESLint config. Use typecheck as the closest linting step.
- Build:
npm run build
- Typecheck (strict):
npm run typecheck
- Tests (all):
npm test
- Test watch (local dev):
npx vitest
Vitest is configured via vitest.config.ts and runs src/**/*.test.ts.
Use any of the following:
npm test -- src/index.test.tsnpx vitest run src/index.test.ts
npm test -- -t "should parse valid frontmatter"npx vitest run -t "should parse valid frontmatter"
npx vitest run src/index.test.ts -t "should parse valid frontmatter"
- Typecheck only:
npm run typecheck
- Build only:
npm run build
- Use TypeScript (ES module syntax) and keep
stricttype safety. - Avoid
any. Prefer explicit types or narrow types with guards. - Prefer
unknownfor untrusted data, then validate or narrow. - Prefer
Record<string, unknown>over loose object types. - Use
type-only imports for types (import { type Foo } ...).
- Use Node.js ESM imports, with
node:specifiers for core modules:import { join } from "node:path"
- Prefer named imports; avoid default imports when not required.
- Keep imports grouped and ordered:
- Node core modules
- External dependencies
- Local modules
- Use 2-space indentation.
- Use double quotes for strings.
- No semicolons in existing code; follow that style.
- Keep lines readable; wrap long objects onto multiple lines.
- Align object literals and multiline logs for readability.
- Functions and variables:
camelCase. - Types and interfaces:
PascalCase. - Constants:
SCREAMING_SNAKE_CASEfor module-level constants. - Filenames:
kebab-caseor existing file names (do not rename casually). - Hook events and conditions use
snake.casestyle strings.
- Prefer explicit error handling with
try/catcharound filesystem I/O. - If an operation is non-critical, log and continue instead of throwing.
- Use the local logger in
src/logger.tsfor plugin-related logging. - Keep error messages concise and include minimal context as JSON when useful.
- When swallowing errors, do so intentionally (as in
log()).
- Keep functions small and focused; avoid deep nesting.
- Avoid mutating inputs; create new objects when transforming data.
- When iterating, prefer
for...ofwhereawaitis used. - Keep hook execution order deterministic (iterate in declaration order).
- Hooks are declared in
hook/hooks.mdfrontmatter. - When adding new hook events, update
VALID_HOOK_EVENTSand docs. - Action errors should not stop later actions.
- Do not change session lifecycle behavior without updating tests.
- Tool hooks track files modified by
writeandedittools.
- Frontmatter parsing is tolerant: invalid YAML yields empty data.
- Treat loader outputs as best-effort (missing dirs return empty results).
- Keep YAML parsing behavior compatible with
js-yaml.
- Use Vitest and global
describe/it/expect. - Tests should be deterministic and avoid network access.
- For filesystem tests, use temp directories via
os.tmpdir()and clean up. - Prefer explicit assertions over snapshots.
- Keep README and hook docs consistent with implementation.
- If you change supported events or actions, update
README.mdaccordingly. - Update
hook/hooks.mdfrontmatter examples if behavior changes.
- No Cursor rules found in
.cursor/rules/or.cursorrules. - No Copilot instructions found in
.github/copilot-instructions.md.
- Be surgical: change only what is required for the task.
- Preserve existing behaviors, especially around hook execution order.
- Avoid broad refactors unless explicitly requested.
- Do not add new dependencies without user approval.
- Prefer adding or updating tests alongside behavior changes.
- Keep logs concise to avoid noisy plugin output.