npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@andygo.dev/cakephp-harness

v1.0.2

Published

Local AI development harness for CakePHP projects: version-aware manual sync, SQLite/FTS5 search, a CakePHP Claude Code Skill, and an MCP server.

Readme

@andygo.dev/cakephp-harness

A local AI development harness for CakePHP projects.

It gives AI coding agents version-aware, local, authoritative CakePHP knowledge, while keeping how to write CakePHP code separate from what the framework actually does:

  • Guidance — development conventions, architecture and testing practice
  • Rolescakephp-expert, cakephp-code-reviewer, cakephp-test-writer and cakephp-planner, which verify APIs against the docs instead of recalling them
  • Manuals + MCP — the official CakePHP documentation for your version
  • Project specs (optional) — your own docs and specs, in a separate corpus
  • Config — how this specific project should be developed

The problem it solves: an agent confidently inventing a CakePHP API, or answering a CakePHP 5.4 question from CakePHP 3.x memory.

It works with Claude Code, Cursor, OpenAI Codex CLI, Gemini CLI and OpenCode — one source of guidance, rendered into whatever each tool reads, so a team on mixed tooling cannot end up with two versions of "how we write CakePHP here".

Developer
    │  npx @andygo.dev/cakephp-harness setup
    ▼
CakePHP Harness ── detects version ── installs guidance ── syncs manuals ── indexes ── serves MCP
                                                                                         │
                                                                                         ▼
                                                       Claude Code · Cursor · Codex · Gemini CLI · OpenCode

Requirements

  • Node.js >= 22.13 (uses the built-in node:sqlite)
  • A CakePHP project with a composer.json requiring cakephp/cakephp

No native modules, no compilation, no database server.

Quick start

cd my-cakephp-project
npx @andygo.dev/cakephp-harness setup

Or install the CLI once and run the binary:

npm install -g @andygo.dev/cakephp-harness
cd my-cakephp-project
cakephp-harness setup

That detects your CakePHP version, detects which coding agents the project already uses, installs the guidance and roles for each of them, downloads and indexes the matching manuals, and offers to register the MCP server with each agent.

To choose the agents yourself:

cakephp-harness setup --target claude-code --target cursor

Then:

