agentleFS
lahfirlahfir/agent-desktop/AGENTS.md

agent-desktop

AGENTS.md19k starsChanged 15 days agoApache-2.0View on GitHub

Guidance for AI coding agents working in this repository. agent-desktop is a tool that AI agents invoke, not an agent. It is a Rust CLI and C library that reads native accessibility trees and returns structured JSON with ref-based element ids. The observe-act loop lives in the calling agent. It never embeds an LLM and has no GUI or interactive prompt. It does not automate web pages (use agent-browser). It cannot see UIs that expose no accessibility tree. Every fix…

1 other project uses a version of this; 1 new project in the last 4 weeks, against 0 the 4 before.

Adopted by

Surging: 1 new project took it in the last 4 weeks, none the 4 weeks before.thin data

Week of Sep 13: 0 new projectsWeek of Sep 20: 0 new projectsWeek of Sep 27: 0 new projectsWeek of Oct 4: 0 new projectsWeek of Oct 11: 0 new projectsWeek of Oct 18: 0 new projectsWeek of Oct 25: 1 new projectWeek of Nov 1: 0 new projects
Sep 2026Oct 2026Nov 2026
New projects taking a version of this file each week, over the 8 weeks our latest run read: only 1 in all, so this is a hint, not a trend.

Most recently taken up by

Who's talking about lahfir/agent-desktop

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

See all 38

Talked about on GitHub, Hacker News, Bluesky and YouTube (38 times).

On GitHub · 30

25 more on GitHub

On Bluesky · 3

On YouTube · 2

  • Other versions1 project uses a version of this.

    Word for word · 1

    1. vercel-labs/agent-desktop★ 19k100% same

    Edited · 0

    None found.

    Wrote their own version · 0

    None found.

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • 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 repository8 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

27 rules. About 0 are common, 10 are distinctive, and 17 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈10

    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:

    Every fix must work through the platform's shared accessibility and lifecycle contracts across applications.

    line 12
  2. Distinctive:

    Never add app-specific branches keyed by app names, bundle IDs, executables, window titles, or a known app's UI layout.

    line 13
  3. Distinctive:

    Use observed capabilities, roles, ownership, and process identity in the shared platform adapter.

    line 14
  4. Very specific:

    When a plan contradicts the code, the code says what shipped.

    line 68
  5. Distinctive:

    Write each deferral into the receiving phase of the local roadmap before the PR opens, with the evidence that forced it, and name it in the …

    line 79
  6. Very specific:

    Never add Co-Authored-By lines, AI attribution or "Generated with" footers.

    line 86
  7. Very specific:

    Use Conventional Commits: feat:, fix:, feat!: or a BREAKING CHANGE: footer, docs:, style:, refactor:, perf:, chore:, ci:, test:.

    line 87
  8. Very specific:

    Only two crates wire a platform to core: the binary (src/) and the FFI crate.

    line 114
  9. Very specific:

    Create crates/core/src/commands/<name>.rs with an execute() function, its tests in <name>_tests.rs, and register it in commands/mod.rs.

    line 136
  10. Very specific:

    Add the CLI variant in src/cli/mod.rs and its arguments under src/cli_args/.

    line 138
  11. Very specific:

    Add its arm to dispatch() and to policy_for() in src/command_policy/mod.rs.

    line 139
  12. Very specific:

    Add its name to parse_command() in src/batch/mod.rs.

    line 140
  13. Very specific:

    Update the command counts in README.md and in this file.

    line 142
  14. Very specific:

    Update the matching skill in the same change: skills/agent-desktop/ for cross-platform behavior, the platform skill for what differs, …

    line 145
  15. Distinctive:

    At most 7 fields per struct and 5 parameters per function: Use a config struct or a builder.

    line 187
  16. Very specific:

    Explicit pub boundaries: Only lib.rs re-exports. Internal modules are pub(crate).

    line 188
  17. Very specific:

    Every command prints one envelope.

    line 205
  18. Very specific:

    Every snapshot carries data.complete.

    line 222
  19. Very specific:

    Use recovery.strategy only when disposition.retry is safe.

    line 229
  20. Very specific:

    All state lives under one root, ~/.agent-desktop by default.

    line 245
  21. Very specific:

    Read attributes in batches with AXUIElementCopyMultipleAttributeValues, not one call per attribute.

    line 258
  22. Distinctive:

    Performance: Check every substantive change for latency against the merge-base before merge.

    line 280
  23. Distinctive:

    Dogfood: Every platform sub-phase drives its own surface against real software and keeps a judged report.

    line 291
  24. Distinctive:

    Run it as a stranger. The operator gets the shipped skill and the built binary, and nothing else: no source, no plan.

    line 292
  25. Distinctive:

    Run every example in the shipped docs verbatim in the platform's default shell.

    line 294
  26. Very specific:

    Read every step's ok. Wait with the tool's own wait primitives.

    line 298
  27. Distinctive:

    Every requirement in a plan maps to at least one test that fails when the requirement is violated.

    line 304

