agentleFS
frankieramirezfrankieramirez/ripen/docs/agents.md

ripen

AGENTS.md0 starsChanged 55 days agoMITView on GitHub

Ripen's machine-facing interface is the CLI and one MCP server. They are the same surface: every MCP tool maps to a CLI verb with the same guard, the same parameters, and the same answer. Neither can apply an update or clear the Circuit breaker from MCP. Those tools do not exist — not disabled, not permissioned, absent. This page is about agents operating Ripen. Agents working on Ripen's own source are a different audience, served by AGENTS.md. There is no…

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

4 rules. About 0 are common, 1 is distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

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

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

    Read 3 narrowly: the Circuit breaker is open, or a rollback failed.

    line 73
  2. Very specific:

    Every read carries backend, stack, and service, with service null for a stack-level policy.

    line 145
  3. Very specific:

    Every run has a UUIDv7 run_id, persisted on attempts, echoed in status, and stamped on Events.

    line 152
  4. Distinctive:

    Read-only, which is what the Docker MCP Catalog entry ships:

    line 199

≈ “Common” is an estimate: at least 1 in 5 of the 36,368 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

The agent surface

Ripen's machine-facing interface is the CLI and one MCP server. They are the same surface: every MCP tool maps to a CLI verb with the same guard, the same parameters, and the same answer.

Neither can apply an update or clear the Circuit breaker from MCP. Those tools do not exist — not disabled, not permissioned, absent.

This page is about agents operating Ripen. Agents working on Ripen's own source are a different audience, served by AGENTS.md.

Everything answers one envelope

There is no --json flag. The default, and the only output an agent should consume, is one JSON object on stdout, success or failure:

{
  "schema_version": 1,
  "command": "status",
  "occurred_at": "2026-08-19T09:14:22Z",
  "ok": true,
  "data": { }
}

A failure is the same envelope with ok: false and a typed error:

{
  "schema_version": 1,
  "command": "propose",
  "occurred_at": "2026-08-19T09:14:22Z",
  "ok": false,
  "error": { "code": "precondition_failed", "message": "…", "retryable": false }
}

Failures also print one human-readable line on stderr. Machines can ignore stderr entirely; people usually want it.

The four read verbs — status, candidates, audit, explain — accept --pretty, which renders the same payload as text. It is never inferred from a TTY: an agent running in a pty still gets the envelope unless it asked. --pretty is not registered on writes, daemon, or mcp.

Error codes

CodeRetryableMeans
usagenoThe command or its flags are wrong.
config_invalidnoThe policy would not load.
not_foundnoNo such stack, or nothing to clear.
precondition_failednoSomething must change before this can work.
breaker_opennoThe Circuit breaker is open. A person has to clear it.
state_lockedyesAnother run holds the lease.
backend_unavailableyesThe backend could not be reached.
registry_unavailableyesThe registry could not be reached.
internalnoSomething Ripen could not classify.

Ignore codes you do not recognize; the set can grow without a version bump.

Exit codes

CodeMeaning
0Success.
1Operational failure.
2Configuration or usage.
3A human needs to look at this.

Read 3 narrowly: the Circuit breaker is open, or a rollback failed. Nothing else uses it, so it is worth alerting on.

The verbs

Reads

VerbAnswers
ripen status [--pretty]Every configured Service with its Baseline, Candidate, pending Proposal, and last result, plus the breaker, the lease, Notifier health, versions, and the effective policy.
ripen candidates [--pretty]Every Candidate under observation and whether it has matured.
ripen audit [--pretty]The audit trail, newest first.
ripen explain [--pretty] <stack>Why the next run would, or would not, act on this stack.

status is driven by the policy, not by what happens to be in the database: a Service that has never been observed still appears, with baseline: null.

audit reads the attempts table — the record of what Ripen did — never the Event stream, which is a notification channel. It pages:

ripen audit --limit 50
ripen audit --limit 50 --cursor 412        # from a previous next_cursor
ripen audit --run 01920e2f-…               # one run
ripen audit --stack media --result rolled_back

