See what's installed
atomic-agent skill list shows every skill with its enabled/disabled state and source (global vs project).
A skill is a reusable playbook you give the agent: a folder with a SKILL.md instruction file and, optionally, a few scripts. When your request matches a skill, the agent loads that playbook and follows it — so you can extend the agent with domain-specific know-how without touching its core.
Think of skills as runbooks the agent reaches for when relevant. A “deploy-staging” skill, a “summarize-invoices” skill, a “scaffold-react-component” skill — each lives on disk, stays out of the way until needed, and runs entirely on your machine.
Local models have small context windows. Pasting a long playbook into every prompt would blow the token budget and break KV-cache reuse. Skills solve this with progressive loading:
skill.view to pull the full body into the session.skill.run_script — and that always goes through the approval gate.The result: dozens of skills can be installed, but the prompt stays small until one is actually used.
See what's installed
atomic-agent skill list shows every skill with its enabled/disabled state and source (global vs project).
Add a skill
atomic-agent skill install ./my-skill copies a skill folder into your global skills directory.
Read a skill
atomic-agent skill show <name> prints the SKILL.md body so you can review the playbook.
Hide a skill
atomic-agent skill disable <name> keeps the files on disk but hides the skill from the agent.
Skills are discovered from two locations. Project skills override global skills with the same name.
| Scope | Location | Use for |
|---|---|---|
| Global | $ATOMIC_AGENT_STATE_DIR/skills/<name>/ | Skills shared across all your projects |
| Project | ./.atomic-agent/skills/<name>/ | Skills specific to one repository |
A handful of starter skills are bundled with Atomic Agent and seeded into the global directory on every boot. Because they are re-seeded each restart, you cannot persist a custom edit to a starter by redefining it globally with the same name — put your override in a project skills directory instead, where it shadows the starter.
A skill is a folder. Only SKILL.md is required.
my-skill/├── SKILL.md # required: frontmatter + Markdown playbook├── scripts/ # optional: whitelisted scripts the agent may run│ └── build.sh└── references/ # optional: static files the playbook points to └── checklist.mdThe file opens with YAML frontmatter, then a Markdown body that is the actual playbook.
---name: deploy-stagingdescription: Build and deploy the web app to the staging environment.version: 1.0.0requires_tools: - os.shellrequires_scripts: - deploy.shdangerous: trueplatforms: - darwin - linux---
# Deploy to staging
1. Run `npm run build` to produce the bundle.2. Run the `deploy.sh` script with the target as the first argument.3. Confirm the health check at the staging URL returns 200.| Key | Required | Notes |
|---|---|---|
name | yes | Kebab-case (a-z, 0-9, hyphen), 2–64 chars, no leading/trailing hyphen. Must be unique. |
description | yes | One line. Renders into the stub the agent sees at startup. |
version | yes | Free-form version string. |
requires_tools | no | Informational list of tools the playbook expects. |
requires_scripts | no | Allowlist of scripts that skill.run_script may invoke. |
dangerous | no | Boolean hint flag. |
platforms | no | Allowlist of darwin / linux / win32. Omit the key entirely for cross-platform. |
The agent has exactly two skill tools, both invoked during a turn:
skill.view { name } — loads the full SKILL.md body (minus frontmatter) into the session. The body is cached for the rest of the session, so repeated calls do not regrow the prompt.skill.run_script { skill, script, args? } — executes a script declared in requires_scripts. This is always treated as a dangerous operation and routed through the approval gate.flowchart TD
Start["User request"] --> Match{"Matches a skill<br/>stub in the catalog?"}
Match -->|no| Normal["Agent proceeds<br/>with normal tools"]
Match -->|yes| View["skill.view { name }"]
View --> Body["Full SKILL.md body<br/>loaded into session<br/>(cached till session end)"]
Body --> Follow["Agent follows<br/>the playbook"]
Follow --> NeedScript{"Playbook calls<br/>a script?"}
NeedScript -->|no| Done["Reply / finish"]
NeedScript -->|yes| Check["Validate script is in<br/>requires_scripts +<br/>path stays under scripts/"]
Check --> Approve["Approval gate:<br/>show preview, await y/n"]
Approve -->|approved| Run["runCommand executes script<br/>(.ts/.js → node, .sh → bash)"]
Approve -->|denied| Done
Run --> Done
When the agent calls skill.run_script, the runtime enforces several guards before anything runs:
requires_scripts frontmatter. Arbitrary files in scripts/ cannot be invoked.<skill_root>/scripts/. Paths like ../../etc/passwd, absolute paths, or subdirectories are rejected..ts / .js run with node; .sh runs with bash; anything else runs directly (relying on its shebang or executable bit).--no-approval auto-approves, intended for testing and trusted environments only.)# Install a skill folder into the global skills directoryatomic-agent skill install ./path/to/my-skill
# Overwrite an existing skill of the same nameatomic-agent skill install ./path/to/my-skill --force
# Remove a global skillatomic-agent skill uninstall my-skillInstallation is validation plus a recursive copy — no downloads, no registry. Without --force, install fails if a skill of that name already exists globally.
# List all skills with enabled/disabled state and sourceatomic-agent skill list
# Print a skill's SKILL.md bodyatomic-agent skill show my-skill# Hide a skill from the agent without deleting itatomic-agent skill disable my-skill
# Bring it backatomic-agent skill enable my-skillEnable/disable mutate the skills.disabled array in config.json. Disabled skills stay on disk and remain visible in the TUI, but the agent cannot skill.view or skill.run_script them — those tools throw SkillNotFoundError.
| Setting | Where | Effect |
|---|---|---|
skills.disabled | config.json (array of names) | Skills hidden from the agent. |
ATOMIC_AGENT_STATE_DIR | env var | Root for the global skills/ directory and runtime state. |
ATOMIC_AGENT_STARTER_SKILLS_DIR | env var | Override the source location for bundled starter skills. |
The HTTP API exposes the same operations for hosted setups: GET /api/skills, POST /api/skills/install, and POST /api/skills/uninstall. In the TUI, the Skills panel toggles skills live.
A complete skill that turns recent commits into release notes.
---name: release-notesdescription: Draft release notes from git history since the last tag.version: 1.0.0requires_tools: - os.shell - os.git.logrequires_scripts: - collect.sh---
# Draft release notes
1. Run the `collect.sh` script to gather commits since the last tag.2. Group the output into Features, Fixes, and Chores.3. Write a concise summary paragraph, then the grouped list.4. Reply with the formatted notes — do not write any files unless asked.#!/usr/bin/env bashset -euo pipefaillast_tag="$(git describe --tags --abbrev=0 2>/dev/null || echo '')"if [ -n "$last_tag" ]; then git log "${last_tag}..HEAD" --pretty='- %s'else git log --pretty='- %s'fiInstall and use it:
atomic-agent skill install ./release-notesatomic-agent run# then ask: "draft release notes for this repo"The agent recognizes the release-notes stub, calls skill.view to load the playbook, then proposes running collect.sh. You approve the script at the gate, and the agent formats the result into release notes.
Skills are intentionally simple. They are data plus scripts, nothing more: