skill
reactive-skills
HSM runtime for deterministic AI workflows
Set up
Skills are installed by placing their folder where your agent loads skills.
The download comes from github.com/Reactive-Skills/reactive-skills itself, not from our server, so what you get is exactly what its author published.
Install instructions come from the README
README
synced Oct 26, 2026⚡ Reactive Skills Architecture (RSA)
Event-Driven Hierarchical State Machine Engine and Immutable Event Store for Agentic Skills
🚀 What's New in v0.19.0:
- New
reactive-skills-axi vet <skill|dir>statically checks a skill's guard code, text, and dependencies for risky patterns before you run it. It is the first part of the trust work; a trust record and a hardened mode are still to come.validatecatches a guard file in the wrong module format before it runs, and<command> --helpnow works on every command.invokerejects a wrappedcontextUpdatespayload and shows the expected shape;jobsandresetfind runs by skill path or name.- Judgments can limit what the AI judge sees with
context_pathsandinclude_payload; a legacy mixed run store migrates instead of crashinginvoke.
🌟 What is Reactive Skills?
Conventional agent skills are static markdown instruction files (SKILL.md). An LLM reads all instructions upfront, enters an unstructured execution loop, and guesses its next steps without state verification or deterministic progress guarantees.
Reactive Skills upgrade passive agent skills into Hierarchical State Machines (HSM) driven by a reactive Event/Signal Bus:
- Just-In-Time Prompt Slices: Only the prompt, constraints, and tool whitelists for the active state are loaded into the LLM turn (~70% token reduction).
- Signal-Driven Ingress: Transitions are triggered by typed runtime signals (
REQUIREMENTS_GATHERED,TESTS_PASSED,USER_APPROVED). - Deterministic Guard Gates: Progress requires deterministic programmatic invariants to evaluate
true(preventing hallucinated completion). - Event Sourcing & Live Deliverables: Every transition is recorded to an append-only ledger (
events.jsonl+ SQLiteevents.db). Documentation, PR bodies, and review matrices are live read-model projections rendered from the event stream.
📦 Packages
This repository is a monorepo containing:
@reactive-skills/runtime: The core TypeScript statechart engine, SQLite event store driver, guard evaluator, and stdio MCP server.@reactive-skills/axi: The Agent eXperience Interface (AXI) CLI (reactive-skills-axi) providing human- and agent-ergonomic state inspection and signal dispatch in TOON format.
🚀 Quickstart
1. Execution Options
You can execute commands on-demand via npx (zero installation required) or install the CLI globally:
# Zero install — works immediately for any agent or shell:
npx -y @reactive-skills/axi state <skill-name>
npx -y @reactive-skills/axi emit <skill-name> <signal-name>
npx -y @reactive-skills/axi capabilities --json
npx -y @reactive-skills/axi preflight <skill-name> --json
# Optional: Install globally for instant local commands (`reactive-skills-axi` or `axi`):
npm install -g @reactive-skills/axi
2. Inspect a Skill's Current State
npx -y @reactive-skills/axi state <skill-name>
Outputs the current state, active prompt instructions, allowed tools, and available transitions in structured format:
state:
skill_id: my-skill
current_state: STEP_ONE
prompt:
raw_prompt: "# State: Processing Step One ..."
allowed_tools: "view_file,grep_search,find_by_name,ask_question"
help[2]:
Read the state prompt above and execute the instructed tasks
Run `npx -y @reactive-skills/axi emit <skill> <signal>` to advance
3. Emit a Signal to Advance
npx -y @reactive-skills/axi emit <skill-name> <signal-name> [--payload '{"exit_code":0}']
The state machine evaluates transition guards, appends to the immutable event ledger, updates deliverables, and outputs the next state instructions.
🔌 Integration Modes
Reactive skills can be driven through two primary integration paths:
- AXI CLI (Universal Shell Mode): Any agent capable of running terminal commands can drive the skill using
npx -y @reactive-skills/axi state <skill>(orreactive-skills-axi state <skill>) andnpx -y @reactive-skills/axi emit <skill> <signal>. - MCP Server (Model Context Protocol): Exposes
reactive_context_prepare,reactive_state, andreactive_emit_signaltools over stdio for Claude Desktop, Antigravity, Cursor, and any MCP-compatible harness:npx -y @reactive-skills/axi mcp
Call reactive_context_prepare with the current user message before loading full skill instructions.
The tool uses Jev to select one skill and returns only its metadata, active state, or bounded instructions.
If Jev is unavailable, it returns route: none and the agent can continue its directly requested runtime path.
🛠️ CLI Reference
Note: Commands below are shown using the zero-install
npx -y @reactive-skills/axiprefix. If installed globally (npm install -g @reactive-skills/axi), you can substitutereactive-skills-axioraxi.
| Command | Usage | Description |
|---|---|---|
state | npx -y @reactive-skills/axi state <skill> | Display current active state, unabridged prompt slice, and allowed tools |
emit | npx -y @reactive-skills/axi emit <skill> <signal> | Emit a signal to evaluate guards and advance to the next state; --payload is the signal payload, with context changes under contextUpdates |
invoke | npx -y @reactive-skills/axi invoke <skill> [--payload JSON] | Initialize and start a skill run; --payload is a flat object that becomes the initial context (a {"contextUpdates":{...}} wrapper is rejected) |
events | npx -y @reactive-skills/axi events [limit] <skill> | Tail recent events from the append-only event store |
inspect | npx -y @reactive-skills/axi inspect <skill> | Print statechart topology, substates, and guard rules |
validate | npx -y @reactive-skills/axi validate [path] | Validate skill manifest, prompt templates, transition targets, and bootloader |
vet | npx -y @reactive-skills/axi vet <path> [--fail-on <severity>] [--allowlist <file>] | Statically scan skills for risky code, prompt injection, hidden content, and download-and-execute steps before you run them; see docs/vetting.md |
init | npx -y @reactive-skills/axi init <name> | Scaffold a new modular reactive skill package |
reset | npx -y @reactive-skills/axi reset <skill> | Clear execution run state while preserving deliverables |
jobs | npx -y @reactive-skills/axi jobs <skill> [list|switch|archive] | Inspect, switch, and archive isolated execution runs and deliverables |
view | npx -y @reactive-skills/axi view <skill> | Launch real-time telemetry server and live visual statechart viewer |
dashboard | npx -y @reactive-skills/axi dashboard [--host <host>] [--port <port>] | Launch one read-only broker for multi-job telemetry |
sync | npx -y @reactive-skills/axi sync [skill] | Copy ordered sources into a physical central directory, then update linked or physical satellites |
capabilities | npx -y @reactive-skills/axi capabilities --json | Report runtime version and capabilities for INIT negotiation |
bootloader | npx -y @reactive-skills/axi bootloader <skill> --json | Retrieve the versioned authoritative runtime bootloader |
preflight | npx -y @reactive-skills/axi preflight <skill> | Check skill runtime requirements without creating a job |
🛠️ Authoring Reactive Skills
Avoid manually hand-authoring reactive skill packages from scratch. A reactive skill binds together statechart topology (skill.yaml), individual state prompt templates (states/*.md), deterministic guards (guards/), projection deliverables (templates/*.hbs), and strict execution bootloaders. Hand-authoring these files easily introduces syntax drift, broken transitions, or missing guards.
Recommended: Use the skill-manager Skill
The canonical method to scaffold, modify, and migrate reactive skills is the skill-manager agent skill.
Instead of writing YAML manifests manually, ask your AI agent:
"Use skill-manager to create a reactive skill named my-feature-workflow"
The skill-manager skill validates schemas, coordinates state prompts with strict execution invariants, and handles lifecycle operations (CREATE, UPDATE, MIGRATE_LEGACY, MIGRATE_REACTIVE).
Visual Statecharts with STATECHART.md
skill-manager supports and generates a STATECHART.md alongside skill.yaml. This document contains a Mermaid stateDiagram-v2 visualization of the entire state machine:
stateDiagram-v2
[*] --> INIT
INIT --> START : RUNTIME_READY
INIT --> SETUP_MCP : SETUP_REQUIRED
SETUP_MCP --> START : SETUP_COMPLETE [exit_code == 0]
SETUP_MCP --> ERROR : SETUP_FAILED [exit_code != 0]
START --> DONE : DONE
DONE --> [*]
- Visual-first design: You can sketch a proposed state machine using a Mermaid
stateDiagram-v2block inSTATECHART.md, andskill-managerwill parse it into the correspondingskill.yamland state templates. - Continuous synchronization: When modifying a skill's states or transitions,
skill-managerupdates bothskill.yamlandSTATECHART.mdto keep documentation and runtime contracts identical.
Terminal Scaffolding (init)
For quick command-line scaffolding, you can also use the AXI CLI:
npx -y @reactive-skills/axi init <skill-name>
This scaffolds the modular file layout in skills/<skill-name>/:
skills/<skill-name>/
├── skill.yaml # Statechart manifest (states, transitions, guards)
├── STATECHART.md # Visual Mermaid statechart diagram
├── SKILL.md # Skill entry point with reactive bootloader
├── states/ # State-specific markdown prompt templates
│ ├── init.md
│ ├── setup_mcp.md
│ ├── start.md
│ ├── done.md
│ └── bypass_detected.md
└── skill-release.json # Release and schema metadata
🔄 Syncing & Distributing Skills
The synchronizer copies skills from ordered local source directories into a physical central directory (default ~/.agents/skills). The first source containing a skill name wins. Agent satellite directories then link to the central copy. Changes in a source repository reach the central directory on the next sync; linked satellites see those central changes immediately. Satellites that cannot read links receive physical copies, refreshed on each sync when their content changes.
Only immediate child folders containing SKILL.md, skill.md, or skill.yaml are distributed. Unrelated folders at a source root are ignored. Sync reads local files, or committed files when a ref is set; it never fetches Git updates.
Within a selected skill, sync preserves every file and directory, including scripts, tests, hidden files and empty directories.
Nested symbolic links remain links; sync does not traverse their targets.
Repository-folder exclusions apply only when discovering skills at the source root.
Configure the layout in ~/.agents/sync.json:
{
"sources": ["~/work/public-skills", "~/work/private-skills"],
"central": "~/.agents/skills",
"satellites": ["~/.claude/skills", "~/.codex/skills", "~/.gemini/config/skills"],
"physicalSatellites": ["~/.gemini/config/skills"]
}
Change the persistent central directory by updating the central value in this file.
Use --central <dir> to override it for one invocation, and use --show-config to inspect the resolved paths.
When prior sync state records the old central path, the next sync can use that directory as a migration fallback while populating the new central directory.
The old central directory remains on disk.
Sources are optional. Without them, sync distributes valid skills already in the central directory. Without a config file, it uses the default central path and existing agent directories as satellites; the physical satellite list is empty. If a directory appears in both satellite lists, the physical copy takes precedence. If the central path appears in either satellite list, sync omits it.
When sync.json is absent, existing sources from ~/.agents/sources.json remain a fallback.
If creating sync.json for the first time, copy any needed source paths into its sources array because the legacy source fallback applies only when sync.json is absent.
Git Sources, Refs, and Downgrade Protection
By default, sync copies each skill from the source folder's working tree as it is at that moment. That means checking out an older branch in a source repository changes what the next sync installs. Three safeguards keep that from replacing newer installed skills silently.
- Pin a ref. A source entry can be an object with a
ref(branch, tag, or commit). Sync then reads the committed files at that ref withgit ls-treeandgit cat-file, so the source can have any branch checked out, dirty or not. Nothing is checked out and the source repository is never modified. The--ref <ref>flag does the same for every source in one run and overrides configured refs. A ref on a source that is not a git repository, or one that does not resolve, stops the sync with an error. - Downgrade protection. Before replacing an installed skill whose content differs, sync compares the
versionin eachskill.yamlusing SemVer. A source version lower than the installed one is refused: the installed copy stays unchanged, the report names the skill and both versions, and the command exits with status 1. Other skills still sync. Pass--allow-downgradeto replace it anyway; the usual backup is still made. A same-version content change and a skill whose version is missing or not SemVer (for example1.0or a legacySKILL.mdskill) produce a warning and are replaced. The check applies to--dry-runand to sources that are not git repositories. - Working-tree warnings. When a git source has no ref, sync warns if it is on a branch other than the default branch (the
origin/HEADbranch, elsemainormaster) or is on a detached HEAD, and warns if the selected skills have uncommitted or untracked changes. Each warning names the source, the branch, and the skills involved. Warnings do not stop the sync.
{
"sources": [
"~/work/private-skills",
{ "path": "~/work/public-skills", "ref": "main" }
]
}
Sync records where each installed skill came from under skills in ~/.agents/sync-state.json: the source path, the ref or checked-out branch, the commit SHA, the skill.yaml version, and dirty: true when the working-tree copy had uncommitted changes.
For a working-tree sync the SHA is the source's HEAD, so check dirty as well.
Sources that are not git repositories record only the source path and version.
The record is merged on each run, so syncing one skill keeps the others, and a skill that is refused keeps its previous record.
sync --show-config prints the configured refs and the recorded provenance, and a sync prints the provenance of the skills it copied.
Empty directories are not part of a commit, so they are not copied when a ref is used.
CLI Synchronization
# Show effective paths and source precedence:
npx -y @reactive-skills/axi sync --show-config
# Preview a one-run central directory override:
npx -y @reactive-skills/axi sync --central ~/work/skill-registry --dry-run
# Preview central copies, satellite links/copies, and source collisions:
npx -y @reactive-skills/axi sync --dry-run
# Synchronize all valid skills:
npx -y @reactive-skills/axi sync
# Synchronize a specific skill only:
npx -y @reactive-skills/axi sync <skill-name>
# Synchronize several selected skills together:
npx -y @reactive-skills/axi sync --skill skill-one,skill-two
# Repeated --skill flags remain supported:
npx -y @reactive-skills/axi sync --skill skill-one --skill skill-two
# Override configured sources with comma-separated paths:
npx -y @reactive-skills/axi sync --source ~/work/public-skills,~/work/private-skills --dry-run
# Add explicit sources before configured sources:
npx -y @reactive-skills/axi sync --source ~/work/public-skills --all-sources --dry-run
# Choose linked and physical satellite directories:
npx -y @reactive-skills/axi sync --target ~/.codex/skills,~/.claude/skills --physical-target ~/.gemini/config/skills,~/.copilot/skills --dry-run
# Install the committed skills of main, whatever the sources have checked out:
npx -y @reactive-skills/axi sync --ref main
# Replace an installed skill with an older source version:
npx -y @reactive-skills/axi sync <skill-name> --allow-downgrade
# Preview changes without modifying files:
npx -y @reactive-skills/axi sync <skill-name> --dry-run
# Use physical copies for all selected satellites for this run:
npx -y @reactive-skills/axi sync <skill-name> --copy
Each --source, --target, and --physical-target value can contain comma-separated paths, and each option can be repeated.
Surrounding whitespace is ignored, and empty path entries are rejected.
Model Context Protocol (MCP)
Agents running in GUI environments can call the native reactive_sync tool:
{
"skill": "my-skill",
"link": true,
"dryRun": false
}
Safety and Backups
The synchronizer validates path overlaps before writing. It stages and verifies central copies before replacing existing skill folders. It backs up physical directories before replacement under each target's .sync-backups/ directory. Valid skills already in the central directory remain there when no configured source supplies them. A state file at ~/.agents/sync-state.json tracks links created by sync, allowing it to remove obsolete managed links when satellite configuration changes while preserving unrelated files.
🗂️ Job & Run Isolation (Multi-Run Management)
RSA provides multi-run isolation, allowing teams and autonomous agents to execute multiple independent runs of the same skill without event log pollution or deliverable overwrites.
Storage Architecture
- Isolated Event Ledgers: Each run maintains its own scoped event ledger under
.reactive/skills/<skill>/jobs/<job-id>/with independentevents.jsonland SQLiteevents.dbstores. - Active Job Pointer: The active run pointer is tracked at
.reactive/skills/<skill>/active_job(defaults todefault). All CLI commands and MCP operations target the active run unless explicitly overridden. - Dual-Write Deliverable Mirroring: Projections write to
.docs/<skill>/jobs/<job-id>/for permanent archival, and automatically mirror to the canonical.docs/path for the active job. - Template Context: Handlebars templates receive
jobIddirectly insideProjectionContext, enabling deliverables to reference their run ID.
CLI Run Management
# Start a fresh execution run (auto-generates sortable job ID)
npx -y @reactive-skills/axi invoke <skill> [--payload JSON]
# Start an isolated named run (does not change the global active pointer)
npx -y @reactive-skills/axi invoke <skill> --job <job-id>
# Inspect or resume the active execution run (auto-rotates if prior job is terminal)
npx -y @reactive-skills/axi state <skill>
# Run with environment-scoped isolation (parallel subagents)
REACTIVE_JOB_ID=subagent-1 npx -y @reactive-skills/axi state <skill>
# List all execution runs for a skill (active job highlighted)
npx -y @reactive-skills/axi jobs <skill> list
# (or bidirectional syntax: npx -y @reactive-skills/axi jobs list <skill>)
# Switch the active execution run
npx -y @reactive-skills/axi jobs <skill> switch <job-id>
# Archive a completed run
npx -y @reactive-skills/axi jobs <skill> archive <job-id>
# Target a specific job explicitly without switching active pointer
npx -y @reactive-skills/axi state <skill> --job <job-id>
npx -y @reactive-skills/axi emit <skill> <signal> --job <job-id>
Model Context Protocol (MCP) Tools
When interacting with agents over MCP, job operations are exposed as native tools:
reactive_bootloader: Retrieves the versioned authoritative bootloader for a reactive skill.reactive_list_jobs: Lists all runs for a skill with state and active indicators.reactive_switch_job: Switches the active job pointer.reactive_archive_job: Marks a job run as archived.
📊 Telemetry & Performance Metrics
RSA provides real-time performance instrumentation and token economy tracking with zero runtime latency tax.
Inspecting Metrics from the Event Ledger
Every state transition records execution telemetry inside .reactive/skills/<skill>/events.jsonl:
{
"type": "STATE_TRANSITION",
"payload": {
"from": "RED_SPEC",
"to": "GREEN_CODE",
"metrics": {
"transition_duration_ms": 1.151,
"slice_duration_ms": 0.922,
"slice_tokens_est": 282
}
}
}
Tail latest transition metrics from your terminal:
# PowerShell
Get-Content .reactive/skills/<skill>/events.jsonl | ConvertFrom-Json | Where-Object { $_.type -eq "STATE_TRANSITION" } | Select-Object -ExpandProperty payload | Select-Object from, to, metrics
# SQLite
sqlite3 .reactive/skills/<skill>/events.db "SELECT seq, json_extract(payload, '$.metrics') FROM events WHERE type = 'STATE_TRANSITION';"
Real-Time Telemetry Dashboard
Launch the existing single-job viewer and SSE event stream:
npx -y @reactive-skills/axi view <skill-name> # prefer 4242, then try the bounded fallback range
npx -y @reactive-skills/axi view <skill-name> --port 5000 # bind only to 5000
npx -y @reactive-skills/axi view <skill-name> --port 0 # ask the OS for an ephemeral port
npx -y @reactive-skills/axi view <skill-name> --job sprint-1 # follow one job without changing the active pointer
Launch the read-only multi-job broker:
npx -y @reactive-skills/axi dashboard
npx -y @reactive-skills/axi dashboard --port 0
npx -y @reactive-skills/axi dashboard --host 0.0.0.0 --port 4500
The command reports the actual listener URL and bound port.
Open the site /telemetry route and enter that broker URL in the connection field.
The broker catalog discovers skills and jobs from the current workspace's .reactive/skills directory and returns skill names, job IDs, status, current HSM state, local latest sequence, update time, and active-job metadata.
The dashboard uses GET /catalog, job-scoped GET /state?skillId=<skill-id>&jobId=<job-id>, and one filtered GET /events SSE connection for all tracked targets.
Add two jobs from the catalog, such as jsm-workflow/review-slice and jsm-workflow/test-slice, to monitor them simultaneously.
Every card verifies both skill ID and job ID before accepting an event, so a signal written to one job cannot update another card.
The broker tails each job's SQLite event store and refreshes the catalog on a bounded interval, so new jobs and cross-process events appear without restarting it.
The broker is read-only telemetry.
It does not dispatch signals, write events, change the active-job pointer, or scan arbitrary browser localhost ports.
The existing view <skill> --job <job-id> command remains single-job scoped for explicit isolation and backward compatibility.
The broker keeps the existing CORS and Local Network Access response headers so a site served from another origin can request local telemetry after the browser grants access.
See the telemetry guide for endpoint details and a two-job walkthrough.
When --port is omitted, the viewer first attempts 127.0.0.1:4242 and then tries the next available port in a bounded deterministic range.
The CLI output, telemetry URLs, /health, /state, and SSE connection metadata report the actual selected port.
An explicit --port is strict, so an occupied port returns an error instead of falling back.
The browser viewer does not scan local ports automatically.
For performance tiers, algorithmic budgets, and caching standards, see PERFORMANCE-STANDARDS.md.
Star History
📜 License
The core Reactive Skills framework (@reactive-skills/runtime and @reactive-skills/axi) is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). See LICENSE for details.
Reactive skills created using the Reactive Skills Architecture (e.g. in community skill repositories or third-party agents) may be licensed independently under permissive licenses such as MIT.