Skip to content

`crimes@0.9.0` — Codex Agent Discovery + Petty Crime

Draft release notes for the GitHub Release tagged v0.9.0. The body below is what should go in the Releases page when you cut the tag — that triggers .github/workflows/release.yml and publishes to npm via Trusted Publishing.

crimes@0.9.0 makes Codex a first-class consumer of crimes’ on-disk agent assets, adds one new petty-crime detector, and rewrites the crimes explain output to be friendlier to humans triaging a single finding. No schema_version bump on the Finding wire format.

  • Codex agent discovery is a first-class signal. crimes init --agents now writes both .claude/skills/crimes/SKILL.md and .agents/skills/crimes/SKILL.md, and the missing_agent_context detector recognises the Codex path as a satisfying signal. A new --codex-skill flag writes only the Codex skill.
  • New detector: finder_duplicate_filename. Flags macOS Finder / iCloud conflict-copy filenames like Button 2.tsx that slip into repos as accidental duplicates and force agents and humans to guess which file is canonical. Medium severity, 0.90 confidence.
  • crimes explain rewrite. Output is broken into named section helpers and gains a “Likely remedies” block synthesised from the finding’s suggested_actions plus generic next-steps. The ExplainReport JSON gains a new likely_remedies: string[] field.
  • Post-install nudge. npm install -g crimes now prints a one-line reminder to run crimes init --agents (suppressed in CI and behind CRIMES_DISABLE_POSTINSTALL=1).
  • Landing-page broken link fix. The “Live status” link on crimes.sh and the llms.txt roadmap pointer now resolve to docs/roadmap.md instead of the moved ROADMAP_STATUS.md path.

Schema: schema_version stays at "0.1.0" — the Finding wire format is unchanged. The ExplainReport (the crimes explain --format json envelope) gains the likely_remedies field; consumers of explain JSON should treat additional fields defensively.

Codex CLI loads SKILL.md files from .agents/skills/<name>/. Until this release, crimes init --agents only wrote the Claude Code skill at .claude/skills/crimes/SKILL.md, and the missing_agent_context detector only looked at the Claude path. A repo with a Codex skill but no other agent signal would still get charged.

Three changes here:

  • crimes init writes both skill files. --agents writes the Claude skill and the Codex skill. A new --codex-skill flag writes only the Codex skill (mirroring the existing --agent-skill flag for Claude). --force applies to both. The Codex skill content mirrors the Claude skill — same workflow, same decision rules.
  • missing_agent_context recognises .agents/skills/*/SKILL.md. The detector treats any of AGENTS.md, CLAUDE.md, .claude/skills/*/SKILL.md, or .agents/skills/*/SKILL.md as satisfying; only repos with a declared bin and none of those fire. Evidence and summary text updated accordingly.
  • IaAgentInventory.codexSkills is a new optional field on the internal IA index, populated alongside claudeSkills from a parallel fg walk.

Repos that have already added a Codex skill outside of crimes init silence the finding automatically — the detector reads the filesystem, not the init command’s output.

The seventh petty crime. macOS Finder and iCloud append 2 (or 3, 4, …) when resolving local filename conflicts — Button.tsx becomes Button 2.tsx. These conflict copies routinely slip into repos as accidental duplicates, and then agents and humans have to guess which file is canonical.

Detection is filename-only:

filename ends with Finder conflict suffix: "Button 2.tsx"
likely intended canonical path: src/components/Button.tsx
suffix number: 2
  • Requires the Finder-style space before the numberPage2.tsx and v2.ts are not flagged.
  • Suggested action: compare the suffixed file with the likely canonical file. If accidental, delete it. If both are real, rename one with a domain-specific name.
  • Surface area for false positives is tiny because the suffix pattern is unusual outside of Finder / iCloud conflict resolution. Confidence pinned at 0.90.

Documented in docs/finding-types/petty.md.

The human-renderer for crimes explain was a single function with inline conditionals for every optional section. It is now a thin top-level that delegates to named section helpers (explainHeaderBlock, evidenceBlock, suggestedActionsBlock, likelyRemediesBlock, relatedFilesBlock) and a pushSection helper that handles the blank-line separator discipline.

The new Likely remedies section is the meaningful addition. crimes explain previously stopped at “here’s the evidence, here’s the suggested action object”. The remedies block synthesises an ordered list of next-steps:

  1. The top three suggested_actions[].description values (already on the finding).
  2. A generic “if this reflects a real project convention, configure the detector or record feedback instead of renaming code blindly”.
  3. A generic “if the team accepts the risk, suppress this exact fingerprint with a one-sentence reason”.

That short list is also exposed on the ExplainReport JSON as the new likely_remedies: string[] field, so agents can ingest it without re-deriving it from suggested_actions.

packages/cli/scripts/postinstall.mjs is a new script wired through package.json’s postinstall hook and the npm tarball files allowlist. After npm install -g crimes, the script prints:

crimes installed.
Run `crimes init --agents` in a repo to add crimes.config.json plus Claude Code and Codex skill files.

The script no-ops in CI (CI=true) and behind a CRIMES_DISABLE_POSTINSTALL=1 escape hatch — the message is for interactive global installs, not for automated environments.

The smoke test now packs and verifies scripts/postinstall.mjs lands in the tarball, with an explicit allowlist exception in the “tarball should not ship dev scripts” guard.

The repo moved ROADMAP_STATUS.md into docs/roadmap.md in commit 5743099 (“Move plan docs out of root”), but the landing page’s “Live status” link and llms.txt’s roadmap pointer were left at the old path and 404’d. Both now resolve to docs/roadmap.md.

  • packages/core/src/ia/build.ts. The 78-line monolith buildIaIndex body is split into collectSourceSignals, readSourceSignal, and a tighter collectAgentInventory. Same outputs, individually testable.
  • packages/core/src/detectors/missing-agent-context.ts. The finding constructor is split into hasAgentContext, missingAgentContextFinding, and missingAgentContextEvidence helpers. Same behaviour, easier to extend when the next agent vendor lands.
  • No schema_version bump. The Finding wire format is byte-identical to 0.8.1. The ExplainReport envelope gains likely_remedies: string[] — additive.
  • No config schema changes. Existing crimes.config.json files keep working unchanged.
  • No package dependency changes.
  • No new commands. crimes init gains a --codex-skill flag and the --agents flag now writes more files — same command surface otherwise.
Terminal window
npm install -g crimes@0.9.0
crimes --version # crimes@0.9.0

For users on crimes@0.8.x:

  • If you have a .claude/skills/crimes/SKILL.md but want Codex coverage too, run crimes init --codex-skill (or --agents to refresh both — note that --agents without --force will refuse if the Claude skill already exists).
  • If your CI gates on crimes scan --fail-on high or crimes baseline check --fail-on, expect at most one new finding kind (finder_duplicate_filename) — and only if your repo actually contains Finder-suffixed files, which is rare in checked-in code.
  • If you parse crimes explain --format json output, the new likely_remedies: string[] field is required on the response. Treat it as additive.