feat: add build-adapter skill#2077
Conversation
Adds plugin/skills/build-adapter/SKILL.md — a single-file skill that hands /claude-mem:make-plan a dual-track research brief (claude-mem adapter contract + target platform extension API), then hands off to /claude-mem:do for execution and PR creation. The skill itself carries no architecture content; it names authoritative source files as anchors so subagents read live code. Trigger phrases cover "add claude-mem support for X", "build a claude-mem adapter for X", "integrate claude-mem with X", "make claude-mem work with X". Also includes the planning artifact at .plan/build-adapter-skill.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary by CodeRabbit
WalkthroughA new skill documentation file defines the Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Code Review —
|
Greptile SummaryThis PR adds
Confidence Score: 4/5Safe to merge after the slug-normalization gap is addressed; no risk to existing functionality. One P1 finding: multi-word target names (e.g. "Codex CLI") will produce invalid file paths and git refs because the brief provides no normalization rule for the plugin/skills/build-adapter/SKILL.md — the Synthesis and Final phase sections of the embedded brief need a slug-normalization instruction. Important Files Changed
Reviews (1): Last reviewed commit: "feat: add build-adapter skill for buildi..." | Re-trigger Greptile |
| > - New file: `src/cli/adapters/<target>.ts` | ||
| > - Register in `src/cli/adapters/index.ts` | ||
| > - If <TARGET> has a hook mechanism, add a manifest under `plugin/` or the | ||
| > appropriate location, mirroring `plugin/hooks/hooks.json` | ||
| > - If <TARGET> has no hook mechanism, plan uses direct HTTP POSTs to the | ||
| > worker instead | ||
| > - Tests mirror in `tests/cli/adapters/<target>.test.ts` if test convention | ||
| > applies | ||
| > | ||
| > ### Anti-patterns (MUST NOT) | ||
| > | ||
| > - Don't invent endpoints not in `SessionRoutes.ts` | ||
| > - Don't populate `agent_id` / `agent_type` unless <TARGET> has true subagents | ||
| > - Don't edit `CHANGELOG.md` (auto-generated) | ||
| > - Don't add a skills-registry manifest | ||
| > - Don't `--no-verify` / `--amend` / force-push | ||
| > - Don't use `claude-code.ts` as the copy-from template | ||
| > | ||
| > ### Final phase | ||
| > | ||
| > - Smoke test: `npm run build-and-sync`, then POST a synthetic observation | ||
| > to `/api/sessions/observations`, confirm it lands via `GET /api/sessions/status` | ||
| > - `git checkout -b adapter/<target>` | ||
| > - Commit: `feat(adapter): add <target> adapter` |
There was a problem hiding this comment.
<target> slug normalization not specified
The brief uses <TARGET> (the raw user-provided name) for display contexts and switches to <target> (lowercase) only for file/branch names — but never tells the executing AI how to normalize. For multi-word inputs like "Codex CLI" or "Continue.dev", the unguided AI may emit src/cli/adapters/Codex CLI.ts (space in filename) or branch adapter/Codex CLI (space in git ref), both of which are invalid.
Consider adding a one-line normalization rule at the top of the Synthesis section:
> ### Synthesis
>
> Normalize the target name to a lowercase slug (spaces → hyphens, strip non-alphanumeric except hyphens)
> and use that slug everywhere a filename or git ref is needed. Example: "Codex CLI" → `codex-cli`.
>
> Plan the implementation as phases…| ## Stop conditions | ||
|
|
||
| - Target has no documented extension API and no public repo → ask the user | ||
| for a docs URL before starting Track B | ||
| - Track B finds no session-ID mechanism → flag to user; a direct-HTTP | ||
| adapter may still be viable but needs explicit session-ID assignment | ||
| - `do` verification fails → do NOT open the PR; return control to user |
There was a problem hiding this comment.
No stop condition for missing target argument
The three existing stop conditions handle runtime research failures, but there's no guard for the trivially broken case where the user invokes /build-adapter with no argument. In that state <TARGET> passes through literally to make-plan, producing a prompt about building an adapter for the string "<TARGET>".
A short pre-flight check would close this gap:
| ## Stop conditions | |
| - Target has no documented extension API and no public repo → ask the user | |
| for a docs URL before starting Track B | |
| - Track B finds no session-ID mechanism → flag to user; a direct-HTTP | |
| adapter may still be viable but needs explicit session-ID assignment | |
| - `do` verification fails → do NOT open the PR; return control to user | |
| ## Stop conditions | |
| - No target argument provided → reply "Usage: `/build-adapter <target>` — please specify the agent, IDE, or CLI name." and stop. | |
| - Target has no documented extension API and no public repo → ask the user | |
| for a docs URL before starting Track B | |
| - Track B finds no session-ID mechanism → flag to user; a direct-HTTP | |
| adapter may still be viable but needs explicit session-ID assignment | |
| - `do` verification fails → do NOT open the PR; return control to user |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.plan/build-adapter-skill.md:
- Around line 57-59: The table entry incorrectly points to the
export/registration file rather than where the interface is declared; update the
"Adapter" / "PlatformAdapter" table row so its Location references the file that
actually declares the PlatformAdapter interface (the file that contains the
PlatformAdapter type declaration), not the file that only exports
getPlatformAdapter/registration; ensure the table text names PlatformAdapter (or
Adapter) consistently and remove the misleading reference to the registration
file (where getPlatformAdapter is defined).
In `@plugin/skills/build-adapter/SKILL.md`:
- Line 13: The "## When to use" heading in SKILL.md is missing a blank line
above it; add a single blank line immediately before the line containing the
heading "## When to use" so the heading is separated from the previous
paragraph/content to follow Markdown convention.
- Around line 33-35: The documentation points Track A to the wrong place for the
Adapter contract; update the doc so it references the actual interface name
PlatformAdapter and its method signatures normalizeInput and formatOutput
instead of pointing to index.ts; specifically mention that the interface is
defined where PlatformAdapter is declared (imported into the adapter
registration code which contains getPlatformAdapter) so the subagent reads
PlatformAdapter to obtain the normalizeInput/formatOutput signatures rather than
the registration-only file.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: de5df742-c450-40e5-86fe-80fa5188ce28
📒 Files selected for processing (2)
.plan/build-adapter-skill.mdplugin/skills/build-adapter/SKILL.md
| | Surface | Location | Role in adapter | | ||
| |---|---|---| | ||
| | `Adapter` interface | `src/cli/adapters/index.ts` | Normalizer + formatter contract every adapter implements | |
There was a problem hiding this comment.
Incorrect file reference for the Adapter interface.
Line 59 lists the Adapter interface location as src/cli/adapters/index.ts, but the PlatformAdapter interface is actually defined in src/cli/types.ts. The index.ts file contains only the registration pattern (the getPlatformAdapter function and exports), not the interface definition.
This is the same issue flagged in SKILL.md and should be corrected for consistency.
🔧 Proposed fix for the table
| Surface | Location | Role in adapter |
|---|---|---|
+| `PlatformAdapter` interface | `src/cli/types.ts:35–42` | Normalizer + formatter contract every adapter implements |
-| `Adapter` interface | `src/cli/adapters/index.ts` | Normalizer + formatter contract every adapter implements |
+| Registration pattern | `src/cli/adapters/index.ts` | getPlatformAdapter switch, imports, exports |
| Best exemplars | `src/cli/adapters/cursor.ts`, `gemini-cli.ts` | Copy-from templates (NOT `claude-code.ts` — too special-cased) |🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.plan/build-adapter-skill.md around lines 57 - 59, The table entry
incorrectly points to the export/registration file rather than where the
interface is declared; update the "Adapter" / "PlatformAdapter" table row so its
Location references the file that actually declares the PlatformAdapter
interface (the file that contains the PlatformAdapter type declaration), not the
file that only exports getPlatformAdapter/registration; ensure the table text
names PlatformAdapter (or Adapter) consistently and remove the misleading
reference to the registration file (where getPlatformAdapter is defined).
|
|
||
| # build-adapter | ||
|
|
||
| ## When to use |
There was a problem hiding this comment.
Add blank line above heading.
Markdown formatting convention requires blank lines surrounding headings.
📝 Proposed formatting fix
description: Use when the user wants claude-mem to work with a new agent, IDE,
or CLI (Cursor, Zed, Aider, Codex, custom agents, etc.). Researches both
claude-mem's adapter contract and the target platform's extension API in
parallel via make-plan, executes the plan via do, and opens a PR. Trigger
phrases: "add claude-mem support for X", "build a claude-mem adapter for X",
"integrate claude-mem with X", "make claude-mem work with X".
---
+
# build-adapter🧰 Tools
🪛 markdownlint-cli2 (0.22.0)
[warning] 13-13: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@plugin/skills/build-adapter/SKILL.md` at line 13, The "## When to use"
heading in SKILL.md is missing a blank line above it; add a single blank line
immediately before the line containing the heading "## When to use" so the
heading is separated from the previous paragraph/content to follow Markdown
convention.
| > Explore subagent reads and reports file:line facts from: | ||
| > - `src/cli/adapters/index.ts` — the `Adapter` interface (normalizeInput, | ||
| > formatOutput, registration) |
There was a problem hiding this comment.
Incorrect file reference for the Adapter interface.
Line 34 instructs Track A to read the Adapter interface from src/cli/adapters/index.ts, but the PlatformAdapter interface is actually defined in src/cli/types.ts (lines 35-42). The index.ts file only contains the registration pattern (getPlatformAdapter function) and imports the interface from ../types.js.
This will cause the Track A subagent to miss the actual interface contract (normalizeInput and formatOutput method signatures), which is critical for implementing a new adapter.
🔧 Proposed fix
> Explore subagent reads and reports file:line facts from:
+> - `src/cli/types.ts` — the `PlatformAdapter` interface (normalizeInput,
+> formatOutput signatures)
> - `src/cli/adapters/index.ts` — the `Adapter` interface (normalizeInput,
-> formatOutput, registration)
+> registration pattern (getPlatformAdapter function, exports)
> - `src/cli/adapters/cursor.ts` and `src/cli/adapters/gemini-cli.ts` — use📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| > Explore subagent reads and reports file:line facts from: | |
| > - `src/cli/adapters/index.ts` — the `Adapter` interface (normalizeInput, | |
| > formatOutput, registration) | |
| > Explore subagent reads and reports file:line facts from: | |
| > - `src/cli/types.ts` — the `PlatformAdapter` interface (normalizeInput, | |
| > formatOutput signatures) | |
| > - `src/cli/adapters/index.ts` — the `Adapter` interface registration pattern (getPlatformAdapter function, exports) | |
| > - `src/cli/adapters/cursor.ts` and `src/cli/adapters/gemini-cli.ts` — use |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@plugin/skills/build-adapter/SKILL.md` around lines 33 - 35, The documentation
points Track A to the wrong place for the Adapter contract; update the doc so it
references the actual interface name PlatformAdapter and its method signatures
normalizeInput and formatOutput instead of pointing to index.ts; specifically
mention that the interface is defined where PlatformAdapter is declared
(imported into the adapter registration code which contains getPlatformAdapter)
so the subagent reads PlatformAdapter to obtain the normalizeInput/formatOutput
signatures rather than the registration-only file.
Merges 33 commits from main including v12.3.1 release, the 301-anti-pattern error-handling cleanup (PR #2077), subagent observation labeling (PR #2073), worktree adoption with merged_into_project (PR #2052), infinite summary-retry break (PR #2072), basic Docker container (PR #2076), and assorted parser + OpenRouter fixes. Conflict resolution preserved both sides' features: - Observation metadata pipeline (HEAD's tool_name/source_url/command capture via processingMessageMeta) coexists with subagent labeling (main's agent_type/agent_id on observations + pending_messages). All 5 observation INSERT paths updated to 19-column form. - TITANS conversation observations through SessionManager (HEAD) coexist with the refactored GeminiAgent.processMessageLoop / OpenRouterAgent.processOneMessage helpers (main). processingMessageMeta push added to both extracted helpers. - Layer 3 transcript storage (HEAD's addTranscriptChunks / getTranscriptSegment / queryTranscriptSegment on ChromaSync) coexists with worktree adoption's updateMergedIntoProject. - Migrations: HEAD's addObservationMetadataColumn (v27) + addConversationMessageType (v28) run alongside main's ensureMergedIntoProjectColumns + addObservationSubagentColumns (also v27 — documented coexistence via INSERT OR IGNORE + PRAGMA column guards). Migration 28 rewritten to preserve agent_type/agent_id columns in the recreated pending_messages table. - ResponseProcessor: storeObservations call now threads both labeledObservations (agent identity) and sourceMetadata, wrapped in try/finally so agent identity clears even on storage failure. - Retained main's cleaner error-handling style everywhere outside the above feature intersections (consecutiveSummaryFailures circuit breaker, unknown-error instanceof handling, OpenRouter assistant-history restoration). - MCP server timeout fix (our 5-min worker API timeout) preserved by pushing timeoutMs into executeWorkerPostRequest helper. Built artifacts regenerated from merged source via npm run build. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
plugin/skills/build-adapter/SKILL.md— an auto-discovered skill that generates a new claude-mem adapter for any agent/IDE/CLI in one shot./claude-mem:make-plana dual-track research brief: Track A reads the claude-mem adapter contract from live source (Adapter interface, HookInput, SessionRoutes, DB schema, hooks.json), Track B researches the target platform's extension API with WebSearch/WebFetch/mcp-deepwiki./claude-mem:doto write the adapter, register it, smoke-test, commit, and open a PR..plan/build-adapter-skill.md.The skill itself is 112 lines and embeds no architecture content — it only names source-file anchors so subagents read live code. This keeps the skill resilient to refactors.
Test plan
/build-adapter zed(or another real target) and observe that make-plan dispatches two Phase 0 subagents in parallel.dowritessrc/cli/adapters/<target>.ts, registers it insrc/cli/adapters/index.ts, and opens a smoke-test PR with a successful round-trip observation.npm run build-and-syncon this branch to confirm plugin build still passes (skill addition should be non-breaking).Anti-patterns checked
CHANGELOG.md(auto-generated per CLAUDE.md).plugin/skills/).nameanddescription, matching the convention of peer skills (make-plan,do,mem-search).references/,templates/, orscripts/subdirectories created.