Skip to content

Create a Capability

The whole arc, in order: from "I keep running these same commands" to a validated, audited, shared capability your team and CI can re-run forever.

Follow this page start to finish once. After that, the Authoring Reference is the page you'll come back to.

Working example used throughout

A repository health check — the summary, community profile and open PRs for one repo. Substitute your own task; the sequence doesn't change.


Before you start

runtime version
runtime config validate

config validate should show your capabilities directory and a working auth provider. If it doesn't, fix that first — Troubleshooting.


Step 1 — Write down the outcome, not the commands

Start from what you want to be true when it finishes, in one sentence:

"For a given repository, show me its summary, whether it has a README and licence, and what PRs are open."

This matters because a capability names operations, not a script's steps. If you can't say the outcome in a sentence, you probably have two capabilities.


Step 2 — Find the operations that serve it

Never guess at operation names. Every provider publishes its real surface:

runtime github --help      # every operation, and the transport chosen for it
runtime files --help

For task-shaped starting points, the Runtime Home ships a use-case reference organized by what engineers are trying to achieve:

cat ~/.engineering-runtime/commands/github_commands.txt

For our example, three operations look right: repo summary, api GET for the community profile, and pr list.

The transport column is information, not a choice

--help shows rest, graphql, cli or file per operation. You never select one, and nothing you write should depend on it.


Step 3 — Prove each operation before you write anything

This is the step that saves the most time, and the one most people skip. Writing nine steps and discovering step two never worked is the default failure mode.

First check the command line resolves — no auth, no policy, no execution, no network:

runtime resolve github repo summary cli/cli
runtime resolve github api GET /repos/cli/cli/community/profile
runtime resolve github pr list --repo cli/cli

Then run each one for real, once, to see the shape of what comes back:

runtime github repo summary cli/cli
runtime github api GET /repos/cli/cli/community/profile
runtime github pr list --repo cli/cli --limit 5

If an operation fails here, it will fail inside a capability too — a capability gets no special powers.


Step 4 — Decide what is an input

The rule of thumb:

The value is… Where it belongs
what this run is about — a repo, a ticket, a version An input
where you are — org, project, namespace Runtime Context

Never hardcode an org, repository or environment into args. In our example, the repository is clearly the subject of the run, so it becomes an input.


Step 5 — Write the file

Create ~/.engineering-runtime/capabilities/repo-health-check.md:

# Repository health check

Summary, community profile and open PRs for one repository.

```runtime
version: v1

inputs:
  repository:
    description: Repository to inspect, as <owner>/<repo>
    required: true

workflow:
  - provider: github
    args: [repo, summary, "${repository}"]

  - provider: github
    args: [api, GET, "/repos/${repository}/community/profile"]

  - provider: github
    args: [pr, list, --repo, "${repository}", --limit, "10"]
```

Three things that trip people up:

  • The prose is for humans. Only the fenced ```runtime block executes.
  • args are the CLI words, split into a list. runtime github repo summary cli/cli becomes args: [repo, summary, "${repository}"].
  • Exactly one of provider: or binary: per step. Never both, never neither.

Prefer required: true on every input. An input you declare but don't supply stays in the arguments as the literal string ${name}.


Step 6 — Validate

runtime capability validate repo-health-check

Validation resolves every step against the operation surface of the binary you are running, and reports every problem it finds — not just the first. A typo, a renamed operation or a binary missing from allowed_binaries fails here, before anything executes.

Fix and re-run until clean. A capability that doesn't validate doesn't run, no matter how reasonable it looks.


Step 7 — Execute

runtime capability execute repo-health-check --input repository=cli/cli

Machine-readable, covering every step:

runtime --output json capability execute repo-health-check --input repository=cli/cli

Execution re-validates, checks required inputs, substitutes ${name}, then runs each step in order — stopping at the first failure. Steps before it have already run. Capabilities are not transactional, so put anything destructive or expensive last.


Step 8 — Confirm what actually happened

runtime audit tail -n 5 --output json

One record per step, each carrying the transport its provider chose. In our example that's graphql for the summary and rest for the profile — and you named neither. That is the property that keeps the file working when a provider changes how it reaches the platform.


Step 9 — Share it

A capability on one laptop is a script. Move it into a version-controlled directory and it becomes something a team and CI both run:

export RUNTIME_CAPABILITIES_DIR=~/work/engineering-runtime-capabilities/capabilities
mv ~/.engineering-runtime/capabilities/repo-health-check.md \
   "$RUNTIME_CAPABILITIES_DIR/github/"

runtime capability validate github/repo-health-check

Commit it and open a pull request — the format is Markdown precisely so the review is a readable diff. From then on, anyone resolves it by name from any directory, and CI executes the same file with no model in the loop.

Full setup: Sharing a Capability Directory and CI/CD.


When something goes wrong

Symptom Where to look
args don't resolve to an operation runtime <provider> --help — it may not exist in your version
An unrecognized key, with a line number Only these keys are valid
binary not allowed Your policy-config.yaml may predate the release that added it — Policy
Validated fine, denied at execution Policy denies those specific arguments, not the operation
Literal ${name} in the output An input was declared but not supplied
Works by path, fails by name The capabilities directory isn't where you think — runtime config validate

More: Validate & Execute and Troubleshooting.


Go deeper

Every key, rule and limitation Authoring Reference
The validate/execute loop in detail Validate & Execute
Command flags and addressing runtime capability
Team and CI distribution Sharing a Capability Directory
Working files to copy Examples

The authoring contract also ships inside your Runtime Home, refreshed with every binary version:

cat ~/.engineering-runtime/specs/capability-spec.md
cat ~/.engineering-runtime/specs/github/capability-spec-github.md
cat ~/.engineering-runtime/specs/files/capability-spec-files.md