cakephp-harness manuals search "middleware queue"
1. Middleware › Creating Middleware
   Section: Controllers
   Version: 5.x (project: 5.4)
   URL: https://book.cakephp.org/5/en/controllers/middleware.html#creating-middleware
   Id:  5.x:en:controllers/middleware.md#creating-middleware

   …MiddlewareQueue { // Add your simple middleware onto the queue …

Checking your setup

cakephp-harness doctor
✓ CakePHP project detected
✓ CakePHP version: 5.4
✓ Manuals synchronized
✓ Documentation index available
✓ CakePHP Skill installed
✓ Cursor guidance installed
✓ MCP server available
✓ search_cakephp_manual available
✓ get_cakephp_manual available
✓ search_cakephp_api available

Available commands:
  cakephp-harness setup                       Run the full idempotent setup flow
  cakephp-harness doctor                      Check setup health and list available commands
  cakephp-harness init                        Detect the project and create .cakephp-harness/
  cakephp-harness manuals sync                Download the official CakePHP manuals
  cakephp-harness manuals index               Build the manual search index
  cakephp-harness manuals update              Sync manuals and update the index
  cakephp-harness manuals search <query>      Search the CakePHP manuals
  cakephp-harness manuals status              Show synchronized and indexed manual status
  cakephp-harness manuals versions            List documentation lines and local status
  cakephp-harness specs index                 Index this project's own specs
  cakephp-harness specs search <query>        Search this project's own specs
  cakephp-harness specs status                Show project spec search status
  cakephp-harness targets list                List coding agents and their setup state
  cakephp-harness targets add <agent>         Set this project up for another coding agent
  cakephp-harness targets remove <agent>      Stop maintaining files for a coding agent
  cakephp-harness targets install             Reinstall files for every configured agent
  cakephp-harness skill install               Install the CakePHP guidance
  cakephp-harness skill update                Update the CakePHP guidance
  cakephp-harness agent install               Install the CakePHP roles
  cakephp-harness agent update                Update the CakePHP roles
  cakephp-harness mcp start                   Run the MCP server on stdio
  cakephp-harness mcp status                  Show MCP registration and readiness

The MCP checks are not assertions — doctor stands the server up over an in-memory transport, lists its tools and calls them, so a tool that is registered but broken (stale index, version drift) is reported as broken. Failures print the command that fixes them, and the exit code is non-zero, which makes it usable as a CI gate. doctor also prints the complete command catalog so it doubles as command discovery. --json emits the full report, including the command catalog.

Commands

| Command | What it does | |---|---| | setup | Everything below, in one idempotent command | | doctor | Check setup health and list available commands (--json) | | init | Detect the project and create .cakephp-harness/ (no downloads) | | manuals sync | Download the official manuals for your version | | manuals index | Build the SQLite/FTS5 search index | | manuals update | Sync, then incrementally reindex — the everyday command | | manuals search <query> | Search the manuals (--limit, --full, --version) | | manuals status | What is synced and indexed (--json) | | manuals versions | Documentation lines and their local status | | specs index | Index this project's own specs (opt-in; enables spec search) | | specs search <query> | Search this project's own specs (--limit, --full) | | specs status | Whether project spec search is enabled and current (--json) | | targets list | Coding agents, and whether each is set up (--json) | | targets add <agent> | Set the project up for another agent and install its files | | targets remove <agent> | Stop maintaining an agent's files (deletes nothing) | | targets install | Reinstall guidance, roles and MCP for every configured agent | | skill install / skill update | Install or refresh the guidance, for every agent | | agent install / agent update | Install or refresh the roles, for every agent | | mcp start | Run the MCP server on stdio (your coding agent launches this) | | mcp status | Registration per agent and documentation readiness (--json) |

Add --verbose to any command for diagnostics and stack traces. setup, targets install, skill install and agent install accept --target <agent> (repeatable) to work on one agent at a time.

Every command is safe to run repeatedly. manuals update detects that nothing changed and does no work; nothing will clobber your local edits.

What gets created

Always:

.cakephp-harness/
├── config.json                       project configuration
├── manuals/cakephp-5.x/              synced Markdown + .meta.json
├── index/docs.sqlite                 FTS5 search index (framework manual)
├── index/specs.sqlite                FTS5 search index (project specs, optional)
├── targets/<agent>.json              what the harness installed, per agent
└── cache/                            download cache

Then, per coding agent — only for the ones your project is set up for:

Claude Code       .claude/skills/cakephp/       SKILL.md + references/
                  .claude/agents/*.md           four subagents
                  .mcp.json

Cursor            .cursor/rules/cakephp.mdc     rule, auto-attached to **/*.php
                  .cursor/commands/*.md         four role playbooks
                  .cursor/mcp.json

OpenAI Codex CLI  AGENTS.md                     a marked-off block, merged in
                  .codex/config.toml

Gemini CLI        GEMINI.md                     a marked-off block, merged in
                  .gemini/commands/cakephp/*.toml   /cakephp:expert, …
                  .gemini/settings.json

OpenCode          AGENTS.md                     a marked-off block, merged in
                  .opencode/agent/*.md          four subagents
                  opencode.json

Agents that do not keep guidance in a self-contained directory share one copy of the reference documents at .cakephp-harness/instructions/references/, which their guidance file links to.

MCP registration files are only written if you approve the prompt.

The npm package contains the tooling. Documentation is downloaded locally by manuals sync, never bundled.

Package name: @andygo.dev/cakephp-harness. The installed CLI binary is still cakephp-harness.

Coding agents

Which agents a project is set up for is recorded in config.json as targets, and init proposes what it can detect (.cursor/, .codex/, GEMINI.md, opencode.json, …). Detection only ever informs a new config — once the list is recorded it is your decision, and adding .cursor/ to a repository will not silently start writing Cursor files.

cakephp-harness targets list
Agent        Set up   Detected   MCP
claude-code  yes      yes        yes
cursor       yes      yes        yes
codex        —        yes        —
gemini       —        —          —
opencode     —        —          —
cakephp-harness targets add codex
cakephp-harness targets remove cursor

targets remove stops maintaining an agent's files; it never deletes them. They are in your repository, possibly committed and possibly edited, and quietly deleting them because a config list changed is not a trade this tool makes. It prints exactly what was left behind.

One source of guidance

The conventions are written once, in this package's Skill templates, and rendered per agent. The four roles are written once as subagent definitions and re-expressed as whatever the tool actually supports:

| Agent | Roles become | Permissions | |---|---|---| | Claude Code | subagents in .claude/agents/ | native tools: list | | OpenCode | subagents in .opencode/agent/ | translated to tools: {write: false, …} | | Gemini CLI | commands — /cakephp:expert, … | not expressible | | Cursor | commands in .cursor/commands/ | not expressible | | OpenAI Codex CLI | playbook documents it is pointed at | not expressible |

Two details there are load-bearing. Claude Code namespaces MCP tools as mcp__<server>__<tool> and other clients do not, so the prefix is stripped for them — a role telling Gemini CLI to call mcp__cakephp-docs__search_cakephp_manual would simply never look anything up. And the reviewer's read-only restriction is translated rather than dropped where the syntax differs; where a tool cannot express it at all, that is stated rather than assumed.

AGENTS.md is shared by Codex and OpenCode, so a project set up for both gets one block describing both, rather than each overwriting the other's on every run.

MCP tools

Once registered, your coding agent gains these tools:

| Tool | Purpose | |---|---| | search_cakephp_manual | Ranked search; returns compact excerpts + documentId | | get_cakephp_manual | Full document text for a documentId | | search_cakephp_api | Look up a class or method | | search_project_specs | Search this project's own specs (optional, see below) | | get_project_spec | Full text of one of this project's spec documents |

Results are deliberately small — title, section, version, URL, excerpt, documentId — so a search never floods the context window. The agent fetches full documents only when it needs them.

Project specs (optional)

Beyond the framework manual, the harness can index your project's own specs, design notes and ADRs — the knowledge that explains how this application is meant to behave.

It is opt-in. Nothing scans your repository until you run:

cakephp-harness specs index
cakephp-harness specs search "invoice numbering"
1. Billing Rules › Invoice Numbering
   Section: docs
   File: docs/billing.md#invoice-numbering
   Id:   spec:docs/billing.md#invoice-numbering

   Invoice numbers use the prefix ACME- followed by a zero-padded sequence…

Which files count is configurable:

"specs": {
  "enabled": true,
  "include": ["docs/**/*.md", "specs/**/*.md", "*.md"],
  "exclude": ["vendor/**", "node_modules/**", ".cakephp-harness/**", ".claude/**",
              ".cursor/**", ".codex/**", ".gemini/**", ".opencode/**",
              "AGENTS.md", "CLAUDE.md", "GEMINI.md"]
}

Discovery prunes excluded directories rather than walking them, skips symlinks so it cannot escape the project, and indexes incrementally by content hash like the manual does.

The excludes cover every file the harness installs for a coding agent. Those hold framework guidance, and indexing them here would let CakePHP conventions come back out of search_project_specs dressed as this project's own requirements.

The two corpora never mix. Project specs live in their own SQLite database (index/specs.sqlite) with their own tools, so a project design note cannot be returned by search_cakephp_manual — that separation is structural, not a filter that could be got wrong. The tool descriptions and the server instructions both state which corpus is which, so an agent does not present your internal ADR as CakePHP framework behaviour.

The CakePHP roles

setup installs four roles for every coding agent the project is set up for:

| Role | Does | Tools | |---|---|---| | cakephp-expert | Implements and refactors CakePHP code | full (reads, edits, runs) | | cakephp-code-reviewer | Reviews CakePHP code for defects | read-only + MCP lookups | | cakephp-test-writer | Writes and repairs tests | read/write + Bash + MCP lookups | | cakephp-planner | Plans features, refactors and migrations before implementation | read-only + MCP lookups |

In Claude Code and OpenCode they are subagents:

> use the cakephp-expert agent to add soft deletes to the Articles table
> use the cakephp-planner agent to plan the billing refactor
> use the cakephp-code-reviewer agent on my changes
> use the cakephp-test-writer agent to cover ArticlesTable

