Skip to main content

typer-agentic

A Typer extension that makes CLIs friendly to coding agents.

When an LLM agent misspells a flag or omits an argument, Typer prints a Rich panel and exits 2. The agent then either burns turns re-reading --help, or, worse, gives up on the tool and starts editing files by hand. typer-agentic intercepts usage errors and, only when an agent is driving, replaces the panel with a compact block: what went wrong, the valid parameters with types and choices, exactly one corrected example, and calm instructions that keep the agent on the retry path. Humans keep Typer's stock output, byte for byte.

Quickstart

from typer_agentic import agent_errors

app = typer.Typer()
...
main = agent_errors(app)  # use `main` as your [project.scripts] entry point

Nothing else changes. agent_errors(app) returns a zero-argument callable, never mutates the app, and never monkeypatches Typer or Click.

Before / after

myapp sync --verbos, Typer 0.27 (stock):

Usage: myapp sync [OPTIONS] {path}
Try 'myapp sync --help' for help.
╭─ Error ────────────────────────────────────────────────────────────╮
│ No such option: --verbos (Possible options: --verbose)             │
╰────────────────────────────────────────────────────────────────────╯

Same command with CLAUDECODE=1 in the environment (Claude Code sets it for you):

✗ Usage error in `myapp sync`: No such option: --verbos

This is a recoverable input mistake, not a bug in the tool. Do not switch tools, edit files or state to work around it, or invent flags; apply the one change below and re-run the command.

Did you mean: --verbose

Fix and retry (one change): Replace '--verbos' with '--verbose'. Run the corrected example.

myapp sync ./PATH --verbose


Valid options:
  --verbose, -v  flag              Enable verbose output.
  --count        INTEGER           How many.
  --env          CHOICE[dev|prod]  Target environment.

Required arguments: PATH

Full reference: myapp sync --help

Honest note: Typer already prints a did-you-mean hint. What this adds is the typed inventory, the runnable example, and the de-escalation copy. If you only want the box-drawing gone, TYPER_USE_RICH=0 does that with no dependency.

Mode resolution

mode="auto" (the default) picks agent or human output per invocation. Highest precedence first:

# Signal Result
1 AgentErrorsConfig(mode="agent" | "human") forced
2 --agent-errors / --human-errors on the command line agent / human
3 AGENT_ERRORS env var (1/true/yes/on vs 0/false/no/off/empty) agent / human
4 Any of CLAUDECODE, CLAUDE_CODE, CLAUDE_CODE_ENTRYPOINT, CODEX, CODEX_CLI, CURSOR, CURSOR_SESSION_ID, OPENCODE, AGENT set and non-empty agent
5 tty_heuristic=True and stderr is not a TTY agent
6 default human

The sentinel flags are consumed by the wrapper before Typer parses anything, so they work even when the rest of the command line is broken. They do not appear in --help.

Format

Markdown (default) is written for a model to read: stable first line ✗ Usage error in \`: …, fixed section order, no ANSI. JSON is for harnesses that parse stderr and retry automatically: select it with AgentErrorsConfig(format="json")orAGENT_ERRORS_FORMAT=json`. The JSON document is the only thing written to the stream. See SCHEMA.md.

For agent-harness authors: grep the first line for ✗ Usage error, or set AGENT_ERRORS_FORMAT=json and json.loads(stderr).

Configuration

from typer_agentic import AgentErrorsConfig

main = agent_errors(
    app,
    config=AgentErrorsConfig(
        mode="auto",  # "agent" | "human" to force
        format="markdown",  # or "json"
        stream="stderr",  # or "stdout"
        env_var="AGENT_ERRORS",
        format_env_var="AGENT_ERRORS_FORMAT",
        flag="--agent-errors",  # None disables
        human_flag="--human-errors",  # None disables
        skill_flag="--agent-skill",  # None disables
        max_suggestions=3,
        include_hidden=False,  # list hidden params too
        tty_heuristic=False,
        agent_detect_env_vars=(...),  # see table above
        intercept_click_exceptions=False,
        repeat_detection=False,  # see below
        repeat_state_dir=None,  # defaults to $TMPDIR
    ),
)

SKILL.md for your CLI

Errors are the reactive channel. myapp --agent-skill prints an Agent Skill describing every visible command, argument, option and one example per command, so the agent has the inventory before it guesses:

myapp --agent-skill > .claude/skills/myapp/SKILL.md

render_skill(app) returns the same text as a string. The library never writes files itself. Every command keeps its arguments, options and example regardless of size; above 10 commands only the first line of each command's help is kept.

Repeat-failure escalation (opt-in)

Each CLI run is a fresh process, so "the agent is looping" needs a little state. With repeat_detection=True the wrapper writes a small JSON record ($TMPDIR/typer-agentic-<uid>/<prog>.json, 10-minute TTL, atomic replace) and on the second identical failure adds: stop retrying variations, read --help, rebuild from the example. On the third it adds: if that does not resolve it, report the exact error to the user instead of working around it. Any I/O problem silently disables the feature.

The copy

All agent-facing text lives in typer_agentic/wording.py. If you customise it, keep the rules the defaults follow: one sentence classifying the failure as a recoverable input mistake; one sentence forbidding the panic behaviours (switching tools, editing state around the CLI, inventing flags); exactly one next action; calm, imperative, no exclamation marks, no apologies, no "please"; identical wording across error types.

Compatibility

  • Python 3.11+, typer>=0.24, no other runtime dependency. External click is imported only when Typer does not vendor Click (< 0.26) or when something else in the process has already imported it; a vendored-Click app never pays for it.
  • Typer 0.26+ bundles its own Click under typer._click; its exception classes are unrelated to click.exceptions. typer_agentic.compat resolves whichever hierarchies are present and catches all of them.
  • If resolution fails on some future Typer, agent_errors(app) becomes a transparent passthrough and emits one RuntimeWarning per process (only in agent mode). Your CLI keeps working; only the feature degrades.
  • Agent mode drives Click's make_context / invoke loop directly (not main(standalone_mode=False), whose return value cannot distinguish typer.Exit(n) from a command returning n), so exit codes match stock Typer: Exit(n)n, normal return → 0, Abort → 1, Ctrl-C → 130. Shell completion is delegated to Typer untouched.
  • Not intercepted, by design: runtime exceptions inside command bodies (they propagate with Typer's pretty-exception hook applied), NoArgsIsHelpError (help is printed as usual), --help / --version / completion.
  • The built-in --help, --install-completion and --show-completion options are omitted from the inventory.

The test suite runs against Typer 0.25 (external Click) and the current release: uv run poe test-compat.

Development

uv sync
uv run poe setup      # install git hooks
uv run poe check      # lint, typecheck, dead code, deps, clones, tests
uv run poe fix        # auto-format + fix lint
uv run poe test       # tests with coverage
uv run poe test-compat

Golden files under tests/golden/ are regenerated with UPDATE_GOLDEN=1 uv run pytest.

Release: uv run poe release (or level=minor uv run poe release) bumps the version, tags, and pushes. The tag triggers the PyPI publish workflow.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

typer_agentic-0.1.4.tar.gz (92.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

typer_agentic-0.1.4-py3-none-any.whl (29.8 kB view details)

Uploaded Python 3

File details

Details for the file typer_agentic-0.1.4.tar.gz.

File metadata

  • Download URL: typer_agentic-0.1.4.tar.gz
  • Upload date:
  • Size: 92.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for typer_agentic-0.1.4.tar.gz
Algorithm Hash digest
SHA256 6f3ea6170c65889b7aca0950a9c9749bb28e164c188ec63221362db71a9fb700
MD5 6e0d04d65a94dcb6b516f68d373c086f
BLAKE2b-256 670fe49c77c1fbe72326fba261d9d85c08b120020aa91ec9db187d3eeaa28084

See more details on using hashes here.

Provenance

The following attestation bundles were made for typer_agentic-0.1.4.tar.gz:

Publisher: release.yml on mojzis/typer-agentic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file typer_agentic-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: typer_agentic-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 29.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for typer_agentic-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 96338f525b27ba9fde64c9aca97d8cabcbbb202c85d885f2f7911b0763c70109
MD5 69318612fbf21415561f5b905cf5ec4f
BLAKE2b-256 88a41a20ff30f0a0e7f7246810a727fe2f88d3cc1bd0f89ebbad7fb10f326812

See more details on using hashes here.

Provenance

The following attestation bundles were made for typer_agentic-0.1.4-py3-none-any.whl:

Publisher: release.yml on mojzis/typer-agentic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.4 This release

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

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