feat(cli): write AGENTS.md into project root for bare agent harnesses (INS-187)#139
Conversation
create/link already install per-agent skills (.claude/, .cursor/, ...) globally, but a bare 'true harness' that follows the open agents.md standard reads ./AGENTS.md instead. Write/refresh an AGENTS.md in the project root during installSkills so those harnesses get InsForge context: what InsForge is, when to consult the installed skills, where credentials live, SDK vs CLI, and a few correctness patterns. - New src/lib/agents-md.ts: buildInsforgeBlock + idempotent mergeAgentsMd + writeLocalAgentsMd. Content is delimited by INSFORGE:START/END markers so it refreshes in place without duplicating, preserves any existing user AGENTS.md content, and embeds no secrets (the file is committed). - AGENTS.md is intentionally left out of the .gitignore block so it can be committed and shared, unlike the per-agent skill dirs. - Wired into installSkills (best-effort; never aborts create/link). - README note + version bump to 0.1.83. Closes INS-187 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
WalkthroughThis PR adds functionality to generate and maintain an ChangesAGENTS.md file generation and installation integration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Greptile SummaryThis PR adds an
Confidence Score: 5/5Safe to merge — the change is a best-effort, isolated file write that cannot block or corrupt the existing create/link flow. Both issues flagged in prior review rounds (orphaned START marker and missing newline separator) have been addressed in the implementation and are covered by dedicated tests. The merge logic is pure and well-bounded: it writes only to AGENTS.md, never touches secrets, and is wrapped in a try/catch in the caller. No existing behaviour is altered. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant CLI as insforge create / link
participant skills as installSkills()
participant gitignore as updateGitignore()
participant agentsmd as writeLocalAgentsMd()
participant fs as fs (AGENTS.md)
CLI->>skills: installSkills(json, authProvider?)
skills->>skills: npx skills add insforge/agent-skills
skills->>skills: npx skills add find-skills
skills->>gitignore: updateGitignore()
gitignore->>fs: appendFileSync(.gitignore)
skills->>agentsmd: writeLocalAgentsMd(json)
agentsmd->>fs: existsSync(AGENTS.md)
alt File does not exist or is blank
agentsmd->>agentsmd: mergeAgentsMd(null, config) → fresh file
else File has INSFORGE markers
agentsmd->>agentsmd: mergeAgentsMd(existing, config) → replace block in place
else File has no INSFORGE markers
agentsmd->>agentsmd: mergeAgentsMd(existing, config) → append block
end
agentsmd->>fs: writeFileSync(AGENTS.md, next)
Reviews (3): Last reviewed commit: "fix(cli): harden AGENTS.md merge against..." | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/lib/agents-md.ts`:
- Around line 68-70: The current logic finds startIdx with AGENTS_MD_START but
locates endIdx with existing.indexOf(AGENTS_MD_END) which can match an earlier
END marker; change endIdx to search after the matched start (e.g.,
existing.indexOf(AGENTS_MD_END, startIdx + AGENTS_MD_START.length)) so the END
corresponds to that START, then keep the existing guard (endIdx > startIdx) and
proceed with replacement using these corrected indices (references: existing,
AGENTS_MD_START, AGENTS_MD_END, startIdx, endIdx).
🪄 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: d5cf1c26-565c-4cc6-9c0e-d1bddfaa0cd6
📒 Files selected for processing (5)
README.mdpackage.jsonsrc/lib/agents-md.test.tssrc/lib/agents-md.tssrc/lib/skills.ts
…insforge docs Per review feedback: name each skill the CLI installs (insforge, insforge-cli, insforge-debug, insforge-integrations, find-skills) with a one-line 'when to use it', and stop recommending `insforge docs` as the fallback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
1 issue found across 5 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
♻️ Duplicate comments (1)
src/lib/agents-md.ts (1)
71-73:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winSearch for the end marker relative to the matched start marker.
endIdxcurrently searches the entire file from position 0. If user content above the InsForge block contains<!-- INSFORGE:END -->, the replacement logic is skipped and duplicate blocks accumulate on reruns, violating the idempotent contract.🔧 Proposed fix
const startIdx = existing.indexOf(AGENTS_MD_START); - const endIdx = existing.indexOf(AGENTS_MD_END); + const endIdx = + startIdx === -1 ? -1 : existing.indexOf(AGENTS_MD_END, startIdx + AGENTS_MD_START.length); if (startIdx !== -1 && endIdx > startIdx) {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/lib/agents-md.ts` around lines 71 - 73, The end marker search is using existing.indexOf(AGENTS_MD_END) from the file start, which can match an earlier marker and break idempotency; change the end index lookup to search after the found start index (use existing.indexOf(AGENTS_MD_END, startIdx)) so endIdx is relative to AGENTS_MD_START, ensuring the replacement logic around startIdx/endIdx correctly finds the matching pair and prevents duplicate blocks when running multiple times.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In `@src/lib/agents-md.ts`:
- Around line 71-73: The end marker search is using
existing.indexOf(AGENTS_MD_END) from the file start, which can match an earlier
marker and break idempotency; change the end index lookup to search after the
found start index (use existing.indexOf(AGENTS_MD_END, startIdx)) so endIdx is
relative to AGENTS_MD_START, ensuring the replacement logic around
startIdx/endIdx correctly finds the matching pair and prevents duplicate blocks
when running multiple times.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: fb6c191d-751a-4c37-b9b4-3a7cd937be92
📒 Files selected for processing (2)
src/lib/agents-md.test.tssrc/lib/agents-md.ts
Addresses CodeRabbit/cubic/greptile review: mergeAgentsMd located the END marker with indexOf from position 0, so a stray <!-- INSFORGE:END --> in the user's own content above the block could skip in-place replacement and append a duplicate block on rerun. Search for END after the matched START instead, preserving idempotency. Adds a regression test. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…g newline Addresses greptile review: - P1: an orphaned START marker (END manually deleted) fell through to the append path and wrote a duplicate block; a later run could then slice between the two blocks and eat user content. Now an existing START with no following END is replaced from START through end-of-file, recovering in place and staying idempotent. - P2: insert a newline when user content directly precedes the block so the START marker can't run onto the same line. Adds regression tests for both. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
What & why
insforge create/insforge linkalready install per-agent skills into per-agent directories (.claude/,.cursor/,.windsurf/, …) globally vianpx skills add. But a bare "true harness" agent that follows the open agents.md standard reads a single./AGENTS.mdat the project root, and never looks at those per-agent dirs.This PR makes the CLI also write an
AGENTS.mdinto the local project directory during the same install step, so those harnesses get InsForge context. Resolves INS-187.What the AGENTS.md says
insforgeskill /insforge docs <feature>before implementing any InsForge feature, instead of guessing the API..env.local/.insforge/project.json),@insforge/sdkfor app code vs. theinsforgeCLI for infra, and a few high-leverage correctness patterns (array inserts,auth.users(id)/auth.uid(), storageurl+key).Behavior / design decisions
<!-- INSFORGE:START -->…<!-- INSFORGE:END -->markers. No file → create it; existing file without our markers → append the block once; existing file with our markers → refresh in place. The file never grows on repeatedlinkruns, and a user's ownAGENTS.mdcontent is preserved.AGENTS.mdis deliberately left out of the.gitignoreblock so it can be committed and shared (the whole point of the standard).api_key— because this file is committed.installSkills()in its own try/catch so a write failure never abortscreate/link.Files
src/lib/agents-md.ts(new) —buildInsforgeBlock, puremergeAgentsMd,writeLocalAgentsMd.src/lib/agents-md.test.ts(new) — 14 unit tests (markers, idempotency, append-preserve, no-secret, content checks).src/lib/skills.ts— callwriteLocalAgentsMd(json)afterupdateGitignore().README.md— Agent Skills section note.package.json— version bump0.1.82→0.1.83.Verification
npm run lint(full vitest suite + eslint): 383 passed / 13 skipped, 0 errors.npm run build: success.🤖 Generated with Claude Code
Note
Write AGENTS.md into project root when installing skills
agents-md.tswith three utilities:buildInsforgeBlockgenerates a secret-free InsForge guidance block;mergeAgentsMdidempotently inserts or replaces the block in existing file content without touching user-written sections;writeLocalAgentsMdreads, merges, and writes AGENTS.md only when content changes.writeLocalAgentsMdat the end ofinstallSkillsinskills.tsinside a best-effort try/catch so failures are silently ignored.api_key.Macroscope summarized 2c444a6.
Summary by CodeRabbit
New Features
Documentation
Tests
Chores