In Gemini CLI they are commands (/cakephp:expert, /cakephp:code-reviewer, /cakephp:test-writer, /cakephp:planner); in Cursor, commands in .cursor/commands/; in Codex, playbook documents its AGENTS.md block points at.

All four share one defining rule: verify framework APIs against the documentation before asserting them. For the expert that means searching before writing; for the planner it means grounding implementation steps in this project's actual CakePHP version; for the reviewer it means confirming an API really is wrong before flagging it — a review that confidently flags correct code is worse than no review; for the test writer it means checking that an assertion actually exists in this version before relying on it.

The reviewer is restricted to Read, Grep, Glob, Bash plus the three MCP tools, so it cannot rewrite the code it is reviewing — translated to write: false, edit: false for OpenCode, and stated in the prose for tools that cannot enforce it. It reports findings as Critical / Warning / Suggestion with file:line and a concrete fix, covering CakePHP-specific defects: mass assignment via $_accessible, interpolated SQL conditions, N+1 from missing contain(), uniqueness checks misplaced in validation instead of buildRules(), unchecked save() returns, fat controllers, and missing CSRF tokens in integration tests.

The test writer carries two hard rules that tool permissions cannot express: it never edits production code to make a test pass (a failing test it wrote is a bug found, and it reports it instead), and it never claims a suite passes without actually running it. It knows the CakePHP 5 testing surface — IntegrationTestTrait, typed protected array $fixtures, enableCsrfToken(), getTableLocator() — and is told to cover failure paths, not just happy paths.

In Claude Code, tool names are namespaced by your MCP server name (mcp__cakephp-docs__search_cakephp_manual), so all four roles are rendered with the mcp.serverName from your config at install time — rename the server and agent update rewires them.

Unlike the ambient guidance, a subagent runs in a separate context with its own tool budget. Use the guidance for everyday CakePHP work; reach for a role on larger, self-contained tasks.

Manual registration

setup asks before touching any MCP configuration file. To do it yourself, in .mcp.json (Claude Code), .cursor/mcp.json (Cursor) or .gemini/settings.json (Gemini CLI):

{
  "mcpServers": {
    "cakephp-docs": {
      "command": "npx",
      "args": ["-y", "@andygo.dev/cakephp-harness", "mcp", "start"]
    }
  }
}

In opencode.json (OpenCode):

{
  "mcp": {
    "cakephp-docs": {
      "type": "local",
      "command": ["npx", "-y", "@andygo.dev/cakephp-harness", "mcp", "start"],
      "enabled": true
    }
  }
}

In .codex/config.toml (Codex CLI — it also reads ~/.codex/config.toml):

[mcp_servers.cakephp-docs]
command = "npx"
args = ["-y", "@andygo.dev/cakephp-harness", "mcp", "start"]

Existing servers in these files are never modified, and an entry for our own server that you have customised is left alone.

Version safety

This is the point of the tool, so it is strict.

Claude → MCP → project config → CakePHP version → version-specific index → search

CakePHP publishes documentation per major line — there is no 5.4 branch; the 5.x branch is the documentation for 5.4. So the harness records your project version (5.4) and maps it to a corpus (5.x), and never crosses a major-version boundary.

If the right documentation is not available, you get an error, not a guess:

✖ CakePHP 4.5 documentation has not been synchronized (corpus: cakephp-4.x, language: en).

Run:

  cakephp-harness manuals sync
  cakephp-harness manuals index

Indexed documentation for other versions is present but will not be used:
  cakephp-5.x (en, 1066 documents)

Version detection prefers composer.lock (exact, 5.4.2) and falls back to the composer.json constraint (^5.4).

How it works

Sync asks GitHub for the head commit of the cakephp/docs branch for your major line. If it matches what you have, nothing is downloaded. Otherwise it pulls the branch tarball once and extracts only docs/<lang>/**/*.md.

Indexing splits each page into one document per ## section — a section is the unit a developer actually wants back, and whole pages rank badly and blow up context. Each chunk is content-hashed, so re-indexing only touches what changed.

Search is BM25 via SQLite FTS5 by default, with title and heading weighted above body text. Queries are tokenised and re-quoted before they reach FTS5, so Cake\ORM\Table, find() and $this->Articles work rather than throwing syntax errors. The search widens in stages: all terms → any term → prefix.

