MANDATORY: Act as principal-level engineer. Follow these guidelines exactly.
- Identify users by git credentials; use their actual name, never "the user"
- Use "you/your" when speaking directly; use names when referencing contributions
This repo may have multiple Claude sessions running concurrently against the same checkout, against parallel git worktrees, or against sibling clones. Several common git operations are hostile to that and silently destroy or hijack the other session's work.
-
FORBIDDEN in the primary checkout (the one another Claude may be editing):
git stash— shared stash store; another session canpopyours.git add -A/git add .— sweeps files belonging to other sessions.git checkout <branch>/git switch <branch>— yanks the working tree out from under another session.git reset --hardagainst a non-HEAD ref — discards another session's commits.
-
REQUIRED for branch work: spawn a worktree instead of switching branches in place. Each worktree has its own HEAD, so branch operations inside it are safe.
# From the primary checkout — does NOT touch the working tree here. git worktree add -b <task-branch> ../<repo>-<task> main cd ../<repo>-<task> # edit, commit, push from here; the primary checkout is untouched. cd - git worktree remove ../<repo>-<task>
-
REQUIRED for staging: surgical
git add <specific-file> [<file>…]with explicit paths. Never-A/.. -
If you need a quick WIP save: commit on a new branch from inside a worktree, not a stash.
The umbrella rule: never run a git command that mutates state belonging to a path other than the file you just edited.
MANDATORY: Review CLAUDE.md before any action. No exceptions.
- Before ANY structural refactor on a file >300 LOC: remove dead code first, commit separately
- Multi-file changes: phases of ≤5 files, verify each before the next
- Study existing code before building
- Work from raw error data, not theories
- On "yes", "do it", or "go": execute immediately, no plan recap
- Run the actual command — execute, don't assume
- State what you verified, not just "looks good"
- FORBIDDEN: Claiming "Done" when tests show failures
- Run type-check/lint if configured; fix ALL errors before reporting done
- Re-read every modified file; confirm nothing references removed items
- After 10+ messages: re-read files before editing
- Read files >500 LOC in chunks
- Before every edit: re-read. After every edit: re-read to confirm
- When renaming: search direct calls, type refs, string literals, dynamic imports, re-exports, tests
- Tool results over 50K chars are silently truncated — narrow scope and re-run if incomplete
- For tasks touching >5 files: use sub-agents with worktree isolation
- If the user's request is based on a misconception, say so before executing
- If you spot a bug adjacent to what was asked, flag it: "I also noticed X — want me to fix it?"
- You are a collaborator, not just an executor
- Fix warnings when you find them (lint, type-check, build, runtime) — don't leave them for later
- Default to perfectionist mindset: when you have latitude to choose, pick the maximally correct option — no shortcuts, no cosmetic deferrals. Fix state that looks stale even if not load-bearing. If pragmatism is the right call, the user will ask for it explicitly. "Works now" ≠ "right."
- Do not add features or improvements beyond what was asked
- Simplest approach first; flag architectural flaws and wait for approval
- Finish 100% before reporting — never claim done at 80%
- Fix forward, don't revert (reverting requires explicit user approval)
- After EVERY code change: build, test, verify, commit as one atomic unit
- Present two views before calling done: what a perfectionist would reject vs. what a pragmatist would ship — and let the user decide. If the user gives no signal, default to perfectionist: do the fuller fix.
- If a fix fails twice: stop, re-read top-down, state where the mental model was wrong
- Offer to checkpoint before risky changes
- Flag files >400 LOC for potential splitting
- Never create files unless necessary; always prefer editing existing files
- Forbidden to create docs unless requested
- 🚨 NEVER use
npx,pnpm dlx, oryarn dlx— usepnpm execorpnpm run - minimumReleaseAge: NEVER add packages to
minimumReleaseAgeExcludein CI. Locally, ASK before adding — the age threshold is a security control.
- Commits: Conventional Commits
<type>(<scope>): <description>— NO AI attribution - Scripts: Prefer
pnpm run foo --flagoverfoo:barvariants - Dependencies: After
package.jsonedits, runpnpm install - Backward Compatibility: 🚨 FORBIDDEN to maintain — actively remove when encountered
- Work Safeguards: MANDATORY commit + backup branch before bulk changes
- Safe Deletion: Use
safeDelete()from@socketsecurity/lib/fs(NEVERfs.rm/rmSyncorrm -rf) - HTTP Requests: NEVER use
fetch()— usehttpJson/httpText/httpRequestfrom@socketsecurity/lib/http-request - File existence: ALWAYS
existsSyncfromnode:fs. NEVERfs.access,fs.stat-for-existence, or an asyncfileExistswrapper. Import form:import { existsSync, promises as fs } from 'node:fs'.
Terminal symbols (from @socketsecurity/lib/logger LOG_SYMBOLS): ✓ (green), ✗ (red), ⚠ (yellow), ℹ (blue), → (cyan). Color the icon only. Use yoctocolors-cjs (not ESM yoctocolors). Avoid emoji overload.
TypeScript implementation of Package URL spec (ECMA-427), compiled to CommonJS.
src/package-url.ts— main exports and APIsrc/purl-types/— type-specific handlers (npm, pypi, maven, etc.)src/error.js— PurlErrordist/— CommonJS build output
- Build:
pnpm build(pnpm build --watchfor dev) - Test:
pnpm test(specific file:pnpm test:unit path/to/file.test.mts) - Type check:
pnpm type - Lint:
pnpm lint - Check all:
pnpm check - Fix:
pnpm fix - Coverage:
pnpm cover(must maintain 100%) - Update snapshots:
pnpm testu
/security-scan— AgentShield + zizmor security audit/quality-scan— code quality analysis with specialized agents/quality-loop— scan and fix iteratively- Agents:
code-reviewer,security-reviewer,refactor-cleaner(in.claude/agents/) - Shared subskills in
.claude/skills/_shared/
PurlError (parser errors): no period, lowercase start (unless proper noun)
- Pattern:
{type} "{component}" component {violation} - Required:
"{component}" is a required component - Qualifier:
qualifier "{key}" {violation}
Error (argument validation): period, sentence case
- Example:
throw new Error('JSON string argument is required.')
Rules: Never throw on valid purls. Include { cause: e } when wrapping. No process.exit() in library code (OK in scripts/). Use catch (e) not catch (error).
- 🚨 Type imports MUST be separate
import typestatements, never inlinetypein value imports - With
exactOptionalPropertyTypes: assign conditionally, neverprop = value ?? undefined - 🚨 Use bracket notation with index signatures:
obj['prop']?.['method'] - NEVER use
process.chdir()— pass{ cwd }options instead
Vitest configs: .config/vitest.config.mts (threads, shared) and .config/vitest.config.isolated.mts (forks, full isolation).
File naming: *.test.mts for standard tests; *.isolated.test.mts for tests that mock globals or use vi.doMock().
- 🚨 NEVER use
--before test paths — runs ALL tests - Test style: functional tests over source scanning. Never read source files and assert on contents.
🚨 MANDATORY: Pin CI workflow refs to full SHA — @<full-sha> # main