Specification
The complete format specification for CLAW.md
A claw is an asynchronous agent. It packages work you would normally hand to an agent so it can run unattended, rather than inside an interactive session. Anything you can ask an agent to do once, a claw can do without you in the loop. They use the same MCP servers, CLIs, and tools your agent does, so claws inherit whatever capabilities the host environment already provides. A claw runs whenever something triggers it: a schedule, an event such as a webhook, or a manual run. A claw with a schedule runs at those times; one with no schedule can still run from an event or a manual start. The optional concurrency field governs what happens when runs would overlap, and it applies to every run source alike.
A claw is made of ordered tasks, runtime defaults, an optional shared system prompt, and an optional schedule. A CLAW.md file is the portable description of one claw, a single self-contained file with no companion directories, no sibling scripts, no external assets. Everything a claw needs lives inside it.
The format is designed for portability. Any tool can implement a CLAW.md parser and runner without knowledge of the host that produced it.
CLAW.md format
A CLAW.md file has three parts, in order:
- YAML frontmatter between
---fences, holding claw-level metadata - Optional intro markdown between the closing fence and the first task heading
- Zero or more tasks, each opened by a single top-level
# Task nameheading. A file with no tasks is valid documentation but cannot be executed
Frontmatter
| Field | Required | Constraints |
|---|---|---|
name |
Yes | Max 64 characters. Lowercase letters, numbers, and hyphens only. Must not start or end with a hyphen, and must not contain consecutive hyphens. |
description |
Yes | Max 1024 characters. Non-empty. Describes what the claw does and when to use it. |
version |
No | Integer. The specification version the document targets. Absent means 1. |
system_prompt |
No | Inline body of a shared system prompt applied to every task. |
schedule |
No | Schedule expression. Absent means the claw runs only when explicitly executed. |
start |
No | Earliest moment the schedule may trigger. A bare date YYYY-MM-DD or a datetime (see the start and end section). Absent means unbounded on the start side. |
end |
No | Latest moment the schedule may trigger. A bare date YYYY-MM-DD or a datetime; a bare date includes the whole day. Absent means unbounded on the end side. Must be greater than or equal to start when both are present. |
timezone |
No | IANA Time Zone Database name (e.g. America/New_York, UTC) governing clock rules and date-only start/end bounds. Absent means UTC. Interval rules ignore it. |
concurrency |
No | One of skip, allow, queue, replace. Governs what happens when a run is requested while another run of the same claw is active. Absent means skip. |
runtime |
No | Default runtime for tasks that do not declare their own. A short identifier with the same character and length rules as name. auto and bash are the conventional values; a host may define others. Absent defaults to auto. |
options |
No | Map of string keys to string values, passed to the runtime adapter. Every key is specific to the runtime that consumes it; the adapter maps the keys it recognizes to its CLI/config and may ignore or reject the rest. model and effort are common examples. Per-task options shallow-merge over these. |
skills |
No | Array of Agent Skills names the runtime should load. Max 64 characters per name. Lowercase letters, numbers, and hyphens, with no leading or trailing hyphen. Advisory; whether and how a runtime loads a named skill is an implementation detail, and it ignores names it does not recognize. A task that declares its own skills replaces this set for that task. |
timeout |
No | Default per-task wall-clock cap. Duration string of one or more <count><unit> segments, units s, m, h, non-negative integer counts, no fractional values (e.g. 45s, 30m, 1h, 1h30m). Absent or 0 inherits the runtime's built-in default. Tasks override per task. |
compatibility |
No | Max 500 characters. Free-form prose describing environment requirements (intended product, system packages, network access, credentials). |
license |
No | Short string. SPDX identifier or a short license string. |
metadata |
No | Map of string keys to string values for implementation-specific extensions. |
Minimal example
---
name: claw-name
description: A description of what this claw does and when to use it.
---
# Task name
The prompt the agent will execute for this task.
Example with optional fields
---
name: eng-dependency-cve-watch
description: Watch the GHSA, OSV, and NVD advisory feeds each morning for new entries that affect your declared dependencies, rank each by severity with the fixed version, and email a digest only when a new advisory lands.
schedule: daily @ 07:00
timezone: America/New_York
concurrency: queue
runtime: auto
options:
model: fast
effort: high
skills:
- web-search
- email
compatibility: A dependency manifest the agent can read. Private lockfile access is optional; without it the public manifest is the source of declared dependencies.
license: MIT
metadata:
author: example-org
version: "1.0"
---
name field
The required name field:
- Must be 1-64 characters
- May only contain lowercase alphanumeric characters (
a-z,0-9) and hyphens (-) - Must not start or end with a hyphen
- Must not contain consecutive hyphens (
--) - Is a stable identifier for the claw, suitable for unambiguous reference across systems. It is not a filename or directory name and need not match any containing path
Valid examples
name: eng-dependency-cve-watch
name: sales-funding-alerts
Invalid examples
name: Sales-Funding-Alerts # uppercase not allowed
name: -sales-funding-alerts # cannot start with a hyphen
name: sales--funding-alerts # consecutive hyphens not allowed
description field
The required description field:
- Must be 1-1024 characters
- Should describe both what the claw does and when to use it
- Should include keywords that help agents identify relevant tasks
Good example
description: Sweep public funding signals each weekday against your target account list, then email each match with the round size, the lead investor where disclosed, and a one-line read on what the company can now afford.
Poor example
description: Watches for funding.
version field
The optional version field declares which specification version the document targets:
- Is an integer
- Absent means
1 - A parser must accept the versions it implements and reject a document whose declared
versionit does not support, so later features cannot be silently misinterpreted
Example
version: 1
system_prompt field
The optional system_prompt field:
- Holds an inline body of a shared system prompt that every task inherits
- Is YAML text; multi-line bodies use the block scalar syntax (
|) - Is an inline body, not a reference to a named or externally stored personality. The full text lives here so the CLAW.md stays self-contained
Example
system_prompt: |
You are a cautious security operations assistant. Prefer clear,
actionable findings over noisy speculation. Never modify firewall
rules, users, packages, services, or files unless explicitly
instructed.
schedule field
The optional schedule field declares times at which a claw runs on its own. It is one trigger among several; a claw with no schedule still runs from an event such as a webhook or a manual start. Grammar:
every Nmorevery Nh(interval rules; timezone-independent, anchored at 00:00 UTC)hourly(interval shorthand forevery 1h)daily,weekly, ormonthly(period shorthands firing at 00:00;weeklyon Sunday,monthlyon the 1st)daily @ HH:MM[,HH:MM...]weekly @ HH:MM[,HH:MM...]monthly @ HH:MM[,HH:MM...]weekdays @ HH:MM[,HH:MM...]weekends @ HH:MM[,HH:MM...]mon,wed,fri @ HH:MM[,HH:MM...](specific days of the week)on YYYY-MM-DD[,YYYY-MM-DD...] @ HH:MM[,HH:MM...]- Combine multiple rules with
;
Clock rules (daily, weekly, monthly, weekdays, weekends, weekday lists, on DATE, and any @ HH:MM) are evaluated in the claw's timezone, which defaults to UTC. A bare daily, weekly, or monthly fires at 00:00 in that timezone (weekly on Sunday, monthly on the 1st), and a trailing @ HH:MM overrides the time. Interval rules (every Nm, every Nh, hourly) are timezone-independent. Absent means the claw runs only when explicitly executed, which a runner may expose as a manual run or an external trigger such as a webhook. The concurrency field governs overlap across all of these run sources alike.
Keywords and weekday tokens are lowercase (mon, tue, wed, thu, fri, sat, sun). @ introduces times. Times are 24-hour HH:MM in the range 00:00 to 23:59. Optional spaces are allowed around @, ,, and ;. Rules combined with ; are unioned, and duplicate trigger instants collapse to a single run.
N in an interval rule must be a positive integer. Interval rules anchor at 00:00 UTC of each day and reset at the next midnight, so an interval that does not divide 24h (e.g. every 5h) realigns at midnight and leaves a shorter final gap before 00:00. For even spacing, prefer a 24h-divisor interval: 1m..30m, 1h, 2h, 3h, 4h, 6h, 8h, or 12h.
Examples
schedule: every 5m
schedule: weekdays @ 09:00,17:00
schedule: weekdays @ 09:00; weekends @ 12:00
schedule: on 2026-01-15 @ 12:00
schedule: monthly @ 09:00
schedule: hourly
start and end fields
The optional start and end fields bound the window during which a schedule is active. The two fields are independent:
startis the earliest moment the schedule may trigger. Before it, the claw does not run automatically.endis the latest moment the schedule may trigger. After it, the claw does not run automatically.- An absent bound leaves that side unbounded.
- When both are present,
endmust be greater than or equal tostart.
Each bound accepts one of these forms:
- a bare date
YYYY-MM-DD YYYY-MM-DDTHH:MMYYYY-MM-DDTHH:MM:SS- a full RFC3339 timestamp
A bare date and an offset-less datetime are interpreted in the claw's timezone; an RFC3339 string keeps its own offset. A bare-date start anchors at 00:00 of that day. A bare-date end resolves to the last instant of that day, so the end day is included.
These fields only affect scheduled triggers. A claw with no schedule runs only on explicit invocation (a manual run or an external trigger such as a webhook) regardless of start and end.
Examples
schedule: daily @ 09:00
start: 2026-06-01
end: 2026-08-31
schedule: every 1h
start: 2026-01-01
timezone field
The optional timezone field is an IANA Time Zone Database name (e.g. America/New_York, Europe/Paris, UTC). It governs every clock rule in schedule (daily, weekdays, weekends, weekday lists, on DATE, and any @ HH:MM) and the interpretation of date-only start and end bounds. Absent means UTC. Interval rules (every Nm, every Nh) ignore this field.
Example
timezone: America/New_York
concurrency field
The optional concurrency field declares what a runner does when a new run of a claw is requested while another run of the same claw is active. Run requests come from any source equally, whether a schedule firing, a manual run, or a runner-exposed webhook. Identity is the claw's name within the runner's scope, so runs of different claws never gate one another.
The field is a fixed enum of four values:
skip(the default). At most one run is active at a time. A request that arrives while a run is active is dropped.allow. Runs may overlap. Each request starts its own run with no limit on how many run at once. This suits a burst of webhook events that should each get their own run.queue. Runs never overlap, but a request during an active run waits and starts after the active run finishes. How many requests may wait, and whether repeated requests collapse while one is already waiting, is left to the runner.replace. A new request cancels the active run, then starts a fresh one. Cancellation is best effort. A runner stops the active run as cleanly as it can before starting the replacement.
An absent concurrency defaults to skip. The value is a fixed enum, so a parser rejects any other value rather than deferring it to the runtime. concurrency is a claw-level property of the whole run and has no per-task override.
Example
concurrency: allow
runtime field
The optional runtime field names the runtime for tasks that do not declare their own. It is a short identifier following the same character and length rules as name: 1-64 characters, lowercase letters, numbers, and hyphens, with no leading, trailing, or consecutive hyphens.
Two values are conventional. Most runtimes are expected to support them, though support is optional:
autoruns the task body as a prompt against an AI agent with full tool use. The model is selected throughoptions.bashruns the task body as a shell script (it must be a single fenced```bashblock).
A host may also define more specific runtime identifiers, for example claude or codex. A runtime accepts the values it understands and rejects the rest at run time, not at parse time. Absent, runtime defaults to auto. A task may override this field via its per-task fenced YAML block.
options field
The optional options field is a map of string keys to string values that tune the runtime. Every key is specific to the runtime that consumes it. A runtime maps the keys it recognizes to its own CLI flags or configuration and may ignore or reject the rest. The spec defines no keys and does not validate the values; an unrecognized key or value surfaces at run time as an error from the runtime, not at parse time.
model (an opaque model identifier) and effort (an opaque reasoning-effort value such as low, medium, or high) are keys an auto runtime commonly accepts. They are illustrative; a runtime may accept any keys it chooses.
A task may override individual keys via its per-task fenced YAML block: per-task options shallow-merge over the claw-level options, so a task can change one key while inheriting the rest.
Example
options:
model: fast
effort: high
skills field
The optional skills field is an array of skill names declaring the Agent Skills a runtime should load for the claw. Each entry is a skill name (the identifier from a skill's SKILL.md): 1-64 characters, lowercase letters, numbers, and hyphens, with no leading or trailing hyphen. There is no slash-namespacing.
The format carries only the names. Whether a runtime supports Agent Skills at all, how it resolves a name to a skill, and whether or how it loads that skill are implementation details left to the runtime and its agent. The specification defines no skill names, no registry, and no resolution or loading behavior. A runtime maps the names it recognizes to its own catalog and ignores the rest, so a name is a portable hint, not a guaranteed contract. A runtime may honor or ignore the field as a whole.
Declaring a skill is a request, not a grant. A runtime still applies its own permissions, sandboxing, and credential policy, and never installs or runs anything merely because a claw names a skill. Naming a skill cannot widen what the runtime would otherwise allow.
Because skills is advisory, a name alone cannot guarantee a skill is present. When a skill is required rather than merely preferred, state that requirement in the human-readable compatibility prose as well, since the format does not mandate runtime execution behavior.
Order is not significant; skills is a set, and duplicate entries collapse to one. At the claw level, an empty skills: [] is equivalent to an absent field. At the task level it is not, because a per-task skills block replaces the inherited set, so skills: [] clears it (see the per-task replacement below).
A task replaces this set rather than merging into it. A task with no skills block inherits the claw-level set, and a task that declares skills replaces the claw-level set entirely for that task. This differs from options, which shallow-merges. The replacement supports least-privilege scoping: declare a high-reach skill only on the one task that needs it, or drop it for a task with skills: [].
Example
skills:
- web-search
- email
compatibility field
The optional compatibility field:
- Must be 1-500 characters if provided
- Should only be included if the claw has specific environment requirements
- Can describe intended product, required system packages, network access, credentials, or anything else a host needs in place before running
Examples
compatibility: Designed for a claw runner on a Linux host.
compatibility: Requires git, docker, jq, and outbound HTTPS.
compatibility: Requires Python 3.14+ and uv.
Most claws do not need this field.
license field
The optional license field specifies the license applied to the claw. Keep it short, either an SPDX identifier or a short license string.
Examples
license: MIT
license: Apache-2.0
license: Proprietary
metadata field
The optional metadata field:
- Is a map of string keys to string values
- Lets implementations store properties not defined by this specification
- Must be preserved on round-trip when a tool reads and rewrites a CLAW.md
- Should use uniquely-named keys (e.g.
org:source,org:author) to avoid accidental conflicts across implementations
Example
metadata:
author: example-org
version: "1.0"
org:source: https://example.com/claws/eng-dependency-cve-watch
Body content
The Markdown body after the frontmatter contains the claw's tasks. Tasks are detected by their top-level # headings.
Intro
Markdown between the closing frontmatter fence and the first # heading is treated as a human-readable introduction. Implementations may render it on a detail page. It is never part of any task prompt and carries no runtime semantics.
Task headings
A task starts at the first column-0 # heading (one hash followed by a space) and ends at the next column-0 # heading or end of file. The heading text is the task name. Tasks run in the order they appear.
# Watch
You are a watchman for this host. Gather these signals from the local
machine and write a brief report.
Task headings must be preceded by a blank line or start of body. A column-0 # starts a task only when it is not inside a fenced code block, so a parser must track fenced code blocks while scanning for headings. Inside a task body, authors may freely use ##, ###, and lower-level headings without triggering a new task. A column-0 # heading inside a task body would be interpreted as the next task; wrap such content in a fenced code block or use a lower heading level.
Per-task overrides
Immediately under a task heading (allowing one blank line) a fenced ```yaml block may set per-task overrides:
# Watch
```yaml
runtime: auto
options:
model: capable
skills:
- web-search
```
You are a watchman for this host...
Recognised per-task keys: runtime, options, skills, timeout. If the block is absent, the task inherits the claw-level defaults. options is a map that shallow-merges over the claw-level options (see the options field definition above); the values are opaque and an unrecognized value surfaces at run time, not at parse time. skills is an array that replaces the claw-level skills for that task rather than merging into it (see the skills field definition above); a task with no skills block inherits the claw-level set, and skills: [] clears it. This replace behavior is deliberately different from the options shallow-merge. timeout is a duration string of one or more <count><unit> segments, units s, m, h, non-negative integer counts, no fractional values (e.g. 45s, 30m, 1h, 1h30m); absent or 0 inherits the claw default, which itself inherits the runtime's built-in default.
A leading ```yaml block is read as overrides only when it is the immediate first content under the heading (after an optional blank line) and it contains at least one recognised override key. When it is the overrides block, any unrecognized top-level key inside it is a validation error, so a misspelled key is reported rather than silently swallowed. A leading YAML block that contains none of the reserved keys is treated as ordinary prompt body, so a prompt that merely opens with a YAML example is not consumed as overrides. The residual cost of this leniency is that a block carrying only a typo and no valid key (for example only timeut: 5m) reads as prompt body. A fenced YAML block is used here, rather than a second ----fenced frontmatter, to avoid colliding with markdown's horizontal-rule syntax.
Task body by runtime
- For
runtime: auto, everything after the optional yaml block is the prompt sent to the model. Markdown formatting is allowed; implementations render it as plain text. A runtime other thanbashfollows this same prompt-body convention unless it defines its own. - For
runtime: bash, the body must contain exactly one fenced code block whose info string is exactlybash(an opening fence of three backticks at column 0, the info stringbash, and a matching closing fence). The fenced content is the script. Prose outside the fence is treated as documentation and ignored at runtime.
# Cleanup
```yaml
runtime: bash
```
Wipe the snapshot file written by the previous task.
```bash
#!/bin/bash
set -o errexit
set -o nounset
set -o pipefail
rm -f /tmp/snapshot.json
```
Tasks run in source order. How an implementation handles a task that fails, including whether later tasks still run, is left to the implementation.
Placeholders
CLAW.md v1 treats {{anything}} as ordinary text. Tools neither extract nor substitute {{...}}. A tool that does not reformat the body preserves the body text exactly, whether it contains literal values or template-style markers; a tool that reserializes the frontmatter (for example rewriting metadata) need not be byte-identical.
Authors who want parameterization can hand-edit the file before running it. A future revision of this specification may define substitution semantics; v1 leaves that surface undefined.
Progressive disclosure
A CLAW.md should be structured so agents can load detail incrementally:
- Frontmatter is cheap to scan and is loaded cheaply for listing and search
- Body loads when the claw is activated for execution or detailed inspection
Keep CLAW.md under 500 lines. If a task prompt needs extensive reference material, inline it concisely or split the work into multiple tasks.
Validation
A conforming parser must reject:
- Missing
nameordescription nameviolating the character or length rulesdescriptionexceeding 1024 characterscompatibilityexceeding 500 charactersruntimeviolating thenamecharacter or length rules (claw-level or per-task)- A
skillsvalue that is not an array of strings, or anyskillsentry violating the identifier character or length rules (claw-level or per-task) - A
concurrencyvalue that is not one ofskip,allow,queue, orreplace endearlier thanstartwhen both are present- Unknown top-level frontmatter keys
- A present
versionwhose value the parser does not support (e.g.version: 2on a v1 parser) - A
bash-runtime task whose body has zero or more than one fencedbashblock - A per-task overrides block (a leading
```yamlblock carrying at least one recognised override key, one ofruntime,options,skills,timeout) that also carries an unrecognized top-level key
A conforming parser must accept:
- An absent
version, orversion: 1 - A CLAW.md with no tasks (treated as documentation; cannot be executed)
- A CLAW.md with no intro markdown
- Unknown keys inside
metadata(preserved on round-trip) - Any keys inside
optionsat either claw or per-task scope; the map is opaque in meaning and its values are strings, since nested maps and arrays are not part of the format - An absent
skillsat either claw or per-task scope, and an emptyskills: [](at claw level equivalent to absent; at task level an empty replacement set that clears the inherited skills) - Duplicate
skillsentries (collapsed to one, since the field is a set) - An absent
concurrency(equivalent toskip) - A
runtimevalue other thanautoorbashthat satisfies thenamecharacter rules (the runtime, not the parser, decides whether it can run it) - A leading
```yamlblock that contains none of the recognised per-task override keys (treated as prompt body, not an error) - Multi-line YAML block scalars in any string field
{{...}}tokens anywhere in any string field, treated as literal text
Version
This document specifies CLAW.md v1. The optional top-level version field is the forward-compatibility signal: a document declares the specification version it targets, an absent version means 1, and a parser rejects a declared version it does not support. Alongside this, conforming v1 parsers must reject documents that introduce unknown top-level keys so that later features cannot be silently misinterpreted. The skills and concurrency fields are new top-level keys folded into v1 before adoption; a v1 parser recognizes them and must still reject any other unknown top-level key.