View raw

Table of Contents

RAIL tool reference

Read this file when you need the exact arguments of one tool, or the shape of its result. The main skill file gives the workflow.

Every tool accepts an optional `root` argument. `root` names the project directory that holds the stream file. When you omit `root`, the tools use `rail-project-root`. That variable comes from an upward search for `RAIL.org`, so it needs no configuration.

Every tool returns one JSON object. A failed call returns an object with one `error` field. An absent value returns JSON `null`.

Read-only tools

rail-inspect

Arguments: none beyond `root`.

Returns `file`, `todo_keywords`, and `tags`. The `tags` field groups the vocabulary by axis: `kind`, `scope`, `impact`, and `misc`.

Run this tool when a tag call fails, or when you need the keyword sequence of the file.

rail-list

Arguments:

Returns an array of objects, newest first. Each object holds `id`, `title`, `state`, `scheduled`, and `tags`. The `id` field is `null` for an entry that carries no Org ID.

Pass a filter whenever you can, because the stream grows without bound.

rail-show

Arguments:

Returns `id`, `heading`, `state`, `tags`, `scheduled`, `closed`, `body`, `logbook`, `checklist`, and `result`. The `checklist` field holds objects with a boolean `done` field and a `text` field. The `result` field holds the text of the `CLOSING NOTE` from the `:LOGBOOK:` drawer, or `null` when the entry has no closing note. The closing note also appears in the `logbook` array.

rail-verify

Arguments:

Returns `id`, `heading`, `state`, `closed`, and `tags`. Use this tool before a status change and after a status change.

Writing tools

rail-capture

Arguments:

Returns `id`, `file`, `heading`, and `tags`.

The tool inserts the entry as a top-level heading above every other entry. It records the capture time as an inactive `SCHEDULED` timestamp. It wraps the body to 72 columns, and it assigns an Org ID.

rail-set-status

Arguments:

Returns `id` and `state`.

The tool refuses `DONE`. Use `rail-complete` for `DONE`.

rail-block and rail-cancel

Arguments:

Returns `id` and `state`.

`rail-block` writes a `BLOCKED NOTE` closing note into the `:LOGBOOK:` drawer and sets `BLOCKED`. `rail-cancel` writes a `CANCELLED NOTE` closing note and sets `CANCELLED`. Each tool refuses a blank reason.

rail-check

Arguments:

Returns `id` and `items`.

The tool keeps the items in a `Checklist [/]:` block in the body. The `[/]` cookie counts the completed items. `toggle` matches the item text from the start, and it fails when no item matches.

rail-log

Arguments:

Returns `id` and `state`.

The tool prepends a timestamped item to the `:LOGBOOK:` drawer, and creates the drawer when it is absent. The drawer is append-only.

rail-retag

Arguments:

Returns `id` and `tags`.

The tool replaces every tag on the entry. It validates each tag first, so one invalid tag leaves the entry unchanged.

rail-set-result

Arguments:

Returns `id` and `result`.

The tool writes the DONE closing note (`CLOSING NOTE`) into the `:LOGBOOK:` drawer without changing the state, and replaces an earlier closing note. Use it to pre-stage the closing evidence before `rail-complete`. The note stays on one line, because the reader reads one line.

rail-complete

Arguments: the same arguments as `rail-set-result`.

Returns `id`, `state`, `result`, and `closed`.

The tool sets `DONE`, then writes the `CLOSING NOTE` into the `:LOGBOOK:` drawer next to the `CLOSED` timestamp, and reads that timestamp back. It fails when the file does not set `org-log-done` to `time`, because Org must write that timestamp.

Closing note format

Each closing transition writes one note into the `:LOGBOOK:` drawer, next to the state timestamp. The note replaces the old body-line evidence. It reads:

:LOGBOOK:
- CLOSING NOTE [2026-09-07 Mon 19:31] :: model=example-agent commit=3051af0 tests=243 pass; short root cause
:END:

The label is `CLOSING NOTE` for `DONE`, `BLOCKED NOTE` for `BLOCKED`, and `CANCELLED NOTE` for `CANCELLED`. For `DONE`, the `model` field and the tail after the semicolon are optional. The `commit` field and the `tests` field are always present. For `BLOCKED` and `CANCELLED`, the note holds the reason. The note stays on one line.