Using extensions
Extensions adapt agents-cli to a workflow it doesn't ship with, such as a different agent framework, an org's deploy policy, or a command of your own, without forking the tool.
What an extension can do#
- Override a built-in command. Replace what
create,run,deploy, oreval generatedoes. Your command-line arguments pass straight through to the replacement, so the command still feels native. - Add a new command. Expose a workflow the tool doesn't have as
agents-cli <your-command>. - Ship coding-agent skills. Skills the extension declares are copied into
.agents/skills/when you add it, so your coding agent knows how to use the extension.
An extension adds skills but can't change existing ones. Skill names starting with google-agents-cli- are reserved for the skills agents-cli setup installs, and extension add stops if a skill folder with the same name exists that this extension didn't install.
No extension can override info, login, setup, update, install, or the extension commands. They always run the built-in, so you can inspect, set up, or repair agents-cli in a repo you don't trust yet, and remove a broken extension.
A few things extensions make possible:
- Swap the agent framework. Run the lifecycle (
run,eval,deploy) on LangChain or the Claude Agent SDK instead of ADK by scaffolding from a framework template that carries its own extension. See First-party frameworks. - Wrap a command with policy. Run a compliance or SBOM check before the built-in
deploy. - Standardize a team workflow. Commit an
agents-cli-extension.yamlso everyone, including CI, gets the same overrides.
How extensions work#
An extension contributes two things:
- Command overrides: the extension maps a command name to a
run:command vector, a list such as["uv", "run", "scripts/custom_deploy.py"]. When you invoke the command,agents-cliruns that vector (no shell) with your arguments appended. - Skills: directories with a
SKILL.md. Theextension addcommand copies them into the skills folder:<project>/.agents/skills/at project scope, or~/.agents/skills/with--global.- A skill folder that an extension copied belongs to the extension. The
extension add,extension update, andagents-cli installcommands replace the whole folder, so your own files there are lost. To change a skill, copy its folder under a new name. The copy is yours:agents-clinever replaces or deletes it. - Many coding agents read the project folder, for example Gemini CLI, Antigravity, Codex, and Cursor. Fewer read
~/.agents/skills/. Claude Code reads.claude/skills/instead, so link or copy the skill there yourself. - For Antigravity,
agents-clilinks each--globalskill into its global skills folder. - If your home folder is a project, both scopes share
~/.agents/skills/, so an extension with skills can be installed at only one of them.
- A skill folder that an extension copied belongs to the extension. The
Extensions come from these places: any org/repo on GitHub, a URL on any git host, a local path, a first-party shorthand name, or an agents-cli-extension.yaml committed at your project root (auto-loaded, no install step). A framework template ships that last kind, so scaffolding from one needs no install. A template ships its skills as files under .agents/skills/, and scaffolding copies them like any other file. Only extension add, extension update, and agents-cli install read the skills: field.
Adopt an extension#
agents-cli extension add <ref> [--global] [--ref <branch|tag|sha|:latest>] [--yes]
agents-cli extension list # active extensions, their scope, and the commands they contribute
agents-cli extension update [<name>] [--to <branch|tag|sha|:latest>] # advance or move the pin and replace its skills
agents-cli extension remove <name> [--global] # drop it, its vendored copy, and skills no other scope uses
agents-cli info # active extensions, their sources, and any conflicts
An overridden or added command is tagged in agents-cli --help with [↑ <extension>], and agents-cli <command> --help shows its source, scope, and the run: vector it executes.
Reference forms#
| Form | Meaning |
|---|---|
acme/acli-extensions | any org/repo on GitHub |
acme/acli-extensions#soc2-deploy | select one extension from a multi-extension repo |
https://git.example.com/acme/acli-extensions | any git host, over https://, http://, or ssh:// |
git@git.example.com:acme/acli-extensions | the same host, in scp form |
local@../my-extension | a local path (for development) |
<name> | first-party shorthand that pins the latest release tag of the google/agents-cli repo that isn't newer than your agents-cli (for example v1.12.0) |
--ref <branch|tag|sha> | pin a branch, tag, or commit SHA |
--ref :latest | pin the latest release, as the shorthand does without --ref (first-party only) |
Agents CLI clones a URL with your existing git configuration, so whatever already authenticates you to that host (a credential helper or an SSH agent) applies. Agents CLI doesn't ask for or store credentials.
Scopes#
- Project (default): recorded in this repo's
agents-cli-extensions.yaml, with the working copy vendored underextensions/. It affects only this project, and committing both means teammates and CI get the same overrides. - User (
--global): stored in~/.config/agents-cli/(%APPDATA%\agents-clion Windows). Applies to every project on the machine, and works before a project exists, so you can use it to bootstrap an override.
When both scopes define the same command, project wins; agents-cli info shows the source.
Prefer project scope
A global extension changes commands across every project on the machine. Reach for --global only when you need it before a project exists (framework bootstrap) or want it machine-wide.
Trust#
Extensions from google/agents-cli, google/agents-cli-extensions and google/adk-recipes are verified and trusted automatically, whether you add them with the shorthand form (agents-cli extension add <name>), an org/repo reference, or an https or ssh URL. Every other reference prompts before install, since its commands run arbitrary code when invoked. The --yes flag skips the prompt and trusts every extension, so use it only for automation and bootstrap.
Pin and update extensions#
Extensions pin to an exact commit, like a lockfile:
extension addresolves the ref to a commit SHA, recordssource/ref/shaunderextensions:inagents-cli-extensions.yaml, vendors a working copy underextensions/, and copies the extension's skills into the skills folder.- Each copied skill folder gets a
.agents-cli-extensionmarker file that holds the extension name and the skill name. A skill folder without this file, or copied under a new folder name, is yours. A folder whose file names another extension belongs to that extension. Neither is overwritten. Don't delete the marker: without it,agents-clitreats the folder as yours and no longer replaces or removes it. - If a skill folder is yours or another extension's,
extension addstops with an error, changes no skill, and records nothing. - While it copies or deletes skills,
agents-cliuses hidden folders named.<name>.incomingand.<name>.outgoingin the skills folder. Don't keep your own files under these names, because they can be overwritten.
- Each copied skill folder gets a
agents-cli installre-materializes any missing or stale vendored copy from the pinned SHA, so CI and fresh checkouts get the exact reviewed code, and commands and overrides work immediately. It never advances a pin.- It re-copies all of an extension's skills when any of them is missing or differs from the vendored copy. Caches such as
__pycache__and.DS_Storedon't count. - It deletes the skills of extensions that are no longer recorded, for example after a teammate removed one. It deletes none in these cases:
- An extension list for that skills folder can't be fully read. Fix that list first.
- The project reaches its
.agents/skillsfolder through a link, or~/.agents/skillsleads to it. Then it deletes none at either scope, because that folder can hold skills that another list records. ~/.agents/skillsleads somewhere else, for example into a project. Then it deletes none from that folder, in any project.
- If project A links its
.agentsfolder to~/.agents, A's skills land in~/.agents/skills. Runningagents-cli installin another project doesn't read A's list, so it can delete them. Runagents-cli installin A to bring them back. - If a skill folder is yours or another extension's,
agents-cli installwarns, skips that extension's skills, and installs everything else, so CI doesn't break.
- It re-copies all of an extension's skills when any of them is missing or differs from the vendored copy. Caches such as
extension update [name]advances the pin to the latest commit of the same tracked ref (for example, a branch), re-prompting for trust unless the extension is verified by the agents-cli team. A pinned tag or SHA stays where it is. Nothing updates in the background.--to <branch|tag|sha>moves the pin of the named extension to another ref, for exampleextension update langchain --to v1.13.0.--to :latestmoves a first-party extension to the latest release that is not newer than your agents-cli. Without a name it moves every first-party extension and skips the others. It records the tag, so run it again to pick up later releases.- It replaces the extension's skills with the new version's skills, and removes any it no longer declares. If it can't delete an old skill folder, it warns and leaves the folder with its marker. The update still counts, and a later
extension updatetries the delete again. - If the new skills can't be installed (for example, a new skill would replace a folder that is yours or another extension's),
extension updateskips the extension, changes no skill, and keeps the old pin.- In a batch
extension update, the other extension may drop the skill in its own update. If it's at the same scope and comes later in the list,extension updatetries this extension once more after it, but only if the old copy could be put back. - If copying the new skills fails and putting the old skills back also fails,
extension updatewarns which skills may be changed and says to runextension updateagain, which installs the new skills.
- In a batch
extension remove <name> [--global]drops the entry and deletes the working copy and the skills it owns. It acts on one scope per call, so an extension installed at both scopes needs a secondremove.- Without
--global, it checks project scope first, then user scope. - With
--global, it acts on user scope only. Inside a project that also has the extension, use it to remove the user-scope copy. - If your home folder is a project and the extension is recorded at both scopes,
removekeeps the shared skills, because the other install still uses them. To delete them, also run the command thatremoveprints for the other scope.
- Without
Commit both files
For a project-scoped extension, commit both the extensions: entry in agents-cli-extensions.yaml and the vendored copy under extensions/. Then it works offline: agents-cli install restores the vendored copy, command overrides, and skills on a fresh checkout.
If you also commit .agents/skills/, keep the .agents-cli-extension files in it: they tell agents-cli which skill folders belong to which extension.
Compatibility#
An extension can declare the range of agents-cli versions it supports in requires.agents_cli (see Authoring). What you see as a user:
agents-cli extension add/updaterefuse an out-of-range install when the extension iserror-mode (and roll back), so you can't install something that won't run on your CLI. Awarn-mode extension installs with a warning.- After a CLI upgrade that moves an extension out of its range, nothing breaks silently. The extension warns, and an
error-mode one fails with the range and the fix instead of running the built-in. Runagents-cli extension update <name> --to <tag>(or--to :latestfor a first-party extension) to move to a version that supports your CLI. The commands no extension can override (info,login,setup,update,install, andextension) keep working either way. agents-cli extension listandagents-cli infoshow each extension'srequiresrange and flag any that are! incompatiblewith the running CLI.
Last updated