Skip to content

feat(cli): write AGENTS.md into project root for bare agent harnesses (INS-187)#139

Merged
tonychang04 merged 4 commits into
mainfrom
tonychang/ins-187-install-agentsmd-in-local-directory-for-true-harness-cli
May 24, 2026
Merged

feat(cli): write AGENTS.md into project root for bare agent harnesses (INS-187)#139
tonychang04 merged 4 commits into
mainfrom
tonychang/ins-187-install-agentsmd-in-local-directory-for-true-harness-cli

Conversation

@tonychang04
Copy link
Copy Markdown
Member

@tonychang04 tonychang04 commented May 24, 2026

What & why

insforge create / insforge link already install per-agent skills into per-agent directories (.claude/, .cursor/, .windsurf/, …) globally via npx skills add. But a bare "true harness" agent that follows the open agents.md standard reads a single ./AGENTS.md at the project root, and never looks at those per-agent dirs.

This PR makes the CLI also write an AGENTS.md into the local project directory during the same install step, so those harnesses get InsForge context. Resolves INS-187.

What the AGENTS.md says

  • What InsForge is (all-in-one Postgres BaaS).
  • When to use the installed skills — consult the insforge skill / insforge docs <feature> before implementing any InsForge feature, instead of guessing the API.
  • Where credentials live (.env.local / .insforge/project.json), @insforge/sdk for app code vs. the insforge CLI for infra, and a few high-leverage correctness patterns (array inserts, auth.users(id)/auth.uid(), storage url+key).

Behavior / design decisions

  • Idempotent merge. Content sits inside <!-- 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 repeated link runs, and a user's own AGENTS.md content is preserved.
  • Committed, not gitignored. Unlike the per-agent skill dirs, AGENTS.md is deliberately left out of the .gitignore block so it can be committed and shared (the whole point of the standard).
  • No secrets. Only the project name and the (already public) API host are embedded — never the api_key — because this file is committed.
  • Best-effort. Wired into installSkills() in its own try/catch so a write failure never aborts create/link.

Files

  • src/lib/agents-md.ts (new) — buildInsforgeBlock, pure mergeAgentsMd, writeLocalAgentsMd.
  • src/lib/agents-md.test.ts (new) — 14 unit tests (markers, idempotency, append-preserve, no-secret, content checks).
  • src/lib/skills.ts — call writeLocalAgentsMd(json) after updateGitignore().
  • README.md — Agent Skills section note.
  • package.json — version bump 0.1.820.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

  • Adds agents-md.ts with three utilities: buildInsforgeBlock generates a secret-free InsForge guidance block; mergeAgentsMd idempotently inserts or replaces the block in existing file content without touching user-written sections; writeLocalAgentsMd reads, merges, and writes AGENTS.md only when content changes.
  • Calls writeLocalAgentsMd at the end of installSkills in skills.ts inside a best-effort try/catch so failures are silently ignored.
  • The generated block includes installed skills, credential locations, and correctness patterns, but never embeds api_key.
  • AGENTS.md is committed (not gitignored) and updated in-place on repeated installs.

Macroscope summarized 2c444a6.

Summary by CodeRabbit

  • New Features

    • CLI now generates and maintains an AGENTS.md at the project root to document agent skills and public project config; the generated block is idempotent, refreshable, and preserves existing user content.
  • Documentation

    • README updated to describe AGENTS.md generation and behavior.
  • Tests

    • Added test coverage validating AGENTS.md creation, idempotency, merging, and preservation of user content.
  • Chores

    • Package version bumped to 0.1.83.

Review Change Stack

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>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 24, 2026

Walkthrough

This PR adds functionality to generate and maintain an AGENTS.md file at the project root containing project metadata within an InsForge-managed block. The implementation includes idempotent merge and file I/O logic, comprehensive test coverage, integration into skill installation, and updated documentation with a version bump.

Changes

AGENTS.md file generation and installation integration

