The framework for building Agent Skills: scaffolding, validation, packaging, and runtime components (secrets, storage, context, flows, processes, learning) for SKILL.md
Project description
steer
The framework for building Agent Skills.
Agent Skills (a SKILL.md plus scripts) are the
open standard for packaging agent capabilities, supported by Claude Code,
Codex, Copilot, Cursor, Gemini CLI, and ~40 other clients. The format is
deliberately tiny, which means it ships no batteries: the spec says nothing
about credentials, persistence, context gathering, step enforcement, or
managed processes. Every serious skill hand-rolls some of these.
Steer provides them as components, plus the authoring tools to scaffold, validate, package, and install skills. Zero dependencies; Python stdlib only.
┌─ author-time ──────────────────────┐ ┌─ runtime (CLI or library) ─────────┐
│ steer new scaffold a skill │ │ steer secrets credentials │
│ steer validate spec + hygiene │ │ steer store per-skill SQLite │
│ steer package API-ready zip │ │ steer context situational recon │
│ steer install into skill dirs │ │ steer flow enforced steps │
│ steer list what's installed │ │ steer proc managed processes │
└────────────────────────────────────┘ │ steer learn skills that learn │
└────────────────────────────────────┘
Why
Steer's components are reverse-engineered from what good skills already hand-roll in prose and fragile bash (enforced steps, situational recon, persistent state, credentials, process lifecycles), turned into machinery you get with one flag.
Install
uv tool install steer-ai # installs the `steer` command
# or: pip install steer-ai
# latest from main: uv tool install git+https://github.com/bh-rat/steer
steer --version
Requires Python ≥ 3.11. No runtime dependencies.
Quickstart
steer new stripe-report \
--description "Generates revenue reports from Stripe. Use when the user asks for revenue, MRR, or payment reporting." \
--with secrets,context,flow,learn --scripts
This scaffolds a spec-valid skill:
stripe-report/
├── SKILL.md # frontmatter + body with the components wired in
├── flow.toml # declarative steps with verify conditions
└── scripts/
└── example.py # non-interactive, JSON result envelope on stdout
The generated SKILL.md already tells the agent how to behave:
- Ground yourself. Run
steer contextand read the snapshot.- Apply past lessons. Run
steer learn show; those lessons came from real previous runs.- Check credentials. Run
steer secrets check STRIPE_REPORT_API_KEY --skill stripe-report. If missing, ask the user to runsteer secrets set ...(never ask them to paste the value into the chat).- Follow the flow.
steer flow status→ do the step → steps verify themselves against reality; you cannot skip ahead.
For a skill only the human should trigger, steer new --user-invoked
sets disable-model-invocation: true and validation adapts.
Then:
steer validate stripe-report # spec rules, broken refs, secret hygiene
steer install stripe-report # → .claude/skills/ (project scope)
steer package stripe-report # → validated zip for the Claude API / claude.ai
Examples
Two complete skills built this way live in examples/:
repo-health exercises all six components in
one skill (enforced flow, trend memory, credential handoff, managed
preview server, lesson capture), and
commit-message is the minimal user-invoked
counterpoint. Their READMEs show exactly which lines steer generated and
which the author filled in.
The components
steer secrets: credentials that never live in the skill
Skill directories get zipped and uploaded; credentials must live outside
them. Resolution order: env var → OS keychain (macOS security /
Linux secret-tool) → 0600 file under ~/.steer/.
steer secrets check STRIPE_API_KEY --skill stripe-report # agent checks
steer secrets set STRIPE_API_KEY --skill stripe-report # human sets (hidden prompt)
from steer import Secrets
key = Secrets("stripe-report").require("STRIPE_API_KEY",
hint="dashboard.stripe.com/apikeys")
# missing -> MissingSecretError whose message tells the agent
# exactly what command to ask the human to run
steer store: per-skill SQLite
steer store put last_run '"2026-06-11"' --skill stripe-report
steer store insert runs '{"month": "may", "total": 1200}' --skill stripe-report
steer store find runs --where month=may --skill stripe-report
KV + JSON-document tables + raw SQL. Two scopes: user
(~/.steer/skills/<name>/store.db) and workspace
(<project>/.steer/<name>/store.db).
steer context: situational recon in one command
steer context # markdown for the agent to read
steer context --json --only git,project,tools
One command reports the platform, host agent (Claude Code, Codex, Cursor, and others), git state, project type (from lockfiles and manifests), tools on PATH, and a small allowlist of env flags. It never dumps the environment.
steer flow: steps the agent cannot skip
Define the process in flow.toml; steps with a verify condition complete
only when reality matches, mandate steps are marked explicitly, and marking
is gated on prerequisites:
[[steps]]
id = "configure"
directive = "Create out/config.json with the data sources"
[steps.verify]
file_exists = "out/config.json"
[[steps]]
id = "review"
directive = "Read the config and confirm the mappings look right"
requires = ["configure"]
steer flow status # progress bar + current directive
steer flow next # what to do now
steer flow done review # mark a mandate step (refused if prereqs incomplete)
Verify conditions: file_exists, dir_exists, glob, command (exit 0),
env. Python API: steer.Flow / steer.Step for full programmatic control.
steer proc: background processes that don't zombie
steer proc start web --ready-port 5173 -- npm run dev
steer proc status web
steer proc logs web
steer proc stop web # TERM → wait → KILL, whole process group
It checks readiness by port or log pattern, keeps PID bookkeeping under
<workspace>/.steer/proc/, guards against recycled PIDs, and captures logs.
steer learn: skills that improve from their own runs
Tooling exists to improve a skill before it ships, and agents carry runtime
memory; nothing connects the two, so a skill learns nothing from its own
runs. steer learn is that connection, a capture → curate → promote loop:
the agent records lessons the moment they happen, reads a bounded digest at
the start of every run, and the author promotes the keepers into the shipped
skill.
steer learn note "Use the EU endpoint for EU accounts" --kind correction
steer learn show # ranked digest the SKILL.md tells the agent to read
steer learn confirm 3 # helped → stronger; dispute → weaker, auto-archives
steer learn promote 3 # human-gated: append to the skill's learnings.md
steer learn run ok && steer learn stats
Curation is deterministic (no LLM inside the framework; the agent is the reflector): duplicates confirm instead of duplicating, disputed-more-than- confirmed auto-archives, a hard cap evicts the weakest, credential-shaped notes are refused.
The structure is fixed and inspectable: ~/.steer/skills/<name>/lessons.db
(source of truth) plus an auto-maintained readable LEARNINGS.md mirror,
both outside the skill dir, so lessons survive reinstalls and never ship by
accident. Promoted lessons land in the skill's learnings.md, which does
ship.
Auto-learning: steer new my-skill --auto-learn wires a Claude Code
skill-scoped Stop hook running steer learn reflect. When the agent tries
to finish, it deterministically scans the session transcript for corrections
and failed tool calls, and (once) blocks the stop with exact capture
instructions. Capture no longer depends on the agent remembering to do it.
Result envelope: one output shape for every script
from steer.output import print_envelope
print_envelope("ok", "Report generated",
data={"rows": 120}, artifacts=["out/report.pdf"])
{
"status": "ok",
"summary": "Report generated",
"data": {"rows": 120},
"artifacts": ["out/report.pdf"]
}
Validation
steer validate checks the open spec's hard rules (name format/length and
directory match, description 1-1024 chars, no XML), progressive-disclosure
budgets (<500-line body), broken file references, portability (Claude-Code-
only frontmatter), thin trigger descriptions, duplicated paragraphs across
SKILL.md and references (keep one source of truth), orphaned references/
files nothing points to, and secret hygiene: credential-looking files
inside a skill are warnings normally and hard errors at packaging time.
steer package refuses to ship them.
Library use
Everything the CLI does is importable (from steer import Skill, Flow, Secrets, Store, validate_skill, discover) for building your own skill
tooling on top.
What steer is not
Not a registry or installer ecosystem (use npx skills, Tessl, or plugin
marketplaces; steer sits upstream of them), not an eval harness (yet), and
not useful at runtime for pure-knowledge skills (a style guide needs no
database, though steer still helps author and validate it).
Roadmap
Skill-to-skill dependencies / shared libraries, steer test
(trigger-regression + cross-runtime checks), signing/provenance, TypeScript
SDK, PyPI release.
Docs & contributing
Full documentation lives in docs/ (introduction, quickstart, a
page per component, and the authoring guide, including the checklist for
writing skill bodies: trigger, structure, steering, pruning). Contributions
are welcome; see CONTRIBUTING.md. Security reports go to
SECURITY.md.
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file steer_ai-0.1.0.tar.gz.
File metadata
- Download URL: steer_ai-0.1.0.tar.gz
- Upload date:
- Size: 96.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cb75aecb3307fc48113e024fd1118ed987a092d6f48ea99be4d93a9a47bc84cc
|
|
| MD5 |
89ad074fd51a4da75ab3bb59bed1300d
|
|
| BLAKE2b-256 |
7cb39292600b860156763264b3ad33ef778739e7646ba6421354568a121ed48b
|
File details
Details for the file steer_ai-0.1.0-py3-none-any.whl.
File metadata
- Download URL: steer_ai-0.1.0-py3-none-any.whl
- Upload date:
- Size: 68.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
be6b95a1235e922523ed7173036595757fe8e32bb63c4c7ee463816dd431af6b
|
|
| MD5 |
0f0e40b69481e1263b6f05a868d67683
|
|
| BLAKE2b-256 |
6664fbefee1669c4c54bb0e70419e32fb25646905ff99495fbe5fab9f112dfd5
|