≈ “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

Guidance for AI coding agents working in this repository.

agent-desktop is a tool that AI agents invoke, not an agent. It is a Rust CLI and C library that reads native accessibility trees and returns structured JSON with ref-based element ids. The observe-act loop lives in the calling agent. It never embeds an LLM and has no GUI or interactive prompt. It does not automate web pages (use agent-browser). It cannot see UIs that expose no accessibility tree.

Critical: fixes must be application-agnostic

Every fix must work through the platform's shared accessibility and lifecycle contracts across applications. Never add app-specific branches keyed by app names, bundle IDs, executables, window titles, or a known app's UI layout. Use observed capabilities, roles, ownership, and process identity in the shared platform adapter. Preserve safe failure when the platform cannot establish the required identity or capability. Verify changed behavior against multiple real apps and relevant UI toolkits; one app passing does not establish platform-wide correctness. App-specific names belong in examples and verification scenarios, never in runtime special cases.

Commands

Each platform adapter compiles only on its own OS and the workspace names all three, so an unscoped cargo build, cargo test --workspace or cargo clippy --all-targets fails on every host. Scope cargo to the host's package set, the same set .githooks/pre-commit uses:

HOST_PKGS=(-p agent-desktop-core -p agent-desktop-macos -p agent-desktop -p agent-desktop-ffi)
# Windows: replace agent-desktop-macos with agent-desktop-windows. Linux: with agent-desktop-linux.
# An array expands to separate arguments in both bash and zsh; a plain string does not in zsh.

cargo build "${HOST_PKGS[@]}"                                  # debug build
cargo build --release -p agent-desktop                         # release CLI; CI fails it above 15 MB
cargo test "${HOST_PKGS[@]}"                                   # every test target
cargo test "${HOST_PKGS[@]}" --lib                             # library tests only; skips the binary crate
cargo test -p agent-desktop                                    # binary crate: CLI contract, dispatch, batch, policy
cargo test "${HOST_PKGS[@]}" <test_name>                       # one test by name
cargo clippy "${HOST_PKGS[@]}" --all-targets -- -D warnings    # zero warnings
cargo fmt --all -- --check
cargo check -p agent-desktop-core --all-targets --target x86_64-pc-windows-msvc   # core cross-compiles
cargo check -p agent-desktop-core --all-targets --target x86_64-unknown-linux-gnu
cargo tree -p agent-desktop-core                               # must name no platform crate
AGENT_DESKTOP_E2E_EXCLUSIVE=1 bash tests/e2e/run.sh            # macOS E2E; builds its own artifacts
bash scripts/perf-baseline-compare.sh                          # macOS perf A/B against the merge-base

scripts/cargo-test-isolated-home.sh test "${HOST_PKGS[@]}" --lib runs tests with a throwaway HOME, which keeps them out of your real ~/.agent-desktop. The pre-commit hook uses it.

Enable the hook once per clone with git config core.hooksPath .githooks. For staged Rust or TOML changes it runs the source-rule scripts (check-rust-file-size.sh, check-no-phase-references.sh, check-stale-ref-constructor-misuse.sh), fmt, clippy and library tests over the host set. FFI changes add the C ABI passthrough test and the cbindgen header check. Bypass it only in an emergency: git commit --no-verify or SKIP_PRECOMMIT=1 git commit ....