An empty cursor starts at the newest attempts. Otherwise, pass a positive decimal integer from next_cursor, within the signed 64-bit range. Signs, whitespace, and trailing text are rejected with a usage error. A null next_cursor means the last page.

The limit defaults to 50 when omitted, zero, or negative. Malformed limits and values that overflow pagination are rejected. CLI and MCP use the same pagination rules. The Web UI's /audit and /api/audit routes accept limit and cursor query parameters and return HTTP 400 for invalid values.

explain answers offline, from policy and state alone. No backend call, no registry call, no network. It lists the blockers in the order a run would hit them:

{"blockers": ["the configured mode is monitor", "the candidate matures at 2026-08-20T09:14:22Z"]}

Writes

VerbDoes
ripen run --mode monitorOne observation cycle. Never mutates a Stack.
ripen run --mode applyOne Transaction that may change one Service.
ripen propose <stack>Open the Proposal for a matured Candidate.
ripen clear-proposal <stack> --reason "…"Drop a reviewed, stale Proposal.
ripen clear-breaker --reason "…"Close the Circuit breaker.
ripen rebaseline <stack> [--service name] --reason "…"Accept a drifted Service's proven running digest as its Baseline.

The clear- verbs and rebaseline require a reason, and it is recorded. An operator saying what they fixed, or why a change should stand, is the point of the gate.

Process verbs

VerbDoes
ripen daemon [--once] [--success-reports=false]Run on the configured interval. Writes nothing to stdout. Successful updates also print a plain-text report to stderr by default; disable it for structured-only consumers.
ripen mcp [--enable-writes]Serve MCP over stdio.
ripen notify testSend a real notifier.test through the real webhook path.
ripen schemaThe JSON Schema for every response.
ripen versionBuild metadata and every schema version.

Identity on the wire

Every read carries backend, stack, and service, with service null for a stack-level policy. The state store's internal key never appears in JSON.

actor — cli, daemon, or mcp — is recorded on every write and every Event. It is determined by the surface that ran the code. There is no parameter for it, and no caller can declare its own.

Every run has a UUIDv7 run_id, persisted on attempts, echoed in status, and stamped on Events. It is how you tie an alert to what actually happened:

ripen audit --run "$(ripen run --mode monitor | jq -r .data.run_id)"

Schemas

ripen schema emits a JSON Schema per command, and the same documents are checked into docs/schema/v1/ and shipped in every release archive. A test asserts the two are identical, so the published schema cannot drift from what the binary emits.

Receivers should ignore unknown fields and unknown result codes. Adding either is not a breaking change and does not bump schema_version.

MCP

ripen mcp                    # four read tools
ripen mcp --enable-writes    # plus three write tools

Stdio, tools only. Nothing but protocol frames is ever written to stdout.

ToolCLI equivalent
statusripen status
candidatesripen candidates
auditripen audit
explainripen explain <stack>
run_monitor_cycleripen run --mode monitor (writes only)
create_proposalripen propose <stack> (writes only)
clear_proposalripen clear-proposal <stack> --reason … (writes only)

Results carry the identical Response envelope as structuredContent. A failure is isError: true with the failure envelope attached, never a JSON-RPC protocol error, so a caller can see what went wrong and correct itself.

Read-only mode is structural. Without --enable-writes the write tools are never registered and the write path is never built: the process loads no credentials and opens no clients. Apply mode and clear_breaker have no tool in either mode.

Container packaging

Read-only, which is what the Docker MCP Catalog entry ships:

services:
  ripen-mcp:
    image: ghcr.io/frankieramirez/ripen:latest
    command: ["mcp"]
    stdin_open: true
    volumes:
      - ./policy.yaml:/config/policy.yaml:ro
      - ./data:/data:ro

Writes enabled, which is a deliberate choice for your own infrastructure:

    command: ["mcp", "--enable-writes"]
    volumes:
      - ./policy.yaml:/config/policy.yaml:ro
      - ./data:/data

The difference is one flag and one :ro.

Download now (ZIP)

  • 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 28,693 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 repository17 other files it gives its agents.

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.