agentleFS
amtiYoamtiYo/agents/AGENTS.md

agents

AGENTS.md102 starsChanged 2 months agoApache-2.0View on GitHub

Instructions for AI coding agents working on the @agents-dev/cli project. @agents-dev/cli is a CLI tool that provides a practical standard layer for multi-LLM development. It solves the configuration fragmentation problem by syncing MCP servers, skills and instructions across 18 AI coding tools from a single source of truth, and packages the result as an Agent Plugins bundle. Key Principle: One .agents/ folder syncs to all tools. Add an MCP server once, it appears everywhere. Projects have: - .agents/agents.json — MCP…

  • Installs packages
  • Commits and pushes
  • Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.

    Of the AGENTS.md files we read, the 31,542 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.

  • In this repository3 other files it gives its agents.

The file

Show its rules and text

We split this AGENTS.md into the rules it gives an agent

46 rules. About 1 is common, 28 are distinctive, and 17 are very specific to this project.

  • ≈1

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈28

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 17

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Unit tests: Test individual functions in isolation

    line 77
  2. Distinctive:

    Integration tests: Test full command flows with temp directories

    line 78
  3. Very specific:

    Use mkdtemp for temporary test directories

    line 79
  4. Very specific:

    Always clean up in afterEach hooks

    line 80
  5. Distinctive:

    Follow existing patterns and conventions

    line 86
  6. Distinctive:

    Use descriptive variable names

    line 87
  7. Distinctive:

    Add JSDoc comments for exported functions

    line 88
  8. Distinctive:

    Keep functions focused (single responsibility)

    line 89
  9. Distinctive:

    Prefer pure functions where possible

    line 90
  10. Very specific:

    Read .agents/agents.json and .agents/local.json

    line 105
  11. Distinctive:

    Write atomically (temp file + rename)

    line 108
  12. Distinctive:

    Read the section with a line scan, so a syntax error elsewhere does not hide it

    line 148
  13. Distinctive:

    Never reserialize the whole config: it carries comments and settings we do not own

    line 152
  14. Distinctive:

    Write to temp file

    line 157
  15. Very specific:

    Add tests in tests/your-command.test.ts

    line 168
  16. Distinctive:

    Update README.md command reference

    line 169
  17. Very specific:

    Add renderer in src/core/renderers.ts

    line 180
  18. Very specific:

    Add the paths it needs in src/core/paths.ts

    line 181
  19. Very specific:

    Add a sync hook in src/integrations/syncHooks.ts

    line 187
  20. Very specific:

    Add the skills bridge to SKILL_BRIDGES in src/core/skills.ts, or set nativeSkills when the tool reads .agents/skills itself

    line 188
  21. Distinctive:

    Update README supported tools table

    line 191
  22. Distinctive:

    Write a failing test that reproduces the bug

    line 195
  23. Distinctive:

    Add edge case tests

    line 198
  24. Distinctive:

    Update CHANGELOG.md (## Unreleased > ### Fixed)

    line 199
  25. Distinctive:

    Write tests for new behavior

    line 204
  26. Distinctive:

    Update CHANGELOG.md (## Unreleased > ### Added)

    line 207
  27. Very specific:

    Use src/core/ui.ts for all user-facing output:

    line 249
  28. Very specific:

    Never use raw console.log() for user-facing output

    line 276
  29. Very specific:

    Use ui.spin() for any operation > 500ms

    line 277
  30. Distinctive:

    If a test is flaky (timing-dependent):

    line 334
  31. Distinctive:

    Add retry logic if appropriate

    line 336
  32. Distinctive:

    Create GitHub release with tag

    line 347
  33. Very specific:

    Always use afterEach to clean up, or tests will leave garbage in /tmp.

    line 365
  34. Distinctive:

    Check if CLI is installed before calling:

    line 390
  35. Common:

    Never log secrets to console

    line 402
  36. Very specific:

    Use --secret-env and --secret-header flags for sensitive values

    line 403
  37. Distinctive:

    Don't execute arbitrary code from config files

    line 405
  38. Very specific:

    Use sync --check for drift detection (faster than full sync)

    line 409
  39. Very specific:

    Use status --fast to skip slow external CLI probes

    line 410
  40. Very specific:

    Use Promise.all() for parallel operations

    line 412
  41. Distinctive:

    Keep README.md concise (high-level overview)

    line 417
  42. Very specific:

    Put details in docs/ files

    line 418
  43. Distinctive:

    Use code examples for clarity

    line 419
  44. Distinctive:

    Check existing code for patterns

    line 447
  45. Distinctive:

    Read tests for examples

    line 448
  46. Distinctive:

    Ask in GitHub Discussions

    line 449

≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

AGENTS.md

Instructions for AI coding agents working on the @agents-dev/cli project.

Project Overview

@agents-dev/cli is a CLI tool that provides a practical standard layer for multi-LLM development. It solves the configuration fragmentation problem by syncing MCP servers, skills and instructions across 18 AI coding tools from a single source of truth, and packages the result as an Agent Plugins bundle.

Key Principle: One .agents/ folder syncs to all tools. Add an MCP server once, it appears everywhere.

Tech Stack

  • Language: TypeScript (strict mode)
  • Runtime: Node.js 20.12+
  • Build: tsc (TypeScript compiler)
  • Tests: Vitest
  • CLI Framework: Commander.js
  • Prompts: @clack/prompts
  • Package Manager: npm

Project Structure

agents/
├── src/
│   ├── cli.ts                    # CLI entry point
│   ├── commands/                 # Command implementations
│   │   ├── start.ts             # Setup wizard
│   │   ├── sync.ts              # Config sync
│   │   ├── mcp-add.ts           # Add MCP server
│   │   └── ...
│   ├── core/                     # Core logic
│   │   ├── sync.ts              # Sync orchestration
│   │   ├── mcp.ts               # MCP management
│   │   ├── renderers.ts         # Tool-specific config generators
│   │   ├── trust.ts             # Codex trust management
│   │   ├── ui.ts                # CLI output helpers (colors, spinners)
│   │   └── ...
│   ├── integrations/             # Tool integrations
│   │   ├── codex.ts
│   │   ├── claude.ts
│   │   ├── cursor.ts
│   │   └── ...
│   └── types.ts                  # TypeScript types
├── tests/                        # Test files
│   ├── *.test.ts                # Unit tests
│   └── *.integration.test.ts    # Integration tests
├── templates/                    # Scaffold templates
│   └── agents/                  # .agents/ directory templates
├── docs/                         # Public documentation
└── bin/agents                    # CLI wrapper script

Development Workflow

Setup

npm install
npm run build
npm link

Development Commands

npm run dev -- <command>          # Run CLI in dev mode
npm run build                     # Compile TypeScript
npm test                          # Run all tests
npm test tests/sync.test.ts       # Run specific test
npm test -- --watch               # Watch mode
npm run lint                      # Run ESLint

Testing

  • Unit tests: Test individual functions in isolation
  • Integration tests: Test full command flows with temp directories
  • Use mkdtemp for temporary test directories
  • Always clean up in afterEach hooks
  • Mock external CLI calls when appropriate

Code Style

  • TypeScript strict mode is enabled
  • Follow existing patterns and conventions
  • Use descriptive variable names
  • Add JSDoc comments for exported functions
  • Keep functions focused (single responsibility)
  • Prefer pure functions where possible

Key Concepts

1. Project Structure (core/project.ts)

Projects have:

  • .agents/agents.json — MCP servers, shared config
  • .agents/local.json — Secrets (gitignored)
  • .agents/skills/ — Reusable workflows
  • .agents/generated/ — Auto-generated files (gitignored)
  • AGENTS.md — Instructions for all tools

2. Sync Process (core/sync.ts)

  1. Read .agents/agents.json and .agents/local.json
  2. Merge configs (local overrides shared)
  3. Generate tool-specific configs via renderers
  4. Write atomically (temp file + rename)
  5. Acquire sync lock to prevent race conditions

3. Renderers (core/renderers.ts)

Each tool has a renderer that converts .agents/agents.json to tool-specific format:

  • Codex: TOML (.codex/config.toml)
  • Claude Code: JSON (.mcp.json, project scope, shared with Copilot CLI)
  • Gemini: JSON (.gemini/settings.json)
  • Cursor: JSON (.cursor/mcp.json)
  • Copilot VS Code: JSON (.vscode/mcp.json)
  • Antigravity: JSON (.agents/mcp_config.json)
  • Grok Build: TOML (.grok/config.toml), same dialect as Codex with a headers table
  • Amp: JSON (.amp/settings.json, key amp.mcpServers)
  • Droid / Devin: JSON (.factory/mcp.json, .devin/mcp_config.json)
  • Kilo: JSONC (.kilo/kilo.jsonc, key mcp)
  • Zed: JSONC (.zed/settings.json, key context_servers)
  • Goose: YAML (~/.config/goose/config.yaml, key extensions)

Two renderers are shared: Codex and Grok use renderMcpToml with different options, OpenCode and Kilo use the same local/remote shape.

4. MCP Server Management (core/mcp.ts)

MCP servers have:

  • Transport: stdio (command-based) or http/sse (URL-based). sse is deprecated by the MCP 2026-07-28 specification and flagged by agents doctor.
  • Config: command, args, env, headers, cwd, plus the optional timeout, connectTimeout, tools, disabledTools, oauth, headersHelper, bearerTokenEnvVar and envFile, each rendered only where the tool supports it
  • Secrets: Stored in .agents/local.json, never exported into a plugin
  • Validation: Keys must be shell-safe (env) or HTTP token format (headers)
  • Profiles: profiles and activeProfile select a subset of servers for a sync

5. Trust Management (core/trust.ts)

Codex ignores a project-local .codex/config.toml unless the project is trusted, and there is no codex trust command to do it. Trust lives in the [projects."<path>"] section of the global ~/.codex/config.toml, which we edit in place:

  • Read the section with a line scan, so a syntax error elsewhere does not hide it
  • Refuse to touch a file Codex itself cannot parse; agents doctor reports the error
  • Refuse to append when the project is recorded in another valid TOML shape, which would create a duplicate key and break the file
  • Never reserialize the whole config: it carries comments and settings we do not own

6. File Safety (core/fs.ts)

Critical operations use atomic writes:

  • Write to temp file
  • Rename to target (atomic on most filesystems)
  • Prevents data corruption if process crashes

Common Tasks

Adding a New Command

  1. Create src/commands/your-command.ts
  2. Export async function matching command signature
  3. Register in src/cli.ts with Commander
  4. Add tests in tests/your-command.test.ts
  5. Update README.md command reference
  6. Update CHANGELOG.md

Adding a New Tool Integration

Before writing code: confirm the config path and schema in the vendor's own documentation, and run the tool's CLI against a generated file if it is installed. Integrations verified that way are marked in the README table; the rest say so.

  1. Create src/integrations/your-tool.ts
  2. Implement integration interface (id, name, paths)
  3. Add renderer in src/core/renderers.ts
  4. Add the paths it needs in src/core/paths.ts
  5. Register in src/integrations/registry.ts, including the config descriptor: the path key, the format and the label. status, doctor, reset and start read the descriptor, so this is the only place that list lives. A tool whose file depends on an option or the platform has no descriptor and is handled where that choice is made — add it to WITHOUT_DESCRIPTOR in tests/integration-registry.test.ts with the reason.
  6. Add a sync hook in src/integrations/syncHooks.ts
  7. Add the skills bridge to SKILL_BRIDGES in src/core/skills.ts, or set nativeSkills when the tool reads .agents/skills itself
  8. Add tests
  9. Update README supported tools table

Fixing a Bug

  1. Write a failing test that reproduces the bug
  2. Fix the bug
  3. Verify test passes
  4. Add edge case tests
  5. Update CHANGELOG.md (## Unreleased > ### Fixed)

Adding a Feature

  1. Discuss in GitHub issue first (if major)
  2. Write tests for new behavior
  3. Implement feature
  4. Update documentation
  5. Update CHANGELOG.md (## Unreleased > ### Added)

Important Patterns

Error Handling

// Throw descriptive errors
throw new Error(`MCP server "${name}" not found in .agents/agents.json`)

// User-facing errors should be clear and actionable
console.error(`Error: Invalid env key "${key}". Use format: [A-Za-z_][A-Za-z0-9_]*`)
process.exitCode = 1

File Operations

// Always use atomic writes for critical files
import { writeJsonAtomic } from './core/fs.js'

await writeJsonAtomic(path, data)

External CLI Calls

// Use spawnSync for external commands
import { spawnSync } from 'node:child_process'

const result = spawnSync('codex', ['trust', 'list'], {
  encoding: 'utf-8',
  stdio: ['ignore', 'pipe', 'pipe']
})

if (result.status !== 0) {
  // Handle error
}

CLI Output (UI Module)

Use src/core/ui.ts for all user-facing output:

import { ui } from './core/ui.js'

// Status messages
ui.success('Config synced')
ui.error('Failed to connect')
ui.warning('Server not responding')
ui.info('Checking configuration...')

// Formatted output
ui.keyValue('Status', 'connected')
ui.list(['item1', 'item2'])
ui.section('MCP Servers')
ui.hint('Run `agents sync` to apply changes')

// Spinners for async operations
const result = await ui.spin('Syncing...', async () => {
  return await doAsyncWork()
})

// Context-aware (respects --json, --quiet, NO_COLOR)
ui.json(data)  // Only outputs if --json flag is set

Rules:

  • Never use raw console.log() for user-facing output
  • Use ui.spin() for any operation > 500ms
  • Colors are minimal: green (success), red (error), yellow (warning), cyan (info)
  • Unicode symbols have ASCII fallbacks for non-Unicode terminals

Temp Directories in Tests

import { mkdtemp, rm } from 'node:fs/promises'
import { join } from 'node:path'
import { tmpdir } from 'node:os'

describe('my test', () => {
  const tempDirs: string[] = []

  afterEach(async () => {
    await Promise.all(tempDirs.map(dir => rm(dir, { recursive: true, force: true })))
    tempDirs.length = 0
  })

  it('does something', async () => {
    const dir = await mkdtemp(join(tmpdir(), 'agents-test-'))
    tempDirs.push(dir)
    // test logic
  })
})

Testing Guidelines

What to Test

  • ✅ All public functions
  • ✅ Error conditions
  • ✅ Edge cases (empty arrays, null values, etc.)
  • ✅ Integration flows (full command execution)
  • ✅ File I/O (read/write operations)
  • ❌ Don't test third-party libraries

Test Structure

describe('feature', () => {
  it('should do X when Y', () => {
    // Arrange
    const input = { ... }

    // Act
    const result = myFunction(input)

    // Assert
    expect(result).toBe(expected)
  })
})

Flaky Tests

If a test is flaky (timing-dependent):

  • Increase timeout: it('test', { timeout: 10000 }, async () => { ... })
  • Add retry logic if appropriate
  • Mock external dependencies that cause flakiness

Release Process

(For maintainers only - see .docs-internal/PUBLISHING.md)

  1. Update CHANGELOG.md
  2. Bump version: npm version patch|minor|major
  3. Build and test: npm run build && npm test
  4. Publish: npm publish --access public
  5. Create GitHub release with tag

Common Pitfalls

1. Forgetting Atomic Writes

Wrong:

await writeFile(path, JSON.stringify(data))

Right:

await writeJsonAtomic(path, data)

2. Not Cleaning Up Temp Dirs in Tests

Always use afterEach to clean up, or tests will leave garbage in /tmp.

3. Hardcoding Paths

Wrong:

const codexConfig = '/Users/me/.codex/config.toml'

Right:

import { getCodexConfigPath } from './core/paths.js'
const codexConfig = getCodexConfigPath()

4. Not Validating User Input

Always validate:

  • MCP server names (no spaces, special chars)
  • Env keys (shell-safe format)
  • Header keys (HTTP token format)
  • File paths (absolute, not relative)

5. Assuming External CLIs Are Available

Check if CLI is installed before calling:

const result = spawnSync('codex', ['--version'], { encoding: 'utf-8' })
if (result.status !== 0) {
  console.warn('Codex CLI not found. Skipping Codex integration.')
  return
}

Security Considerations

  • Secrets are stored in .agents/local.json (gitignored)
  • Never log secrets to console
  • Use --secret-env and --secret-header flags for sensitive values
  • Validate all user input (especially paths and shell commands)
  • Don't execute arbitrary code from config files

Performance Tips

  • Use sync --check for drift detection (faster than full sync)
  • Use status --fast to skip slow external CLI probes
  • Cache external CLI results when appropriate
  • Use Promise.all() for parallel operations

Documentation Standards

When updating docs:

  • Keep README.md concise (high-level overview)
  • Put details in docs/ files
  • Use code examples for clarity
  • Include expected output
  • Add troubleshooting sections

Git Workflow

# Create feature branch
git checkout -b feature/my-feature

# Make changes, commit
git add .
git commit -m "feat: add new feature"

# Push and create PR
git push origin feature/my-feature

Commit Message Format:

  • feat: — New feature
  • fix: — Bug fix
  • docs: — Documentation
  • test: — Tests
  • refactor: — Code refactoring
  • chore: — Maintenance

Questions?

  • Check existing code for patterns
  • Read tests for examples
  • Ask in GitHub Discussions
  • Open an issue if stuck

Key Files Reference

  • Entry point: src/cli.ts
  • Sync logic: src/core/sync.ts
  • MCP management: src/core/mcp.ts, src/core/mcpCrud.ts
  • Renderers: src/core/renderers.ts
  • Project MCP (.mcp.json): src/core/projectMcp.ts
  • Agent Plugins: src/core/agentPlugin.ts
  • MCP client for budget: src/core/mcpProbe.ts
  • Types: src/types.ts
  • File I/O: src/core/fs.ts
  • Paths: src/core/paths.ts
  • UI helpers: src/core/ui.ts

Remember: The goal is to make multi-LLM development simple. Every feature should reduce friction, not add complexity.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.