Where the truth lives

  • Shipped behavior is the code and its tests. A doc that contradicts the code is a defect; fix it in the same change.
  • Agent usage is the skills under skills/. They compile into the binary: agent-desktop skills get desktop and agent-desktop skills get platform.
  • Vocabulary is CONCEPTS.md. The JSON contract is docs/json-output.md. Past lessons are in docs/solutions/, with YAML frontmatter (module, tags, problem_type); search it before you work in a documented area.
  • User docs live in apps/docs and are served at agent-browser.dev/desktop. Use the technical-writer skill (.agents/skills/technical-writer/SKILL.md) when you write or edit prose: docs pages, READMEs, skills, changelog entries, commit messages, PR descriptions, and issues. The docs serve developers and the agents that call agent-desktop, so keep them complete, short, and checked against the code.
  • Planning documents (the phase roadmap phases.md, sub-phase plans, brainstorms) live in .compound-engineering/ at the repo root. That folder is untracked on purpose. Read it when you plan. Never link to it or cite it from a committed file, because it does not exist in any other checkout.
  • When a plan contradicts the code, the code says what shipped. Correct the plan in place, with no "previously said" note, and cite what disproved it: a probes/**/FINDINGS.md row id or the source line.

Build it; do not defer it

  • The implementer makes the work land. "Harder than expected", "the PR is already large" and "a later phase touches this" are not reasons to defer.
  • Defer only when the work is blocked: impossible on the platform, dependent on infrastructure that does not exist, or possible only by breaking a stated invariant or safety property. Name which one.
  • Measure before you defer. Settle an unknown with a probe; a deferral that rests on an assumption is a guess.
  • Reducing scope is the owner's call. If the work cannot land, say so and stop. Never narrow it quietly.
  • Write each deferral into the receiving phase of the local roadmap before the PR opens, with the evidence that forced it, and name it in the PR description. If it changes what the current phase delivers, correct that phase too.

Branches and commits

  • main carries macOS, Windows and Linux. Fixes and features branch off main and merge back as squash merges; main requires linear history.
  • Never add Co-Authored-By lines, AI attribution or "Generated with" footers.
  • Use Conventional Commits: feat:, fix:, feat!: or a BREAKING CHANGE: footer, docs:, style:, refactor:, perf:, chore:, ci:, test:. Write type: imperative summary in lowercase after the colon, and say why.
  • Versions follow semver from 1.0.0. A release is one PR that bumps the workspace version in Cargo.toml, Cargo.lock, npm/package.json and CHANGELOG.md. Merging it starts .github/workflows/release.yml, which publishes npm and the GitHub release; docs/releasing.md has the steps.

Architecture

crates/core/     agent-desktop-core: PlatformAdapter trait in adapter/, shared types in domain folders,
                 one file per command in commands/
crates/macos/    agent-desktop-macos: AX API
crates/windows/  agent-desktop-windows: UI Automation
crates/linux/    agent-desktop-linux: AT-SPI
crates/ffi/      agent-desktop-ffi: cdylib and the committed C header include/agent_desktop.h
src/             agent-desktop binary: cli/, cli_args/, dispatch/, batch/, command_policy/,
                 diagnostic/, visual_debug/, mcp/
skills/          agent skills, compiled into the binary
tests/           golden fixtures, E2E harness per OS, FFI smoke tests
probes/          raw platform measurements; FINDINGS.md rows are citable evidence
apps/docs/       Geistdocs site served at agent-browser.dev/desktop as a Vercel Microfrontends child app

Dependency inversion (non-negotiable).

  • Core defines PlatformAdapter and every shared type. Platform crates implement the trait.
  • Core never imports a platform crate, and platform crates never import each other. CI fails if cargo tree -p agent-desktop-core names a platform crate.
  • Only two crates wire a platform to core: the binary (src/) and the FFI crate.
  • The platform is chosen at compile time by #[cfg(target_os)] in build_adapter() (src/main.rs, crates/ffi/src/adapter.rs) with target-gated dependencies in src/Cargo.toml ([target.'cfg(target_os = "macos")'.dependencies]), never unconditional dependencies behind source cfgs.
  • PlatformAdapter is split across crates/core/src/adapter/ (mod.rs plus the actions, input, observation and system fragments). Every method defaults to AdapterError::not_supported, so an adapter implements only what it supports. Strict resolution (resolve_element_strict*) returns STALE_REF for zero matches and AMBIGUOUS_TARGET for two or more.
  • Core must run on every OS. A #[cfg] branch in core that no CI lane executes is a hypothesis, not shipped code: add a lane or move it behind PlatformAdapter.

