Skip to content
Resource library
GOCUX / Articlescli

Wrapping a command-line tool as a safe, reusable agent skill

A step-by-step method for packaging an existing CLI as an agent skill: a description that loads at the right time, clear inputs, safe defaults and tests.

Most teams already own the tools an agent would need: a deploy script, a database query utility, a cloud provider's CLI, an internal tool that pulls invoices. An agent with shell access can call any of them, but a bare shell gives it too much power and too little guidance. It has to guess flags, it parses output written for humans, and nothing stops it from running the destructive subcommand that sits next to the harmless one. Wrapping the CLI as a skill fixes that. This guide walks through doing it for one tool, from deciding what to expose to testing the result before anyone relies on it.

What a skill adds on top of a CLI

A command-line tool already has an interface. A skill adds the knowledge a careful colleague would bring: when this tool is the right choice, which command answers which question, which flags always belong, what the output means and what to do when something fails. In the common SKILL.md format, that knowledge lives in a folder: a short description the agent sees up front, instructions it loads only when they are relevant, and optional helper scripts. What agent skills are explains the format itself; this page is about the wrapping.

Not every CLI is a good candidate. Look for these properties before you start:

  • A non-interactive mode, with no prompts waiting for a keypress.
  • Machine-readable output, such as a --json or --format flag.
  • Meaningful exit codes, so success and failure can be told apart without reading prose.
  • Read commands that are safe to repeat.

Full-screen interactive tools, commands that open an editor, and tools whose default action is destructive are poor fits unless you put a wrapper script in front of them.

Step 1: map the command surface

List the subcommands and sort each one into read, write or destructive. Here is the map for a hypothetical internal billing tool called invoicectl:

CommandClassExpose in the first version?
invoicectl listReadYes
invoicectl show <id>ReadYes
invoicectl exportRead, but data leaves the systemNo; add later behind an approval
invoicectl send <id>Write, with an external effectNo
invoicectl void <id>DestructiveNo

The first version exposes reads only. That is not timidity. It lets you learn how the agent really uses the tool before anything it does can reach a customer or erase a record.

Step 2: write the description first

The description decides when the skill loads, so it deserves more care than its length suggests. State what the tool does, which questions it answers and, just as important, when not to use it. Use the words people actually type.

---
name: invoice-lookup
description: Look up invoices in the internal billing system with the
  invoicectl CLI (read-only). Use for questions about an invoice's status,
  amount, due date or customer, or to list invoices by customer or period.
  Do not use for sending, voiding or exporting invoices.
---

# Invoice lookup

Always pass --json and --no-color. Never run send, void or export.

## Find invoices
invoicectl list --customer "<name>" --status open --limit 50 --json

## Show one invoice
invoicectl show <invoice-id> --json

## Reading results
- "status" is one of: draft, open, paid, void
- An empty list means no match, not an error. Say so plainly.
- Exit code 3 means not authenticated: stop and report it, do not retry.

Keep the body short and specific. Long background material belongs in a separate reference file that the agent opens only when it needs it.

Step 3: pin down inputs and outputs

Agents improvise flags when instructions are vague. Leave no room for that.

  • Name the required inputs and their format: what an invoice ID looks like, how a period is written.
  • Fix the flags that must always be present: structured output, no colour, no pager, non-interactive.
  • Bound the output. A command that can return thousands of rows will flood the agent's context. Default to a limit and explain how to page through the rest.
  • Explain how to read failures. Map exit codes and common error messages to an action: retry, ask the user, or stop.
  • Quote values that came from outside. Anything supplied by a person or found in a document goes into an argument, never into a string the shell will interpret.

If the raw CLI makes this awkward, add a thin wrapper script to the skill folder. The wrapper validates arguments, adds the fixed flags, trims long output and returns a clean error. The skill then tells the agent to call the wrapper instead of the CLI.

Step 4: make the safe path the default

Instructions guide; they do not enforce. A sentence saying "never run void" will usually be followed, and usually is not the same as always. Put the hard limits where the agent cannot argue its way around them.

  • Use a read-only credential for the first version, so a write command fails at the service even if the agent attempts it.
  • Allowlist subcommands in the wrapper and refuse everything else with a clear message.
  • Prefer dry runs once you add writes: preview first, apply only after a decision.
  • Keep secrets out of the skill. Credentials come from the environment or a secret store, never from SKILL.md or a committed config file.
  • Set timeouts so a hung command cannot stall the whole run.

When the read-only version has earned trust, add write commands one at a time, each behind an explicit confirmation step. Start agents read-only describes that progression.

Step 5: test the skill, not just the tool

The CLI already works. What you are testing is whether the agent uses it correctly, and three small test sets go a long way.

  1. Loading tests. A handful of prompts that should trigger the skill ("is invoice 1042 paid?") and a handful that should not ("draft a reminder email to this customer"). Check that the skill loads for the first group only.
  2. Invocation tests. For each read question, record the command the agent ran and compare it with the one you expected. Missing flags, wrong filters and unbounded queries show up quickly.
  3. Failure tests. Expired credentials, an ID that does not exist, an empty result, an unreachable service, and a request to do something the skill forbids. The right outcome is a clear report or a refusal, not a retry loop or an invented answer.

Keep these prompts in the repository next to the skill and rerun them whenever the description, the wrapper or the CLI version changes. A refusal that names its reason is a correct result, as a refusal is a result argues.

Where permissions actually live

A skill tells an agent how to use a tool. It does not, and should not, decide whether a particular piece of work is allowed to use it. That decision belongs to the environment the agent runs in: which credentials it holds, which actions pause for a person, what gets recorded.

GoCux keeps those two things apart. A reusable instruction never counts as a grant of permission, so writing or installing a skill does not widen what any task may do. A work order states the goal, the scope and the acceptance criteria, GoCux picks the skills the work requires, and consequential actions such as sending things out, deleting or exporting data still stop until a teammate decides. The customer CLI keeps ownership of its local tools and permissions. The agent skills documentation describes how skills fit into that model.

Checklist before you share the skill

  • The description says what the tool is for, which questions it answers and when not to use it.
  • Every exposed command is classified, and the first version exposes reads only.
  • Fixed flags, output limits and failure handling are written down or enforced by a wrapper.
  • The credential is read-only, and no secret appears anywhere in the skill folder.
  • Subcommands outside the allowlist are refused with a clear message.
  • Loading, invocation and failure tests exist and pass.
  • Write commands, once added, need an explicit decision before they run.
  • You know when a skill, an MCP server or a plain CLI call is the better fit; see MCP, skills or CLI tools.

Bring this workflow into your workspace.

Set the scope. Review the evidence. Approve the steps that need it.

Open the workspace

Keep exploring