Skip to main content

DuckTap — a CLI factory for AI agents. Print agent-native CLIs + MCP servers + skills from any API or website.

Project description

DuckTap

Tape any API to your agent in one command. DuckTap is a CLI factory for AI agents. Point it at an OpenAPI spec, a HAR file, or a plain website, and it prints a Python CLI, an MCP server, and a Claude/Cursor/Codex skill -- wired up, cached, scored, ready to ship.

Website: ducktap-website.vercel.app

CI Release PyPI License: MIT Python 3.11+

DuckTap is inspired by Printing Press by @mvanhorn -- same north star (muscle memory for agents) -- rebuilt in Python with multi-LLM support, a web dashboard, Playwright-powered browser sniffing, and a real plugin system.

DuckTap local dashboard

$ ducktap press tests/fixtures/petstore.yaml --out ./out --name petstore
Pressed petstore (19 operations) -> out
  python-cli: 10 files
  mcp-server: 5 files
  skill:      3 files

Scorecard: 92/100 (A)
  - coverage:      95  -- 19 operations exposed
  - documentation: 100 -- 19/19 operations have docs
  - auth:          100 -- 2 auth scheme(s)
  - typed_params:  54  -- 29/53 params typed/enum
  - artifacts:     100 -- 3/3 expected artifact dirs present
  - naming:        100 -- 19/19 unique operation ids

Why a CLI factory?

In a world of AI agents, a well-designed CLI is muscle memory. No hunting through docs, no wrong turns, no wasted tokens. DuckTap reads the spec, sniffs the traffic when no spec exists, and prints:

  • A Python CLI (<api>-dt-cli) -- Click-based, auth from env vars, JSON by default, pretty mode for humans, local SQLite mirror with FTS5 full-text search, compound query commands (stale, health, bottleneck), retries on transient errors.
  • TypeScript CLI (<api>-dt-ts) -- oclif-based for Node.js teams.
  • Go CLI (<api>-dt-go) -- cobra-based, single binary.
  • Rust CLI (<api>-dt-rs) -- clap-based, single binary distribution.
  • An MCP server (<api>-dt-mcp) -- every operation exposed as an MCP tool, stdio transport, drop into Claude Desktop or Cursor in 60 seconds.
  • A skill for Claude Code, Cursor (.mdc), and a generic tools.json -- so any agent harness can pick up where the others left off.
  • A scorecard grading coverage, docs, auth clarity, typed params, artifacts, and naming.

Install

pip install ducktap
ducktap --version

For browser sniffing (optional):

pip install "ducktap[sniff]"
playwright install chromium

Requires Python 3.11+.

Developer install (contributing to DuckTap itself)
git clone https://github.com/zanni098/DuckTap
cd DuckTap
pip install -e ".[dev]"
python -m pytest tests/ -q   # 85+ passed

Quick start

# 1. Press a built-in catalog entry (no URL needed)
ducktap catalog list                  # browse 30+ built-in APIs
ducktap catalog print stripe          # press Stripe CLI + MCP + skill

# 2. From any OpenAPI spec URL
ducktap press https://petstore3.swagger.io/api/v3/openapi.yaml

# 3. From a local spec or HAR file
ducktap press ./openapi.yaml --name myapi
ducktap press ./traffic.har  --name myapi

# 4. From a website with no public spec (needs [sniff] extra)
ducktap sniff https://example.com

# 5. Open the dashboard
ducktap ui    # http://127.0.0.1:8765

Running ducktap press prints something like:

Pressed petstore (19 operations) -> ./out
  python-cli: 10 files
  mcp-server:  5 files
  skill:       3 files

Scorecard: 92/100 (A)
  - coverage:      95  -- 19 operations exposed
  - documentation: 100 -- 19/19 operations have docs
  - auth:          100 -- 2 auth scheme(s)
  - typed_params:   54 -- 29/53 params typed/enum
  - artifacts:     100 -- 3/3 expected artifact dirs present
  - naming:        100 -- 19/19 unique operation ids

What you get under ./out/:

out/
├── petstore-dt-cli/        # pip install -e .  →  petstore-dt-cli --help
│   ├── pyproject.toml
│   ├── README.md
│   ├── petstore_dt_cli/
│   │   ├── main.py
│   │   ├── commands.py     # one click subcommand per API operation
│   │   ├── client.py       # httpx + env-var auth + retries
│   │   └── mirror.py       # local SQLite cache
│   └── tests/test_smoke.py
├── petstore-dt-mcp/        # pip install -e .  →  add to Claude Desktop config
│   └── petstore_dt_mcp/server.py
└── skills/ducktap-petstore/
    ├── SKILL.md            # Claude Code skill
    ├── ducktap-petstore.mdc  # Cursor rule
    └── tools.json          # generic agent tool definitions

How DuckTap improves on Printing Press

Printing Press DuckTap
Language Go Python -- easier to extend, richer LLM ecosystem
LLM Claude only Multi-LLM via LiteLLM (Anthropic, OpenAI, Gemini, Ollama, Groq, Azure)
Skills Claude Code Claude Code + Cursor .mdc + generic tools.json
UI None Local FastAPI dashboard (ducktap ui)
Plugins Source fork Entry-point plugin system -- drop-in discoverers & generators
Browser sniff Custom Go browser Playwright -- full HAR export, scriptable actions
Generated CLI runtime Single Go binary Python (pip-installable, hackable, single-file editable)

See docs/COMPARISON.md for the full feature matrix.

Commands

ducktap press <source>          # discover + generate (the default loop)
ducktap research <source>       # discover only -- emit normalized APISpec JSON
ducktap sniff <url>             # browser-sniff a site (needs [sniff] extra)
ducktap scorecard <source>      # quality scorecard
ducktap shipcheck <name>        # structural & runtime sanity checks
ducktap catalog list|print      # browse the recipe library
ducktap plugins list            # show installed discoverers + generators
ducktap ui                      # local web dashboard

Plugins

Add a discoverer or generator without forking. Register via Python entry points:

# your_plugin/pyproject.toml
[project.entry-points."ducktap.plugins"]
mything = "your_plugin.module"   # module just calls plugins.register_discoverer(...)

See docs/PLUGINS.md and the sample at src/ducktap/plugins/builtin/graphql_intro.py.

Architecture

input (URL | spec | HAR)
        │
        ▼
  ┌─────────────┐
  │  Discovery  │   openapi / har / browser-sniff / graphql (plugin) / ...
  └──────┬──────┘
         ▼
   APISpec (Pydantic) ──── intermediate normalized representation
         │
         ▼
  ┌─────────────┐
  │  Generator  │   python-cli / mcp-server / skill / ...
  └──────┬──────┘
         ▼
  artifacts/       (CLI pkg + MCP pkg + SKILL.md + cursor.mdc + tools.json)
         │
         ▼
  ┌─────────────┐
  │   Verify    │   scorecard + shipcheck + (optional) live smoke test
  └─────────────┘

See docs/ARCHITECTURE.md.

Roadmap

See docs/ROADMAP.md. Highlights for v0.4+:

  • Compound command macros -- YAML recipes that chain API calls with step references
  • FTS5 full-text search over saved JSON responses in the local data lake
  • DuckDB backend as an alternative to SQLite for analytical workloads
  • Top-level query command for SQL over the mirror
  • CLI publish to PyPI + GitHub in one command

License

MIT -- see LICENSE.

Acknowledgements

Inspired by Printing Press by Matt Van Horn and the agent-CLI playbook proved out by discrawl and gogcli.

Project details


Download files

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

Source Distribution

ducktap-0.6.0.tar.gz (416.5 kB view details)

Uploaded Source

Built Distribution

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

ducktap-0.6.0-py3-none-any.whl (94.9 kB view details)

Uploaded Python 3

File details

Details for the file ducktap-0.6.0.tar.gz.

File metadata

  • Download URL: ducktap-0.6.0.tar.gz
  • Upload date:
  • Size: 416.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ducktap-0.6.0.tar.gz
Algorithm Hash digest
SHA256 74d3c30935aafb7a6d32cf454bd393aae36f90bf79d9a33a39816792ffaf15dc
MD5 0cd69e796db865194070e1f6b0bd4b09
BLAKE2b-256 a35da367389570a3fd7f7b4ab60018509af341a4f5a9cf93b2ae2f478f91ec3e

See more details on using hashes here.

Provenance

The following attestation bundles were made for ducktap-0.6.0.tar.gz:

Publisher: publish.yml on zanni098/DuckTap

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

File details

Details for the file ducktap-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: ducktap-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 94.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ducktap-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 419fe6b8e26c640574f73d7f1937e06ddc95703e1f4e0d16e1f7d97a90ee6a96
MD5 d3982d9c347db01df1c9093cb9da772b
BLAKE2b-256 0c9da3b49c7f604143ea6179ffeea00b0206088b576927223931a825fbcb2bce

See more details on using hashes here.

Provenance

The following attestation bundles were made for ducktap-0.6.0-py3-none-any.whl:

Publisher: publish.yml on zanni098/DuckTap

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

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page