Skip to content

Skills

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.

Why skills exist

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:

  • At startup, the agent sees only a one-line stub per skill (tag + name + description) in the stable prompt prefix.
  • When a request matches, the agent calls skill.view to pull the full body into the session.
  • Scripts run only when the agent calls 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.

Quick start

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.

Where skills live

Skills are discovered from two locations. Project skills override global skills with the same name.

ScopeLocationUse 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.

Anatomy of a skill

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.md

SKILL.md frontmatter

The file opens with YAML frontmatter, then a Markdown body that is the actual playbook.

---
name: deploy-staging
description: Build and deploy the web app to the staging environment.
version: 1.0.0
requires_tools:
- os.shell
requires_scripts:
- deploy.sh
dangerous: true
platforms:
- 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.
KeyRequiredNotes
nameyesKebab-case (a-z, 0-9, hyphen), 2–64 chars, no leading/trailing hyphen. Must be unique.
descriptionyesOne line. Renders into the stub the agent sees at startup.
versionyesFree-form version string.
requires_toolsnoInformational list of tools the playbook expects.
requires_scriptsnoAllowlist of scripts that skill.run_script may invoke.
dangerousnoBoolean hint flag.
platformsnoAllowlist of darwin / linux / win32. Omit the key entirely for cross-platform.

How the agent uses a skill

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

Script execution rules

When the agent calls skill.run_script, the runtime enforces several guards before anything runs:

  • Allowlist only. The script name must appear in the skill’s requires_scripts frontmatter. Arbitrary files in scripts/ cannot be invoked.
  • No path traversal. Scripts must live directly under <skill_root>/scripts/. Paths like ../../etc/passwd, absolute paths, or subdirectories are rejected.
  • Type by extension. .ts / .js run with node; .sh runs with bash; anything else runs directly (relying on its shebang or executable bit).
  • Bounded execution. Scripts run through the shared command runner with a 30-second timeout.
  • Always gated. Execution goes through the approval gate with a preview. There is no unapproved path. (Running the agent with --no-approval auto-approves, intended for testing and trusted environments only.)

Managing skills from the CLI

Terminal window
# Install a skill folder into the global skills directory
atomic-agent skill install ./path/to/my-skill
# Overwrite an existing skill of the same name
atomic-agent skill install ./path/to/my-skill --force
# Remove a global skill
atomic-agent skill uninstall my-skill

Installation is validation plus a recursive copy — no downloads, no registry. Without --force, install fails if a skill of that name already exists globally.

Configuration and environment

SettingWhereEffect
skills.disabledconfig.json (array of names)Skills hidden from the agent.
ATOMIC_AGENT_STATE_DIRenv varRoot for the global skills/ directory and runtime state.
ATOMIC_AGENT_STARTER_SKILLS_DIRenv varOverride 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.

Example: a “release-notes” skill

A complete skill that turns recent commits into release notes.

---
name: release-notes
description: Draft release notes from git history since the last tag.
version: 1.0.0
requires_tools:
- os.shell
- os.git.log
requires_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.
my-skill/scripts/collect.sh
#!/usr/bin/env bash
set -euo pipefail
last_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'
fi

Install and use it:

Terminal window
atomic-agent skill install ./release-notes
atomic-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.

Limits

Skills are intentionally simple. They are data plus scripts, nothing more:

  • They cannot dynamically register new agent tools.
  • They cannot require native modules.
  • Scripts inherit the agent process environment — the approval gate is a policy mechanism, not a sandbox.
  • There is no external registry; you populate skills yourself by installing local folders.