Dispatch. dispatch() in src/dispatch/mod.rs is a direct match that calls each command's execute() in crates/core/src/commands/. There is no command trait or registry. Batch is not a second dispatcher: it deserializes JSON entries into the same Commands enum, runs the same CommandPolicy preflight and calls the same dispatch().

MCP. agent-desktop mcp (src/mcp/) is not a second command surface. It reads the clap command tree at runtime: each leaf command is one tool, its schema comes from the command's clap arguments and help, and a call rebuilds the argv and runs this binary as a child process. A command added to or removed from Commands appears in or disappears from the MCP tool list with no MCP change. mcp itself is attached to the root command in main.rs, outside Commands, so it is never a tool, a batch entry or a counted command.

Adding a command.

  1. Create crates/core/src/commands/<name>.rs with an execute() function, its tests in <name>_tests.rs, and register it in commands/mod.rs.
  2. Add the CLI variant in src/cli/mod.rs and its arguments under src/cli_args/.
  3. Add its arm to dispatch() and to policy_for() in src/command_policy/mod.rs. Both matches are exhaustive.
  4. Add its name to parse_command() in src/batch/mod.rs; every_cli_subcommand_is_known_to_batch_parser fails otherwise. Add it to the surface lists in src/cli/contract_command_surface_tests.rs.
  5. Update the command counts in README.md and in this file; src/cli/doc_literal_drift_tests.rs checks them.
  6. A new Action variant goes in crates/core/src/actions/action.rs. A new adapter method goes in the matching PlatformAdapter fragment with a not_supported default.
  7. Update the matching skill in the same change: skills/agent-desktop/ for cross-platform behavior, the platform skill for what differs, skills/agent-desktop-ffi/ for the C ABI. The skills compile into the binary and are what agents read.

Crate layout. Core's root holds only lib.rs and domain folders named after CONCEPTS.md words: actionability, actions, adapter, commands, context, cursor_overlay, input, locator, notifications, ref_action, refs, response, session, snapshot, storage, system, trace, tree and wait.

  • A platform crate's root holds lib.rs, adapter.rs (the trait impl) and five layer folders, plus bin/ where a helper binary exists. tree/ reads, traverses and resolves the UI; actions/ acts on elements; input/ synthesizes raw keyboard, mouse and clipboard input; system/ handles app lifecycle, windows, permissions and screenshots; notifications/ handles the OS notification surface.
  • Inside a layer, a concept with four or more source files gets a subfolder named from the shared vocabulary (resolve, walk, properties, select, scroll, clipboard, keyboard, mouse, window, capture, ...). File names keep their prefix (system/window/window_ops.rs). A file named like its folder becomes its mod.rs.
  • Tests sit beside their code as foo_tests.rs, declared from foo.rs with #[cfg(test)] #[path = "foo_tests.rs"] mod tests;.
  • Capability impls live in adapter.rs or in the matching layer's adapter.rs.

Grounding rule. scripts/check-architecture.sh (rules in scripts/check_architecture.py) runs in the pre-commit hook and in CI next to the source rules. Before it scans, it plants a violation of every rule, so a rule that stops detecting fails the gate. It fails when core depends on a platform or OS crate, a platform crate reaches another, core gains OS-conditional code outside its allow-list, a crate's top-level layout drifts, a capability is implemented in the wrong layer, core domains reach commands/, or a test file is not declared beside its code. Its lists (core dependencies, core domains, binary folders, OS allow-list) change only in review. The CI cargo tree isolation steps remain the transitive check.

