Build your own CLI.
The way Tyler Fisk builds them: capture the real docs, plan before any code, bring it up to a standard, wrap it in two skills, and prove it against the connector or MCP it replaces. Start with a safe practice run if you like, then build one for a service you actually use.
Before this: Decide: Connector, MCP or CLI. Next: Put Your CLI to Work. Each part works on its own.
A CLI is a tool you run by typing a command. Your agent is very good at running them. When you have decided a service needs one, because its connector or MCP can't do the one thing you need, this blueprint has your agent build it. First it saves the service's docs to your computer and finds out what others have already learned. Then it reads a CLI that already works, plans the commands with you, and writes no code until you say yes. It builds the tool, checks it against a set of rules, adds two skills, and proves it works twice in a row and does everything the MCP did, plus the gap.
A small tool your agent can run for one service you use. It shows you exactly what it would do before it changes anything. You also get two shortcuts (skills) for jobs you repeat, and a saved copy of the service's instructions.
When you can build one CLI, no service is out of your agent's reach, and the tool does exactly what you need, with limits you set.
Tyler Fisk's five-step build path, in seven checkpoints.
You name the service, agree the plan before any code is written, store any key in Infisical yourself, and say yes at each checkpoint.
Already decided?
The real build starts after the decision; the practice run does not need one. If you have not decided yet that your service needs a CLI, start with part 1, Decide: Connector, MCP or CLI.
The decision in one paragraph: use the service's connector or MCP when it does your real tasks. Borrow a CLI when someone already shipped a good one; the Lab vault has four: n8n CLI Toolkit, Slack CLI Toolkit, Zoom Automation Hub and gws CLI Connect. Build your own when you can name the specific thing the connector or MCP can't do, when you need more than one account on the same service, or when you want it to run in a script or on a schedule with no model in the loop. Skip it when you would use it once a month.
Tyler Fisk's five-step build path
The blueprint walks it in seven checkpoints.
- 1. Don't build if you don't need to. That is part 1. Here your agent only checks the decision is made and writes down the gap.
- 2. Get the base CLI. Capture the docs, research how others already connect agents to this service, and check your own notes, with three sub-agents at once. Read a working CLI as the template. Plan with you, then build the core.
- 3. Bring it up to standard. The design rules: JSON output, a schema command, dry runs, keys only through Infisical, hard limits on anything that could do damage, and the searchable method list.
- 4. Wrap it in two skills. In your workbench's skills folders. Part 3 covers the rest.
- 5. Ship and prove it. It works twice in a row, and it does everything the connector or MCP does, plus the gap. Keep the MCP as a fallback for a week.
Your first build
This one teaches the whole process with nothing at risk: free, no key, read-only. Your agent builds weather-cli on Open-Meteo, a free weather API, with all five steps. It saves the three pages of Open-Meteo's docs with your app's own web fetch, so you need no account. Open-Meteo is free for personal use. Business use needs their paid plan. Your agent checks the terms again before it builds.
Then the real build. The same five steps on a service you actually use: the one you decided on in part 1. Two things change. It probably needs a key, so you store the key in Infisical and your agent runs the CLI through infisical run. And it can probably send or change things, so writes come last, behind --dry-run, and the first real write goes to a test account, channel or record.
Already know the service you want? Skip the practice run and go straight to it.
Get the base CLI
Your agent builds from the real reference, not from memory. It runs three research sub-agents at the same time:
- The docs. It captures the API reference and saves it in
work/build-your-own-cli/docs/, one markdown file per group of methods, with the parameters, scopes, rate limits and an example response for each. - How others do it. It searches the web for how people already connect agents to this service, and the limits they ran into.
- Your own notes. It searches your own library in the workbench for anything you saved on this service.
For the practice run, your app's own web fetch saves the three pages, with no account and no key. For your own service, capture the docs in this order:
- Firecrawl, the default. A free account at firecrawl.dev: as read 10-17-2026, 1,000 credits a month, no card, one credit for each page it scrapes. You put the key in Infisical yourself, and your agent runs the Firecrawl CLI through
infisical run, or calls the Firecrawl API from a short script. It tells you the page count before it scrapes, and asks before it installs the CLI. - The crawler from the Research to Cairns card, if you set that up.
crawl_public_site.py: free, reads a small public site from its sitemap, obeys robots.txt, 50 pages by default and 250 at most, no JavaScript and no sign-ins. - Your app's own web fetch, as a last resort, one page at a time.
# list the docs pages, then scrape one into the docs folder infisical run -- firecrawl map https://docs.example.com infisical run -- firecrawl scrape https://docs.example.com/api/messages -o work/build-your-own-cli/docs/example-api/raw/messages.md
The template first. Before it designs anything, your agent reads a CLI that already works, read only. The template with real code is lab/blueprints/zoom-automation-hub/zoom-cli.py, from the Zoom Automation Hub. The n8n CLI Toolkit and gws CLI Connect drops hold setup instructions, not code, so it reads them for how the commands are named and grouped. It never edits anything inside lab/. The new CLI follows a shape that already works.
Your agent comes back with its understanding of what you are building, a gap analysis against the connector or MCP it replaces, and a proposed command set, each command marked read or write. It also says what happens when you ask for something no command covers. Then it waits for your yes. Only then does it build the core, read commands first, in one file with no packages.
Bring it up to standard
The rules come with the blueprint in design-rules.md. Your agent walks them one at a time and shows you proof from a real run for each.
- JSON output, short by default. The fields your agent needs almost every time, and
--fullfor the whole response when it is needed. - A schema command.
schema <command>says what any command takes, so your agent asks the tool instead of guessing. --dry-runon anything that writes. It prints the exact request and sends nothing. The real run waits for your yes.- Shortcut commands and verb-noun names. A
+command for a routine you run every week, and one naming pattern (places search,forecast get) the whole way. - Keys only from environment variables, through Infisical. Never a
--keyoption: a key typed as an option lands in the chat, the history and the logs. - Hard-scope anything destructive or client-facing. Put the limit in the CLI itself, scoped to exactly what it should do: post only to the channels on its list, create email drafts with no send command, delete one record by its id.
- A searchable method list.
methods searchfinds the right entry in the saved docs andmethods getreads it, so your agent builds a call from the real reference for everything you never wrote a skill for.
python3 work/build-your-own-cli/weather_cli.py places search "Austin" --count 3 python3 work/build-your-own-cli/weather_cli.py forecast get --place "Austin" python3 work/build-your-own-cli/weather_cli.py forecast get --place "Austin" --full # prints the address it would call, sends nothing python3 work/build-your-own-cli/weather_cli.py forecast get --lat 52.52 --lon 13.41 --dry-run # what the command takes python3 work/build-your-own-cli/weather_cli.py schema forecast get # build the method list from the saved docs python3 work/build-your-own-cli/weather_cli.py methods rebuild python3 work/build-your-own-cli/weather_cli.py methods search wind python3 work/build-your-own-cli/weather_cli.py methods get precipitation_probability
Run from the root of your workbench. On Windows it may be python instead of python3; in Node, node work/build-your-own-cli/weather-cli.mjs.
Two skills, then prove it
Two skills. Your agent drafts two workflows you would replay (for the practice run, weather-today and weather-compare) from the skill template, shows you the drafts, and says where it will save them before it does: your workbench's .claude/skills/ for Claude Code and .agents/skills/ for Codex. Skills that call other skills, skills that write new skills, more than one account and keeping it all current are part 3, Put Your CLI to Work.
Ship and prove it. Three checks before you call it done:
- It works twice in a row. One whole workflow, end to end, then again with different input. On a service that writes, both test runs are dry runs, or use the test record. One working run is a demo, not a tool.
- It beats what it replaces. Your three real tasks, through the connector or MCP and through the CLI, side by side. It passes when it does everything the MCP does, plus the gap.
- The MCP stays on for a week. The skills use the CLI first and the MCP only if the CLI fails. After a clean week, you decide whether to turn the MCP off.
If nothing reached the service before, the test is your three tasks done by hand: the CLI passes when it gets the same result you do, and there is no fallback week.
Services change their APIs. Part 3 turns capturing the docs again into an ask you run when the service changes.
Want it in every project?
Your skills live in your workbench, with the CLI they call, and stay out of the menu in every other project. If you want one everywhere on this computer, copy its folder to your app's own skills folder: ~/.claude/skills/ for Claude Code, ~/.agents/skills/ for Codex. Your agent asks before it writes there.
# Mac cp -R .claude/skills/weather-today ~/.claude/skills/ # Windows (PowerShell) Copy-Item -Recurse .claude\skills\weather-today $HOME\.claude\skills\
The trade-off: every project sees it, so it shows in every menu and can be picked where you did not mean it. Change the CLI's path in the skill to the full path first, or it breaks in other projects. If the CLI needs a key, a project outside the workbench needs its own infisical init. And keep one copy of each name: Codex shows both if the same skill is in two places.
What you can ask your agent, from now on
Five asks that work once you have built one.
Capture the [service] API docs into work/build-your-own-cli/docs/, one markdown file per group of methods, with parameters, scopes, rate limits and an example response. Use Firecrawl through infisical run, and tell me the page count before you scrape.
Read a working CLI as your template, then come back with your understanding, a gap analysis against the [service] connector or MCP, a proposed command set, and what happens when I ask for something no command covers. Don't write code yet.
I want my CLI to [do this]. Search the method list first, propose the command and its options, and wait for my yes before you write any code. JSON output, and a dry run and a hard scope if it writes.
Check my CLI against design-rules.md, one rule at a time. For each rule, show me proof from a real run, or tell me what is missing.
Run my three real tasks through the [service] connector or MCP and through my CLI, and show me a side-by-side table. Tell me anything the MCP does that the CLI can't yet.
Words you now own
- CLI. A tool you run by typing a command. Short for command-line interface. Your agent runs it for you.
- MCP. A standard way to plug a service's tools into your agent. A connector in the Claude apps is one.
- API. The service's own set of requests a program can send it. A CLI wraps the parts you need.
- Gap analysis. What the connector or MCP can do, next to what the API can do. The difference is what you build.
- Sub-agent. A second agent your agent starts for one job, so several jobs run at the same time.
- JSON. Text in a fixed shape of names and values. Easy for your agent to read without guessing.
- Dry run. A run that prints exactly what it would send, and sends nothing.
- Hard scope. A limit written into the CLI itself, so it can't do what it was not built to do.
- Method list. Every method in the saved docs, searchable with
methods searchand readable withmethods get. - Skill. A short instruction file your agent reads when a request matches it. A workflow you would replay, written down once.
- Environment variable. A value handed to one command when it runs, outside any file. Where a CLI reads its key.
Before you point it at a real account
The weather CLI can't send or change anything. Your own one probably can. Four habits before it touches anything real.
- Read-only commands first. Prove the reads before any command that sends, changes or deletes gets built.
--dry-runbefore every write, and the real run only on your yes. The first real write goes to a test account, channel or record.- Safe to run twice. Agents retry. A create checks whether the thing already exists; a delete of something already gone just says so.
- Read the API's terms. Commercial use, rate limits, what you must credit. Your agent reads them and gives you the date it read them.
Keep the key in Infisical. Do Keys, the First Time first, then store the key in Infisical yourself and run infisical init once at the root of your workbench. Your agent runs your CLI through infisical run, and the key reaches that one command and nothing else: not the chat, not a file, not your shell history.
infisical run -- python3 work/build-your-own-cli/myservice_cli.py items list
You put the key into Infisical yourself, and you do any browser sign-in yourself. If an agent ever asks you to paste a key in, offers to write one into a file, or types one as an option, the answer is no.
Fair questions
No. You agree the plan, say yes at each checkpoint and read the proof. Your agent writes the code, and shows you each command working before it moves on.
Not for the practice run: your app's own web fetch saves those three pages. For your own service, Firecrawl is the default because it reads big docs sites well, and the free account covers a first CLI. For a small public site, the Research to Cairns crawler (if you set that up) or your app's own web fetch also work.
Not on Open-Meteo's free plan, which is for non-commercial use only. Its paid plans come with a key; the CLI would then read that key from an environment variable through Infisical, like any other.
So both apps see them (Claude Code reads .claude/skills/, Codex reads .agents/skills/), they sit with the CLI they call, and they stay out of the menu in every other project. To have one everywhere, see "Want it in every project?" above.