Skip to main content

agtcli

ci

Build CLIs an agent can actually drive. A runtime you import, a scaffold that generates a working tool, and a checklist that runs.

The command, the module, and the PyPI distribution are all agtcli.

The rules and the incident behind each are in PLAYBOOK.md. This file is how to use the thing.

Why a library and not a template

The same contract copied into five projects is five things that drift. orly and mercadona-cli independently grew the same exit-code taxonomy, the same compact/--raw split, and the same atomic-write helper, in two languages, and the copies already disagree.

So the mechanical half is imported and tested once. agtcli check covers the half that is still yours.

Install

pip install agtcli     # or: uv tool install agtcli
agtcli --help

From a clone instead, which is what you want if you are changing the contract:

uv sync && uv tool install --editable .

Either works, and the difference shows up in what you scaffold. A generated project depends on agtcli, and agtcli new pins that dependency at wherever this copy came from: nothing to pin from an index, the local path from a clone, the same commit from a git install. So a project scaffolded by the released agtcli builds anywhere; one scaffolded from your clone builds where that clone is.

Recipes

Scaffold a CLI and confirm it works

agtcli new hansard --description "Search UK Hansard debates." \
                    --triggers "hansard, what did parliament say about X"
cd hansard && uv sync && uv run pytest -q     # 14 passing
uv tool install --editable . && hansard --help

You get a tool that already has typed exit codes, a compact default with a --raw escape hatch, atomic 0600 state, a credential-rotation hook, a blast-radius guard, a thin skill, and contract tests that pass. Then replace src/hansard/api.py with the real service.

Audit one before shipping

agtcli check ./hansard          # exits non-zero while anything fails
agtcli check ./hansard --json   # one object per check
agtcli rules                    # just the checklist

Gate a commit or a CI job on the checklist

agtcli check . --json | jq -e '.failed == 0'

Find which rule a check is about

agtcli rules --json | jq -r '.[] | select(.name=="truncation-marked") | .why'

Fifteen items are checked by reading the project. Nine cannot be, so they are reported as unverified rather than counted as passes.

$ agtcli check ./hansard
  ✓ skill-shipped: skill/SKILL.md
  ✓ exit-codes-typed: inherited from agtcli.build
  ✓ truncation-marked: cuts are marked
  ✓ blast-radius-capped: costly commands consult the guard
  ...
  ? dumb-subagent-test-run: the only step that reliably finds what you missed

9 item(s) cannot be checked mechanically; verify them yourself.

What you import

import agtcli
from agtcli import Session

app = agtcli.build("mytool", help="...", notes=AGENT_NOTES, unit="EUR")

@app.command()
def get(ctx: typer.Context, id: str):
    s = Session.get(ctx)
    s.out.emit(record, compact=lambda r: {"id": r["id"]})

@app.command()
@agtcli.costly                       # cannot return without checking the cap
def submit(ctx: typer.Context, id: str):
    s = Session.get(ctx)
    s.guard.check(total, f"submitting {id}")

main = agtcli.main_for(app)
build / run / main_for a Typer app wired to the contract; one place decides every exit code
ExitCode 0 ok, 1 retryable, 2 usage, 3 not-found, 4 auth, 5 timeout, 6 refused. The --help table is generated from this enum, so it cannot drift
Output compact by default, --raw for everything, and under --json stdout carries JSON and nothing else
trim cut a value yourself; the result says how much is missing. The one to reach for
mark_truncation / elide the halves of trim. mark_truncation alone is for text somebody else cut, where the last character is the only evidence; wrapping your own elide in it marks whole values as truncated
write_atomic / write_json mkstemp plus os.replace, 0600, because agents run in parallel
Guard / @costly a cap by flag, env or config that fails closed, and raises if a costly command never consults it
Config pydantic-settings with the precedence the right way round: flag, then env, then file

Errors are typed and carry what to do next:

$ hansard submit 123 --json ; echo "exit $?"
{
  "error": "refused",
  "message": "submitting 123 is irreversible and --yes was not given",
  "exit_code": 6,
  "retryable": false,
  "remedy": "re-run with --yes once a human has agreed"
}
exit 6

The skill

skill/ is meant to be symlinked, so it versions with the code:

ln -s "$PWD/skill" ~/.claude/skills/agtcli

A CLI is invoked, not found, so the skill body is a one-liner that points at --help. What the agent discovers progressively is the tool: tool --help for the verbs, rules and exit codes; tool <verb> --help for one command, with the global flags carried down so --max-cost is still visible on the command that spends; and a next-step hint in the output itself.

Development

uv run pytest -q

Every test is a rule from the playbook or a bug that actually happened. If you change the contract, a test should fail.

Metadata

Release files for agtcli 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agtcli 0.1.2
File Size Uploaded Provenance
agtcli-0.1.2.tar.gz 78.3 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for agtcli 0.1.2
File Interpreter ABI Platform
agtcli-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 123.5 kB

Release files / agtcli-0.1.2.tar.gz

Download URL agtcli-0.1.2.tar.gz
Size 78.3 kB
Tags Source
SHA-256 checksum
How to use checksums
0bf6f5c1a6d65675fe8452e7d21bce73843f66b64db8bf3adb634e831ac22930
BLAKE2b-256 checksum
How to use checksums
eaa51c42b66a10a433717253ba9b64df457c72ccedaf29b9dd15cccce2b18434
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 18, 2026.

Transparency log

Release files / agtcli-0.1.2-py3-none-any.whl

Download URL agtcli-0.1.2-py3-none-any.whl
Size 45.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e18803ddee3a48ac74b170b87f74c334a383bded17ff0eeeeaa801e6b55ce728
BLAKE2b-256 checksum
How to use checksums
cfa37650b272c4edcbd153df988051399afbb8c4b9547408890a47d3f2484e59
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 18, 2026.

Transparency log

Security for agtcli 0.1.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for agtcli-0.1.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 18, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page