Hybrid search (optional) blends that BM25 ranking with semantic similarity from local embeddings, combined by reciprocal rank fusion — a query phrased nothing like the manual's own wording ("how do I avoid mass assignment vulnerabilities") can still surface the right section. See Hybrid search below.

Storage is behind a repository interface so another backend can be added later.

Hybrid search (optional)

By default, search is BM25 only — lexical, offline, no extra dependency. Set index.searchStrategy to "hybrid" in .cakephp-harness/config.json to also rank by semantic similarity from a local embedding model, blended with BM25 by reciprocal rank fusion:

"index": {
  "searchStrategy": "hybrid",
  "embeddingModel": "Xenova/all-MiniLM-L6-v2"
}

Then reindex — hybrid search needs embeddings to search against, not just the FTS5 index:

cakephp-harness manuals update
cakephp-harness specs index

This works on an index you already have: nothing needs to change on disk for the embeddings to be filled in, and neither command re-downloads or re-parses anything it does not have to. It is also resumable — if the run is interrupted, everything embedded so far is kept and the next run picks up exactly what is still missing.

manuals status reports readiness (1058/1058 documents embedded), and manuals search / search_cakephp_manual refuse to run hybrid search with a message telling you to reindex, rather than silently falling back to bm25, unless every document in the corpus has an embedding for the configured model. Reading a document by id (get_cakephp_manual) and doctor never require embeddings, so neither is affected while a corpus is still filling in.

Why bother: BM25 only ever matches vocabulary that is actually in the query. A query phrased in the developer's own words — "how do I avoid mass assignment vulnerabilities" — has almost no token overlap with the manual's own heading, Mass Assignment, but hybrid search still ranks it first, because the embeddings capture that they mean the same thing.

What's actually running: a small sentence-embedding model (Xenova/all-MiniLM-L6-v2 by default) via @huggingface/transformers — transformers.js, a local WASM/ONNX runtime. No API key, no server, no outbound calls per query. The model downloads once on first use (a few tens of MB), reporting progress as it goes, and is cached after that.

Trade-offs worth knowing before you opt in:

  • It is the one path in this package that is not "no native modules": in Node, transformers.js runs its ONNX graph through onnxruntime-node, a small prebuilt (not compiled) native addon. The default bm25 strategy is entirely unaffected — this only loads if searchStrategy is hybrid.
  • @huggingface/transformers is listed as an optionalDependencies entry specifically so a bm25-only install never has to carry it. It pulls in onnxruntime-node and sharp (image handling the text-embedding path here never uses), both of which currently have open, unpatched high-severity advisories in their dependency chains at the time of writing — check npm audit before deciding whether that is acceptable for your project.
  • Indexing a full manual corpus (~1000 chunks) takes tens of seconds longer than bm25-only, since every added or changed chunk needs an embedding. A chunk that is unchanged and already has a vector for the configured model is never re-embedded.
  • Similarity is a brute-force cosine scan over stored vectors at query time — fine at the corpus sizes this tool deals with (low thousands of documents), deliberately not a dedicated ANN index for a problem this size does not have.

Security

Downloaded documentation is untrusted input:

  • extracted entries must be regular Markdown files under docs/<lang>/
  • absolute paths, .. segments, symlinks and hardlinks are rejected
  • every destination is verified to resolve inside the manuals directory
  • content is only ever stored and displayed — never executed, never interpolated into a shell command, never able to influence control flow

Programmatic use

import { detectCakePhpVersion, openCorpus, searchManuals } from '@andygo.dev/cakephp-harness';

The version model, config, sync, index, search, MCP server and the target installers are all exported. To set a project up for an agent from your own tooling:

import { installTargets, registerTargetServer, TARGETS } from '@andygo.dev/cakephp-harness';

await installTargets(['claude-code', 'cursor'], { root, serverName: 'cakephp-docs' });
await registerTargetServer(root, TARGETS.cursor, 'cakephp-docs');

Development

npm install
npm run build
npm test          # fully offline (hybrid search is tested against a fake embedding provider)
npm run typecheck

License

MIT