Layer / File(s) Summary
AGENTS.md utilities with comprehensive tests
src/lib/agents-md.ts, src/lib/agents-md.test.ts
Marker constants (AGENTS_MD_START/AGENTS_MD_END) and exported functions: buildInsforgeBlock constructs a guidance block with conditional project metadata; mergeAgentsMd idempotently replaces, creates, or appends the block while preserving user content; writeLocalAgentsMd reads, merges, and writes the file only if changed. Tests validate marker wrapping, metadata inclusion, secret non-leakage, idempotent replacement across config changes, and filesystem behavior including preservation of existing content.
Integration into skill installation flow
src/lib/skills.ts
Imports writeLocalAgentsMd and calls it at the end of installSkills wrapped in silent try/catch, making the AGENTS.md generation a non-blocking best-effort step during skill creation and linking.
Documentation and version bump
README.md, package.json
Documents when and how the CLI writes/updates a root AGENTS.md for agents.md-standard harnesses, including the delimited block refresh behavior and non-gitignore status. Package version updated from 0.1.82 to 0.1.83.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • jwfing
  • Fermionic-Lyu

Poem

🐰 I nibble through README and tests,
I plant a block where AGENTS rests,
Markers snug and neat,
Idempotent and sweet,
The CLI hums — the project's blessed.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: writing AGENTS.md into the project root for bare agent harnesses, with a concise feature description and issue reference.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch tonychang/ins-187-install-agentsmd-in-local-directory-for-true-harness-cli

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 24, 2026

Greptile Summary

This PR adds an AGENTS.md generation step to insforge create / insforge link so that bare agent harnesses following the agents.md standard receive InsForge context alongside the per-agent skill directories already written by the CLI.

  • src/lib/agents-md.ts introduces buildInsforgeBlock, mergeAgentsMd, and writeLocalAgentsMd. The merge logic is idempotent via <!-- INSFORGE:START -->/<!-- INSFORGE:END --> markers, preserves existing user content, and handles orphaned/reversed markers and missing newline separators — both issues flagged in prior review threads.
  • src/lib/skills.ts calls writeLocalAgentsMd(json) inside its own try/catch after updateGitignore(), ensuring a write failure never blocks create/link.
  • 14 unit tests cover the merge scenarios end-to-end, including the two edge cases raised in earlier review rounds.

Confidence Score: 5/5

Safe 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

Filename Overview
src/lib/agents-md.ts New module implementing idempotent AGENTS.md generation with marker-based merge logic; previous reviewer concerns (orphaned START, missing newline guard) are addressed with code and tests.
src/lib/agents-md.test.ts 14 unit tests covering block construction, all merge branches, idempotency, orphaned-marker recovery, newline insertion, and no-secret guarantee.
src/lib/skills.ts Minimal addition: imports writeLocalAgentsMd and calls it in its own best-effort try/catch after updateGitignore().
README.md Added one paragraph documenting the AGENTS.md generation behavior in the Agent Skills section.
package.json Version bump 0.1.82 → 0.1.83 only.

Sequence Diagram

sequenceDiagram
    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)
Loading

Reviews (3): Last reviewed commit: "fix(cli): harden AGENTS.md merge against..." | Re-trigger Greptile

Comment thread src/lib/agents-md.ts
Comment thread src/lib/agents-md.ts Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 439b2c8 and 1510c11.

📒 Files selected for processing (5)
  • README.md
  • package.json
  • src/lib/agents-md.test.ts
  • src/lib/agents-md.ts
  • src/lib/skills.ts

Comment thread src/lib/agents-md.ts Outdated
…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>
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 5 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/lib/agents-md.ts Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
src/lib/agents-md.ts (1)

71-73: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Search for the end marker relative to the matched start marker.

endIdx currently 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

📥 Commits

Reviewing files that changed from the base of the PR and between 1510c11 and d4e714e.

📒 Files selected for processing (2)
  • src/lib/agents-md.test.ts
  • src/lib/agents-md.ts

claude added 2 commits May 23, 2026 17:58
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>
@tonychang04 tonychang04 enabled auto-merge (squash) May 24, 2026 01:09
Copy link
Copy Markdown
Member

@jwfing jwfing left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, approved.

@tonychang04 tonychang04 merged commit 40e9450 into main May 24, 2026
4 checks passed
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.

3 participants