Coding standards

  • 400 lines at most per hand-written .rs file (scripts/check-rust-file-size.sh). Split by responsibility. A generated .rs file with an @generated marker in its first five lines is exempt, and the fix goes in the generator, not the output. Probe .ps1 scripts are exempt. The C header is generated by cbindgen and checked by CI for drift: change the Rust ABI or crates/ffi/cbindgen.toml and regenerate it with scripts/update-ffi-header.sh, never edit it by hand.
  • No inline comments. Names carry the meaning. Standalone // lines, end-of-line // comments and non-doc /* */ blocks are all rejected. The allowed forms are /// on public items, only when the name is not enough, and //! module docs. scripts/check-rust-file-size.sh enforces this together with the size cap, through scripts/check_rust_comments.py.
  • No delivery-plan references in crates/** or src/**: no phase, sub-phase, plan decision id (KTD<n>) or plan unit id (U<n>). Write what is true about the code and why. Probe ledger row ids such as A15-7 are allowed and encouraged. scripts/check-no-phase-references.sh enforces this.
  • One domain struct or enum per file (node.rs holds AccessibilityNode). One command per file, named after the command.
  • At most 7 fields per struct and 5 parameters per function. Use a config struct or a builder.
  • Explicit pub boundaries. Only lib.rs re-exports. Internal modules are pub(crate). No wildcard re-exports.
  • Naming. Crates are agent-desktop-<name>; module files are singular snake_case; types are PascalCase; functions are verb-first snake_case; constants are SCREAMING_SNAKE_CASE; CLI flags are kebab-case.

Errors.

  • No unwrap(), expect() or panic! outside tests; panics are test-only. Propagate with ? or match.
  • Adapter functions return Result<T, AdapterError>. Command handlers return Result<serde_json::Value, AppError>. main() turns an AppError into the JSON envelope and the exit code.
  • An error carries code (ErrorCode), message, and optional suggestion, platform_detail and details, plus its delivery disposition.
  • Codes: PERM_DENIED, ELEMENT_NOT_FOUND, APP_NOT_FOUND, ACTION_FAILED, ACTION_NOT_SUPPORTED, STALE_REF, AMBIGUOUS_TARGET, WINDOW_NOT_FOUND, PLATFORM_NOT_SUPPORTED, TIMEOUT, INVALID_ARGS, NOTIFICATION_NOT_FOUND, SNAPSHOT_NOT_FOUND, POLICY_DENIED, APP_UNRESPONSIVE, INTERNAL.
  • Exit codes: 0 success, 1 structured error, 2 argument or parse error.

Output contract

Every command prints one envelope. docs/json-output.md holds the full contract.

{ "version": "2.6", "ok": true, "command": "snapshot",
  "data": { "app": "Finder", "snapshot_id": "s8f3k2p9", "ref_count": 14, "complete": true, "tree": { } } }
{ "version": "2.6", "ok": false, "command": "click",
  "error": { "code": "STALE_REF", "message": "...", "suggestion": "...",
             "recovery": { "strategy": "refresh_snapshot_then_retry_original", "retryable": true,
                           "requires_fresh_snapshot": true },
             "disposition": { "delivery": "not_delivered", "retry": "safe" } } }
  • Omit None fields and empty arrays. Compact mode omits bounds. ref_count and tree live inside data.
  • Snapshot data.window is present for window-owned surfaces. macOS menu and menubar snapshots are application-owned and omit it.
  • Every snapshot carries data.complete. A snapshot that runs out of observation budget succeeds with "complete": false, "truncated": true, "nodes_observed" and the tree it saw; each cut node carries "subtree_truncated": true. A --root drill-down returns TIMEOUT instead of a partial tree.
  • Pointer, drag, clipboard, close-app and window commands return the adapter's OperationReport as data. delivered_verified needs a postcondition read, delivered_unverified means a completed dispatch without one, and not_delivered is only for an operation already observed as satisfied. Core never adds an unconditional success flag such as clicked.
  • Use recovery.strategy only when disposition.retry is safe.

Refs and state

CONCEPTS.md defines refs, snapshots, sessions, cursors and traces. These rules are the ones code most often breaks:

  • Refs are snapshot-qualified (@s8f3k2p9:e1) and allocated depth-first. Only the qualified form is accepted as input; a bare @e1 fails with INVALID_ARGS. @eN is the internal RefMap key only.
  • An element gets a ref when its role is interactive (INTERACTIVE_ROLES in crates/core/src/tree/roles.rs) or it advertises a primary action. SetFocus, RightClick and ScrollTo alone do not qualify, because web runtimes advertise them on nearly every node.
  • Actions re-identify the element one of two ways. A genuine element token resolves through the adapter, which owns re-identification on that platform (macOS). Every other ref resolves from its capture proof: role plus every recorded stable field, that is native id, stable name and description, counted over one complete observation of the window it was captured from. A ref that was not unique at capture is refused before the application is read. Zero live matches is STALE_REF, two or more is AMBIGUOUS_TARGET, and control values and bounds are never identity.
  • All state lives under one root, ~/.agent-desktop by default. AGENT_DESKTOP_HOME relocates it (crates/core/src/storage/state_root.rs). Refmaps live at snapshots/<snapshot_id>/refmap.json, capped at 1 MB each; the store keeps the newest 128 snapshots per namespace and prunes to 96. Command code goes through RefStore, which only reads the legacy last_refmap.json to migrate it.
  • A session is selected by --session, then AGENT_DESKTOP_SESSION, then none. session start does not activate a session for later processes; pass its id. Snapshot lookup never searches another session's namespace.

macOS adapter gotchas

  • macOS reuses AXUIElementRef pointers across sibling branches. Guard traversal with an ancestor-path set, never a global visited set, or real subtrees disappear.
  • AXElement keeps its pointer pub(crate) to prevent a double free. Clone must CFRetain and Drop must CFRelease.
  • Read attributes in batches with AXUIElementCopyMultipleAttributeValues, not one call per attribute.

Testing and CI

  • Unit tests use small purpose-built adapter stubs (see crates/core/src/adapter/test_support.rs). Golden JSON in tests/fixtures/ guards serialization.
  • The E2E harnesses (tests/e2e/, tests/e2e-windows/, tests/e2e-linux/) drive the built binary against real apps. They check every effect by independent observation, never by the command's own ok: true. The macOS harness covers every ref action in headless and --headed mode.
  • CI runs fmt, the MSRV build, the core cross-compile checks, clippy and tests per OS, the core isolation check, a 15 MB binary size check and the FFI header and panic guards.

Command surface

60 commands spanning App/Window, Observation, Interaction, Scroll, Keyboard, Mouse, Notifications, Clipboard, Wait, System (including session, trace, skills) and Batch. 56 of the 60 command names are operational on macOS; the four held-input names (key-down, key-up, mouse-down, mouse-up) fail closed. Windows and Linux expose the same command names. Each platform's limits are in its skill (skills/agent-desktop-macos/, skills/agent-desktop-windows/, skills/agent-desktop-linux/).

Definition of done

Performance. Check every substantive change for latency against the merge-base before merge. A latency change must be intended and explained, never found by users.

  • macOS: bash scripts/perf-baseline-compare.sh writes report.html. Add --apps "Slack,Google Chrome" for dense Electron and Chromium coverage.
  • Windows: that script cannot run there. Use the probe cost method instead: min of seven runs with the warm-up discarded, reported as the min with the median and max beside it (probes/windows/FINDINGS.md A15-13, A18-7).
  • Linux: there is no baseline comparison. Hold these budgets: release CLI at most 15 MiB; every command under a silent display, a silent bus or a stopped app returns its documented code within its timeout plus 1 s; a snapshot of a real app is complete: true or cleanly truncated; FFI threads, descriptors and memory stay flat across repeated calls; the glibc floor stays at 2.35 or lower (scripts/check-elf-glibc-floor.sh).

Dogfood. Every platform sub-phase drives its own surface against real software and keeps a judged report.

  • Run it as a stranger. The operator gets the shipped skill and the built binary, and nothing else: no source, no plan. A subagent that does it is told so and denied the repo.
  • Run every example in the shipped docs verbatim in the platform's default shell. An example that cannot run as written is a defect of the same weight as a broken command.
  • Reaching for a flag, variable or ordering the skill does not document ends the run as a finding.
  • A report with no findings is a failed dogfood, not a passed one.
  • Read every step's ok. Wait with the tool's own wait primitives; a fixed sleep and then a check is a race. Confirm a failure twice before you report it. Measure a behavioral claim in both directions before you write it down.
  • Give every finding exactly one disposition: fixed here, with a named test that you invert-verify (break the fix, watch the test fail, restore); owned elsewhere, written into the receiving phase of the local roadmap; or accepted, with a reason. "Recorded" is not a disposition.
  • Reports and their evidence stay out of version control.
  • Every requirement in a plan maps to at least one test that fails when the requirement is violated.

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.