feat(install): --skill=<name> installs a teaching skill per AI client - #46
Merged
Merged
Conversation
The third tier of the memory bridge slice. PR #44 made the memory plugin auto-select the SaaS backend. PR #45 lets the install CLI write the env block into client configs. This PR adds the skill file that teaches the agent WHEN and HOW to use the memory tools — without it, an agent has the tools but rarely calls them at the right moments. What's a "skill" here: Markdown content (with optional YAML frontmatter) that an AI client loads automatically at session start. Each major coding assistant has a slot for it: - Claude Code: ~/.claude/skills/<name>/skill.md - Claude Desktop: ~/Library/Application Support/Claude/skills/... For tools without a native skills concept (Cursor, Windsurf, Codex CLI), the same content gets wrapped in marker comments and surgically injected into their rules file. That codepath is scaffolded here (upsertManagedBlock + non-exclusive targets) but no rules-file clients are in the default target list yet — adding them needs per-tool research on the rules-file location semantics. Canonical skill — thinkfleet-memory: - Tells the agent to call agentmark_memory_search at session start to load project context. - Tells it to save user preferences, project facts, decisions without being asked. - Tells it to search memory before guessing about the user's environment. - Includes a scope picker, failure modes, and an explicit "what NOT to do" section (don't dump every memory at the user, don't save secrets, don't overwrite user-scope with session-scope writes). - Inlined as a TypeScript constant (~5KB) so the skill ships with the npm package without separate asset bundling. CLI surface: agentmark-mcp install \\ --client=claude-code \\ --env=THINKFLEET_BASE_URL=... \\ --env=THINKFLEET_PROJECT_ID=... \\ --env=THINKFLEET_API_KEY=... \\ --skill=thinkfleet-memory Validation: - Skill name must match [a-z0-9][a-z0-9-]* — rejects path- traversal attempts (../escape) and shell-relevant chars. - Unknown skill names log to stderr and the install still returns a non-zero exit so CI catches typos. - Atomic write via temp-file + rename, 0644 perms. - Idempotent: same content → "already_present"; different content → "updated"; non-existent → "added". Marker-block logic (pure function, fully tested): upsertManagedBlock(text, block) — replaces an existing <!-- thinkfleet:skill:start --> ... <!-- thinkfleet:skill:end --> block in place, or appends one if absent. Preserves user content outside the markers verbatim. Tests: - test/mcp/install-skills.test.ts — 16 cases covering: - upsertManagedBlock: append-empty, append-with-trailing-NL, replace-existing, idempotent, preserve-user-content. - installSkill end-to-end with fake targets: native (whole file), rules-file (marker block), already_present idempotency, dryRun, unsupported-platform skip. - Built-in skill catalog: thinkfleet-memory is registered, unknown names return null, every memory tool name appears in the skill content. - test/mcp/install-flags.test.ts — 6 new cases for --skill name validation. 596 tests pass. Typecheck clean. No new dependencies. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PR δ of the ThinkFleet Memory Bridge slice. Stacked on #45. This closes the loop on "AI tools just know how to use memory."
#44 made the memory plugin auto-select the SaaS backend.
#45 lets the install CLI write the env block into client configs.
This PR adds the skill file that teaches the agent when and how to use the memory tools — without it, an agent has the tools but rarely calls them at the right moments.
What's a "skill" here?
Markdown content (with optional YAML frontmatter) that an AI client loads automatically at session start. Each major coding assistant has a slot for it:
~/.claude/skills/<name>/skill.md(whole file)~/Library/Application Support/Claude/skills/...(whole file).cursorrules(marker block inside larger file).windsurfrules(marker block)AGENTS.md(marker block)The marker-block code path (
upsertManagedBlock+ non-exclusive targets) ships in this PR so a follow-up just registers the descriptors. Per-tool rules-file location semantics need a small amount of per-tool research.The canonical skill —
thinkfleet-memoryTells the agent to:
agentmark_memory_searchat session start to load project contextInlined as a TypeScript constant (~5KB) so the skill ships with the npm package without separate asset bundling.
CLI surface
```bash
agentmark-mcp install \
--client=claude-code \
--env=THINKFLEET_BASE_URL=... \
--env=THINKFLEET_PROJECT_ID=... \
--env=THINKFLEET_API_KEY=... \
--skill=thinkfleet-memory
```
Validation
[a-z0-9][a-z0-9-]*— rejects path-traversal (../escape) and shell-relevant chars0644permsalready_present; different →updated; non-existent →addedMarker-block logic (pure function, fully tested)
upsertManagedBlock(text, block)replaces an existing<!-- thinkfleet:skill:start --> ... <!-- thinkfleet:skill:end -->block in place, or appends one if absent. User content outside the markers is preserved verbatim — this is critical because rules files are user-owned.Tests
test/mcp/install-skills.test.ts— 16 cases:upsertManagedBlock: append-empty, append-with-trailing-NL, replace-existing, idempotent, preserve-user-contentinstallSkillend-to-end with fake targets: native (whole file), rules-file (marker block), already_present idempotency, dryRun, unsupported-platform skipthinkfleet-memoryis registered, unknown names return null, every memory tool appears in the skill contenttest/mcp/install-flags.test.ts— 6 new cases for--skillvalidation596 tests pass. Typecheck clean. No new dependencies.
Follow-ups (not in this PR)
DEFAULT_SKILL_TARGETS--skill=thinkfleet-memoryautomatically when memory creds are wired (small PR inrrader26/thinkfleet-desktop)🤖 Generated with Claude Code