agentleFS
fern-apifern-api/fern/CLAUDE.md

fern

CLAUDE.md3.8k starsChanged 11 months agoApache-2.0View on GitHub

This repository uses DevBox for reproducible development environments with exact version pinning. DevBox is based on Nix and provides cross-platform support (Mac, Linux, Windows via WSL). Quick Start with DevBox: DevBox automatically provides: Node.js 22, pnpm 9.4.0, Go 1.23, Python 3.10, Poetry 1.8, JDK 17, buf 1.50.0, and git-lfs. All versions are pinned in devbox.json to match CI. Manual .NET Installation (Required for C# generator development): DevBox cannot pin multiple .NET SDK versions simultaneously, so .NET must be installed separately.…

  • Pipes a download into a shell
  • Installs packages

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

31 rules. About 0 are common, 7 are distinctive, and 24 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈7

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 24

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Dependency Management: Run pnpm check:knip to check for unused dependencies (or pnpm depcheck which delegates to knip via turbo)

    line 82
  2. Distinctive:

    IR-Centric: All API definitions convert to canonical IR format for consistent generator behavior

    line 113
  3. Very specific:

    When users run fern generate --group <group-name> in production:

    line 122
  4. Very specific:

    IR Migration: If needed, migrates IR backward to match generator's expected version using /packages/cli/generation/ir-migrations

    line 131
  5. Distinctive:

    Run seed test to reproduce issue

    line 158
  6. Distinctive:

    When you need to change a generator default or behavior in a way that is not backwards compatible:

    line 169
  7. Very specific:

    API Schema: Update /fern/apis/<definition>/ → Run generator command (check generators.yml in each API folder)

    line 190
  8. Very specific:

    Add an entry to packages/ir-sdk/fern/apis/ir-types-latest/changelog/CHANGELOG.md (hand-edited.

    line 194
  9. Very specific:

    Do not edit packages/cli/cli/versions.yml irVersion for minor/patch — that field tracks the IR major and only changes during major bumps

    line 195
  10. Very specific:

    CLI Versioning: Add a CLI changelog entry under packages/cli/cli/changes/unreleased/ (drives CLI semver only — see packages/cli/CLAUDE.md)

    line 197
  11. Very specific:

    IR Migrations: Only required for major IR bumps — add under /packages/cli/generation/ir-migrations/

    line 200
  12. Very specific:

    Testing: Always run pnpm test:ete for end-to-end validation after CLI changes

    line 229
  13. Distinctive:

    Monorepo: Use Turbo filters for focused builds/tests on specific packages

    line 230
  14. Very specific:

    Never use any: If the type is truly unknown, use unknown and narrow it with type guards.

    line 237
  15. Very specific:

    Never use @ts-ignore: If you must suppress an error, use @ts-expect-error with a comment explaining why, and only as a last resort.

    line 245
  16. Very specific:

    Never use loose types like object, {}, or Function: Use specific object shapes, Record<K, V>, or typed function signatures like () => …

    line 247
  17. Very specific:

    Never use .then() chains when async/await is available: Prefer linear async code over nested callbacks or promise chains.

    line 284
  18. Very specific:

    Never throw strings or plain objects: Always throw Error instances (or subclasses) to preserve stack traces.

    line 294
  19. Very specific:

    Never mutate function parameters: Create new objects/arrays instead.

    line 300
  20. Very specific:

    Prefer const over let: Only use let when reassignment is actually necessary.

    line 302
  21. Very specific:

    Never use require() in TypeScript: Use ES module import syntax.

    line 310
  22. Very specific:

    Validation: Run pnpm compile to check for issues.

    line 328
  23. Very specific:

    New fixtures: Create /seed/<generator>/<fixture>/ directory → Add seed.yml config → Run pnpm seed:build → Run pnpm test:update and pnpm …

    line 334
  24. Distinctive:

    When creating pull requests in this repository:

    line 340
  25. Very specific:

    PR Title: Must follow semantic commit message rules enforced by CI (.github/workflows/lint-pr-title.yml).

    line 342
  26. Distinctive:

    Assignee: Always assign the person who prompted you to create the PR as the assignee

    line 350
  27. Very specific:

    Description: Follow the PR template in .github/pull_request_template.md

    line 351
  28. Distinctive:

    Testing: Ensure all tests pass before marking PR as ready for review

    line 352
  29. Very specific:

    After writing the ADR, number it by finding the highest existing docs/adr/NNNN-*.md and incrementing by one.

    line 392
  30. Very specific:

    Generator failures: Check docker ps → Rebuild image → Check container logs

    line 399
  31. Very specific:

    Performance: Use Turbo filters | pnpm clean then rebuild | Check Docker limits

    line 402

≈ “Common” is an estimate: at least 1 in 5 of the 25,680 CLAUDE.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
CLAUDE.md

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Development Environment Setup

This repository uses DevBox for reproducible development environments with exact version pinning. DevBox is based on Nix and provides cross-platform support (Mac, Linux, Windows via WSL).

Quick Start with DevBox:

# Install DevBox (if not already installed)
curl -fsSL https://get.jetify.com/devbox | bash

# Enter the development environment (installs all dependencies automatically)
devbox shell

DevBox automatically provides: Node.js 22, pnpm 9.4.0, Go 1.23, Python 3.10, Poetry 1.8, JDK 17, buf 1.50.0, and git-lfs. All versions are pinned in devbox.json to match CI.

Manual .NET Installation (Required for C# generator development):

DevBox cannot pin multiple .NET SDK versions simultaneously, so .NET must be installed separately. The C# generators require:

  • .NET 10 (latest)
  • .NET 9 (test TFM)

We provide a setup script that helps:

bash scripts/setup-dotnet.sh

This script checks for required .NET versions and can automatically install them using official Microsoft installation scripts, or provide links to the official guides. When you run devbox shell, the setup script runs automatically and the .NET installation is added to your PATH.

Alternatively, follow Microsoft .NET Installation Guide for your platform (macOS, Linux, Windows) and install to $HOME/.dotnet.

Available DevBox Scripts:

devbox run install                # Run pnpm install
devbox run compile                # Compile all packages
devbox run test                   # Run tests
devbox run lint                   # Run linting

Development Commands

Package Manager: This project uses pnpm (version 9.4.0+) exclusively. Node.js 18+ required.

Important: Commands from the root package.json can be run directly with pnpm <command>. However, when running commands defined in subfolder package.json files, always use pnpm turbo run <command> so that Turbo can execute dependent tasks first (e.g., compilation before testing).

Common Commands (from root):

# Initial setup
pnpm install                    # Install dependencies

# Building
pnpm compile                     # Compile all packages (production build)
pnpm compile:debug               # Compile with debug info
pnpm clean                       # Clean all build outputs

# Testing
pnpm test                        # Run all tests (excludes end-to-end tests)
pnpm test:debug                  # Run tests with debug info
pnpm test:update                 # Update test snapshots
pnpm test:ete                    # Run end-to-end tests (slower, requires CLI build)

# Linting & Formatting
pnpm lint:eslint                 # Run ESLint
pnpm lint:eslint:fix            # Fix ESLint issues
pnpm format                     # Check formatting with Biome
pnpm format:fix                 # Fix formatting issues

# Fern CLI (for testing)
pnpm fern:build                 # Build production CLI
pnpm fern:local                 # Run local development CLI
pnpm fern                       # Run local CLI directly

# Seed (generator testing)
pnpm seed:build                 # Build seed CLI for generator testing

Running Individual Package Commands: For commands in subfolder packages, use pnpm turbo run <command> --filter @fern-api/cli (e.g., pnpm turbo run test --filter @fern-api/cli)

Dependency Management: Run pnpm check:knip to check for unused dependencies (or pnpm depcheck which delegates to knip via turbo)

Architecture Overview

Fern is a CLI tool for API-first development that transforms API definitions into SDKs and documentation. The architecture has three main layers:

1. CLI Layer (/packages/cli/)

  • Entry Point: packages/cli/cli/src/cli.ts - Main yargs-based CLI
  • Key Components:
    • Configuration management (fern.config.json, generators.yml)
    • Project/workspace loading and validation
    • Command orchestration (generate, check, init, mock, etc.)
    • Logging and error handling infrastructure

2. Core Processing (/packages/)

  • Workspace Management: Loads and validates API workspaces from multiple formats
  • IR (Intermediate Representation): Central data structure (/ir-sdk/) consumed by all generators
  • Import/Export: Converts external formats (OpenAPI, AsyncAPI, gRPC) to Fern IR
  • Utilities: Core libraries for file system, logging, path handling, etc.

3. Generator Layer (/generators/)

Language-specific generators that consume IR and produce outputs:

  • Pattern: Each language has base/, ast/, model/, sdk/, sometimes server/
  • Supported: TypeScript, Python, Java, Go, C#, Ruby, PHP, Rust, Swift
  • Special: OpenAPI export

4. Testing (/seed/)

Comprehensive generator testing with Docker-based fixtures across all supported languages.

Key Architectural Patterns

  1. IR-Centric: All API definitions convert to canonical IR format for consistent generator behavior
  2. Plugin Architecture: Generators are Docker-containerized plugins implementing AbstractGeneratorCli
  3. Workspace-Based: Projects support multiple API workspaces with different configurations
  4. Turbo Monorepo: Uses pnpm workspaces + Turbo for builds and caching

Core Workflows

Production SDK Generation Flow

When users run fern generate --group <group-name> in production:

  1. CLI Version Check: Fern CLI checks fern.config.json for required version and auto-downloads/installs if needed
  2. Configuration Discovery: CLI locates generators.yml file(s) in the fern directory structure:
    • Single API: fern/generators.yml
    • Multiple APIs: fern/apis/<api-name>/generators.yml (separate configs per API)
  3. Generator Selection: Uses --group parameter or default-group field to determine which generator group to run
  4. IR Generation: Creates Fern IR file containing all information needed for generation (always latest IR version)
  5. Version Compatibility: Checks generator version (e.g., typescript-node-sdk:2.6.3) against required IR version (e.g., irVersion: 58) using /generators/<lang>/sdk/versions.yml
  6. IR Migration: If needed, migrates IR backward to match generator's expected version using /packages/cli/generation/ir-migrations
  7. Generation Execution:
    • Local: --local flag downloads Docker image and runs generation locally
    • Remote: Uses Fiddle service for server-side generation (being deprecated)
  8. Output Delivery: Based on generators.yml output configuration:
    • Package registries: npm, PyPI, Maven, NuGet, RubyGems
    • GitHub: release/pull-request/push modes
    • Local filesystem: saves to specified directory

Seed Testing (Development)

Seed validates generator changes against test fixtures. Essential for bug fixes and feature development.

Structure: /test-definitions/ (inputs) → /packages/seed/ (CLI) → /seed/<generator>/<fixture>/ (outputs)

Setup: pnpm install && pnpm compile && pnpm seed:build

Commands:

# Test predefined fixture
pnpm seed test --generator python-sdk --fixture file-download --skip-scripts

# Test custom project
pnpm seed run --generator go-sdk --path /path/to/project --skip-scripts

Development Cycle:

  1. Run seed test to reproduce issue
  2. Modify generator code
  3. Re-run seed test (use git diff to see output changes)
  4. Repeat until fixed

Output: Seed test overwrites /seed/<generator>/<fixture>/, seed run writes to temp directory

Breaking Changes Policy (Generators)

Generators MUST NOT ship breaking changes to existing users without a migration path. Autorelease cannot succeed if a generator silently changes default behavior, and on-call will page.

When you need to change a generator default or behavior in a way that is not backwards compatible:

  1. Gate the new behavior behind a config flag and keep the old behavior as the default. Users opt in to the new behavior by setting the flag.
  2. When you are ready to flip the default (major version bump of the generator), add a generator migration under packages/generator-migrations/src/generators/<generator>/migrations/<next-major>.0.0.ts. The migration must set the old value for users who had not explicitly configured the field, so their existing generators.yml continues to produce the same output.
  3. Register the migration in the generator's migrations/index.ts and publish @fern-api/generator-migrations. Migrations run automatically via fern generator upgrade --include-major.

See packages/generator-migrations/src/generators/typescript/migrations/3.0.0.ts for a reference example (switching TypeScript SDK defaults from yarn/jest to pnpm/vitest). See packages/generator-migrations/README.md for the full authoring guide.

Checklist for any generator-defaults PR:

  • Is the new behavior gated so existing users are unaffected until they opt in or a major version lands?
  • If this is the major version flip, is there a corresponding migration file under packages/generator-migrations/?
  • Is the migration registered in src/generators/<generator>/migrations/index.ts?
  • Are there tests for the migration (see packages/generator-migrations/src/__test__/)?

Skipping this process breaks autorelease for every customer pinned to the old major and will cause an on-call incident.

Feature Addition Workflow (Generated Code)

Multi-stage process: API Schema → IR Updates → Generator Updates → Release

Stages:

  1. API Schema: Update /fern/apis/<definition>/ → Run generator command (check generators.yml in each API folder)
  2. IR Updates: Modify /packages/ir-sdk/fern/apis/ir-types-latest/definition/ → pnpm ir:generate
  3. IR Versioning (REQUIRED for any change to ir-types-latest):
    • Bump packages/ir-sdk/fern/apis/ir-types-latest/VERSION (minor for additive/optional fields, patch for non-schema, major only as a separate batched PR)
    • Add an entry to packages/ir-sdk/fern/apis/ir-types-latest/changelog/CHANGELOG.md (hand-edited; no changes/unreleased/ for IR)
    • Do not edit packages/cli/cli/versions.yml irVersion for minor/patch — that field tracks the IR major and only changes during major bumps
    • See packages/ir-sdk/CLAUDE.md for the full checklist
  4. CLI Versioning: Add a CLI changelog entry under packages/cli/cli/changes/unreleased/ (drives CLI semver only — see packages/cli/CLAUDE.md)
  5. Compile: pnpm compile and fix breaking changes (common: switch statements need new cases)
  6. Generator Updates: One PR for CLI/IR updates (merge first), then separate PR(s) for generator changes
  7. IR Migrations: Only required for major IR bumps — add under /packages/cli/generation/ir-migrations/

Key Points: Multiple PRs required, automatic publishing via versions.yml, generators use published (not workspace) IR versions. Forgetting to bump ir-types-latest/VERSION means no new @fern-fern/ir-sdk is published and the new field is invisible to downstream consumers.

Other Core Workflows

  1. Documentation: Markdown processing + API references → Static site
  2. Validation: Schema validation + reference checking + example verification

Important Files & Locations

  • CLI Entry: packages/cli/cli/src/cli.ts
  • IR Schema: packages/ir-sdk/ (central data structure)
  • Generator Base: generators/base/ (shared generator infrastructure)
  • Workspace Loading: packages/cli/workspace/loader/
  • Configuration: packages/cli/configuration/
  • Build Config: turbo.json, pnpm-workspace.yaml

Development Notes

  • Generator Development: Implement AbstractGeneratorCli, use IR as input, follow existing language patterns
  • Generator-Specific Documentation: Each major generator has its own CLAUDE.md file:
    • generators/python/CLAUDE.md - Python v1+v2 tandem system
    • generators/java/CLAUDE.md - Java v1+v2 tandem system
    • generators/go/CLAUDE.md - Go v1+v2 tandem system
    • generators/typescript/CLAUDE.md - Legacy TypeScript generator
    • generators/ruby-v2/CLAUDE.md - Modern Ruby generator (standalone)
    • generators/csharp/CLAUDE.md - Modern C# generator
  • IR Changes: Require migrations in packages/generation/ir-migrations/
  • Testing: Always run pnpm test:ete for end-to-end validation after CLI changes
  • Monorepo: Use Turbo filters for focused builds/tests on specific packages
  • Docker: Generators run in Docker containers for isolation and consistency

TypeScript Rules

Typing

Never use any. If the type is truly unknown, use unknown and narrow it with type guards. If you're tempted to use any, stop and find the correct type or create one.

Never use as X for type assertions unless you have information the compiler cannot infer. Valid uses are rare—typically only when working with DOM APIs, test mocks, or deserializing JSON where you've validated the shape. If you need to assert, prefer satisfies for validation without widening.

Never use as any or as unknown as X. These are escape hatches that bypass the type system entirely. If the types don't line up, fix the types.

Never use non-null assertions (!) unless you can prove the value is defined and the compiler simply cannot see it. Prefer optional chaining (?.), nullish coalescing (??), or explicit null checks.

Never use @ts-ignore. If you must suppress an error, use @ts-expect-error with a comment explaining why, and only as a last resort.

Never use loose types like object, {}, or Function. Use specific object shapes, Record<K, V>, or typed function signatures like () => void.

Always provide explicit return types for exported functions and public methods. This serves as documentation and catches accidental return type changes.

Prefer named type guard functions over inline in checks. Instead of scattering "prop" in obj && obj.prop === value throughout business logic, extract these into well-named type guard functions (e.g., isInlineSchema(s), schemaAllowsNull(s)). This keeps call sites readable and centralizes the narrowing logic. Use TypeScript's x is T return type for type guards that narrow.

Prefer type guards and discriminated unions over type assertions for narrowing. Write custom type guards rather than asserting.

Prefer unknown over any in generic constraints when the type truly varies. Use <T> or <T extends SomeBase> rather than accepting any.

When working with external data (API responses, JSON parsing), validate and narrow with type guards—never assert the shape blindly.

Exhaustive Checks

Always handle all cases when switching on discriminated unions. Every switch statement on a discriminated union's type field must include a case for every variant. The default case must call assertNever from @fern-api/core-utils to ensure compile-time exhaustiveness—if a new variant is added to the union, any unhandled switch will fail to compile.

import { assertNever } from "@fern-api/core-utils";

switch (shape.type) {
    case "circle":
        return handleCircle(shape);
    case "square":
        return handleSquare(shape);
    default:
        assertNever(shape);
}

Never leave a default case that silently ignores unknown variants. The whole point of assertNever is to turn missed cases into compile-time errors rather than silent runtime bugs. If you find yourself wanting to skip a variant, handle it explicitly (even if the handler is a no-op with a comment explaining why).

This applies to all discriminated union patterns in the codebase, including IR types, generator configuration unions, OpenAPI schema variants, and any other tagged union. Use assertNeverNoThrow from @fern-api/core-utils only when you intentionally want to ignore unexpected variants without throwing (e.g., forward-compatible parsing), and add a comment explaining why.

Here are additional TypeScript rules beyond type safety:

Async/Await & Promises

Never use .then() chains when async/await is available. Prefer linear async code over nested callbacks or promise chains.

Never forget to await a Promise. Unhandled promises silently fail. If you intentionally don't await, assign to void and add a comment explaining why.

Never use async on a function that doesn't await anything. It adds unnecessary overhead and obscures intent.

Error Handling

Never swallow errors with empty catch blocks. At minimum, log the error. If you truly want to ignore it, add a comment explaining why.

Never throw strings or plain objects. Always throw Error instances (or subclasses) to preserve stack traces.

Prefer early returns over deeply nested conditionals. Guard clauses make code easier to follow.

Immutability & Mutation

Never mutate function parameters. Create new objects/arrays instead. Use spread, map, filter, not push, splice, or direct assignment.

Prefer const over let. Only use let when reassignment is actually necessary.

Never use var.

Imports & Modules

Never use default exports. Named exports are easier to refactor, auto-import, and grep for.

Never use require() in TypeScript. Use ES module import syntax.

Keep imports organized. External dependencies first, then internal modules, then relative imports.

Naming & Structure

Never use abbreviations in variable names unless universally understood (e.g., id, url). Write response, not res. Write error, not err.

Never use I prefix for interfaces. Just name the thing what it is.

Prefer pure functions where possible. Functions that depend only on their inputs are easier to test and reason about.

Generated Code Management

Identifying: Generated by Fern (not third-party tools). Common locations: /sdk/src/serialization/, /sdk/src/api/, /seed/ test fixtures.

Regenerating: pnpm fern generate [--group <name>] or pnpm fern:local generate for local testing

Validation: Run pnpm compile to check for issues. Test individual fixtures during development. Run full validation (pnpm check:fix, pnpm test, pnpm test:ete) only when changes are complete.

Seed Testing & Fixtures

Adding/Updating Fixtures

New fixtures: Create /seed/<generator>/<fixture>/ directory → Add seed.yml config → Run pnpm seed:build → Run pnpm test:update and pnpm test:ete:update → Validate → Commit

Update fixtures: pnpm seed:build --filter <fixture-name> or pnpm test:update for snapshots

Pull Request Guidelines

When creating pull requests in this repository:

  1. PR Title: Must follow semantic commit message rules enforced by CI (.github/workflows/lint-pr-title.yml). Format: <type>(<scope>): <description>. Both type and scope are required.

    Allowed types: fix, feat, revert, break, chore

    Allowed scopes: docs, changelog, internal, cli, typescript, python, java, csharp, go, php, ruby, seed, ci, lint, openapi, deps, deps-dev, pydantic, ai-search, swift, rust, generator-cli, parser, ir, cli-v2, cli-generator

    Examples: chore(docs): update guidelines, feat(python): add new feature, fix(cli): resolve config loading bug

  2. Assignee: Always assign the person who prompted you to create the PR as the assignee
  3. Description: Follow the PR template in .github/pull_request_template.md
  4. Testing: Ensure all tests pass before marking PR as ready for review

Architecture Decision Records (ADRs)

ADRs live in docs/adr/ and are numbered sequentially (0001-, 0002-, …).

Create an ADR when a change is cross-cutting — i.e., it affects how multiple components of the repo work together or sets a convention that all contributors must follow:

  • A new repo-wide system or workflow (release pipelines, CI frameworks, build tooling)
  • A design decision that governs the IR or the contract between the CLI and generators broadly
  • A new architectural pattern or abstraction adopted across several packages
  • A policy change that constrains how all (or many) generators/packages must behave

Do NOT create an ADR for:

  • Changes scoped to a single generator or package, even significant ones (new features, output format changes, config additions)
  • Bug fixes at any level
  • Dependency version bumps
  • Refactors that don't change observable behavior
  • IR additions that are additive and don't change existing generator contracts

ADR format

# ADR NNNN: <Title>

## Status
Accepted — merged #<PR> on <date>.

## Context
Why this change was needed and what constraints shaped the design.

## Decision
What was decided and the key implementation details.

## Alternatives Considered
Other approaches evaluated and why they were rejected.

## Consequences
Trade-offs, limitations, and follow-on implications.

After writing the ADR, number it by finding the highest existing docs/adr/NNNN-*.md and incrementing by one.

Troubleshooting

For Sentry buildwithfern / cli false-positive triage, see the Devin skill at .devin/automation/sentry-triage/SKILL.md, plus .devin/automation/sentry-triage/DESIGN_CHOICES.md and the per-issue ledger files under .devin/automation/sentry-triage/ledger/.

Quick Fixes by Issue Type

  • Generator failures: Check docker ps → Rebuild image → Check container logs
  • IR compilation: pnpm fern check → Check circular refs → Review migrations
  • Test failures: Unit (check generated code) | E2E (pnpm fern:build) | Seed (pnpm seed:build) | Lint (pnpm format:fix)
  • Performance: Use Turbo filters | pnpm clean then rebuild | Check Docker limits

Debug Locations

  • Build outputs: dist/, .turbo/ directories
  • Test outputs: /seed/<generator>/<fixture>/ directories

Individual Preferences

@~/.claude/my-fern-instructions.md

Download now (ZIP)

Trending

More talk lately.about the whole repository

Dec 2025: 0 mentionsJan 2026: 1 mentionFeb 2026: 0 mentionsMar 2026: 2 mentionsApr 2026: 1 mentionMay 2026: 1 mentionJun 2026: 0 mentionsJul 2026: 0 mentionsAug 2026: 2 mentionsSep 2026: 0 mentionsOct 2026: 5 mentionsNov 2026: 0 mentions
Dec 2025Jun 2026Nov 2026
Mentions a month of the fern-api/fern repository that our weekly crawl found. There is no adoption data for this file yet.

Who's talking about fern-api/fern

The biggest 5 of 33 mentions linking to the repository that our crawl found. Each line is their own headline.

See all 33

Talked about on GitHub, Hacker News, Bluesky and Stack Overflow (33 times).

On GitHub · 26

21 more on GitHub

On Stack Overflow · 1

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.