Skip to content

feat(install): --skill=<name> installs a teaching skill per AI client - #46

Merged
rrader26 merged 1 commit into
feat/install-env-supportfrom
feat/thinkfleet-memory-skill
May 15, 2026
Merged

feat(install): --skill=<name> installs a teaching skill per AI client#46
rrader26 merged 1 commit into
feat/install-env-supportfrom
feat/thinkfleet-memory-skill

Conversation

@rrader26

Copy link
Copy Markdown
Contributor

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:

Client Mechanism Status in this PR
Claude Code ~/.claude/skills/<name>/skill.md (whole file)
Claude Desktop ~/Library/Application Support/Claude/skills/... (whole file)
Cursor .cursorrules (marker block inside larger file) 🚧 scaffolded, default target list excludes for now
Windsurf .windsurfrules (marker block) 🚧 scaffolded
Codex CLI AGENTS.md (marker block) 🚧 scaffolded

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-memory

Tells the agent to:

  • Call agentmark_memory_search at session start to load project context
  • Save user preferences, project facts, decisions without being asked
  • Search memory before guessing about the user's environment
  • Use the scope picker correctly (platform / user / project / agent / session)
  • Recognize failure modes (don't keep asking "is memory working?")
  • Avoid pitfalls (don't dump every memory at the user, don't save secrets, don't overwrite user-scope with session writes)

Inlined 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

  • Skill name must match [a-z0-9][a-z0-9-]* — rejects path-traversal (../escape) and shell-relevant chars
  • Unknown skill names log to stderr; install exits non-zero so CI catches typos
  • Atomic write via temp-file + rename, 0644 perms
  • Idempotent: same content → already_present; different → 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. User content outside the markers is preserved verbatim — this is critical because rules files are user-owned.

Tests

  • test/mcp/install-skills.test.ts16 cases:
    • 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 appears in the skill content
  • test/mcp/install-flags.test.ts6 new cases for --skill validation

596 tests pass. Typecheck clean. No new dependencies.

Follow-ups (not in this PR)

  • Wire Cursor / Windsurf / Codex CLI rules-file targets into DEFAULT_SKILL_TARGETS
  • Skill versioning: re-install when the skill content version bumps even if the file exists
  • ThinkFleet Desktop integration: pass --skill=thinkfleet-memory automatically when memory creds are wired (small PR in rrader26/thinkfleet-desktop)

🤖 Generated with Claude Code

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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants