skillscript-runtime 0.2.4 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +188 -251
- package/dist/cli.js +1 -1
- package/dist/connectors/agent.d.ts +24 -0
- package/dist/connectors/agent.d.ts.map +1 -1
- package/dist/errors.d.ts +13 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +27 -0
- package/dist/errors.js.map +1 -1
- package/dist/filters.d.ts +4 -1
- package/dist/filters.d.ts.map +1 -1
- package/dist/filters.js +18 -2
- package/dist/filters.js.map +1 -1
- package/dist/lint.d.ts.map +1 -1
- package/dist/lint.js +28 -0
- package/dist/lint.js.map +1 -1
- package/dist/mcp-server.js +1 -1
- package/dist/parser.d.ts +15 -0
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +32 -1
- package/dist/parser.js.map +1 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +61 -7
- package/dist/runtime.js.map +1 -1
- package/examples/hello.skill.provenance.json +1 -1
- package/examples/queue-length-monitor.skill.md +22 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,346 +1,283 @@
|
|
|
1
1
|
# Skillscript
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
3
|
+
*A language for agents to write themselves in.*
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/skillscript-runtime)
|
|
6
|
+
[](#)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
[](#status)
|
|
9
|
+
|
|
10
|
+
> **TL;DR** — `npm install -g skillscript-runtime`, then `skillfile dashboard`. See [Quickstart](#quickstart).
|
|
11
|
+
|
|
12
|
+
## Contents
|
|
13
|
+
|
|
14
|
+
- [The problem](#the-problem)
|
|
15
|
+
- [The frame](#the-frame)
|
|
16
|
+
- [Why a new language](#why-a-new-language)
|
|
17
|
+
- [Why not just have the agent write a Skill?](#why-not-just-have-the-agent-write-a-skill)
|
|
18
|
+
- [Three kinds of skill](#three-kinds-of-skill)
|
|
19
|
+
- [Waking agents](#waking-agents)
|
|
20
|
+
- [Local models as tools for the frontier](#local-models-as-tools-for-the-frontier)
|
|
21
|
+
- [What you get](#what-you-get)
|
|
22
|
+
- [The bet](#the-bet)
|
|
23
|
+
- [Quickstart](#quickstart)
|
|
24
|
+
- [Connector model](#connector-model)
|
|
25
|
+
- [CLI](#cli)
|
|
26
|
+
- [MCP server surface](#mcp-server-surface)
|
|
27
|
+
- [Examples](#examples)
|
|
28
|
+
- [Architecture and deep documentation](#architecture-and-deep-documentation)
|
|
29
|
+
- [Status](#status)
|
|
30
|
+
- [Contributing](#contributing)
|
|
31
|
+
- [License](#license)
|
|
26
32
|
|
|
27
33
|
---
|
|
28
34
|
|
|
29
|
-
##
|
|
30
|
-
|
|
31
|
-
### npm (recommended)
|
|
35
|
+
## The problem
|
|
32
36
|
|
|
33
|
-
|
|
34
|
-
npm install -g skillscript-runtime
|
|
35
|
-
skillfile --version
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
This installs the `skillfile` binary globally. Requires Node.js ≥ 22.5 (the runtime uses `node:sqlite` and other features that landed in 22.5+).
|
|
39
|
-
|
|
40
|
-
### From source
|
|
37
|
+
AI agents are mostly transient. Every routine task is re-derived from prose reasoning. The agent that summarized a thread yesterday will summarize one tomorrow by reasoning from scratch about how to summarize threads, burning frontier inference on a procedure with a known shape, a known output format, and known failure modes.
|
|
41
38
|
|
|
42
|
-
|
|
43
|
-
git clone https://github.com/sshwarts/skillscript-runtime.git
|
|
44
|
-
cd skillscript-runtime
|
|
45
|
-
pnpm install
|
|
46
|
-
pnpm run build
|
|
47
|
-
node dist/cli.js --help
|
|
48
|
-
```
|
|
39
|
+
The waste compounds in three directions: **cost** (every routine operation runs through the most expensive reasoning layer in the system), **latency** (every operation pays the full inference cost), and **drift** (the same task produces slightly different results each invocation because nothing crystallizes).
|
|
49
40
|
|
|
50
|
-
The
|
|
41
|
+
The deeper problem is that *agents have no substrate to write themselves down in*. Agents are partly defined by what they can do and what they can do is currently held entirely in a soft, transient form of reasoning at inference time. There's no hard form. No place for an agent to crystallize a learned procedure into something cheap to execute, cheap to inspect, and cheap to improve.
|
|
51
42
|
|
|
52
|
-
|
|
43
|
+
Most agent infrastructure projects today focus on **memory** — episodic recall, retrieval-augmented context, conversation summarization. Those projects answer *"what does the agent know."* They don't answer *"what can the agent do"* in any persistent, executable, inspectable form.
|
|
53
44
|
|
|
54
|
-
|
|
45
|
+
Skillscript intends to answer the second question.
|
|
55
46
|
|
|
56
|
-
|
|
57
|
-
# 1. Scaffold the config tree
|
|
58
|
-
skillfile init
|
|
47
|
+
## The frame
|
|
59
48
|
|
|
60
|
-
|
|
61
|
-
cat ~/.skillscript/examples/hello.skill.md
|
|
49
|
+
**Agents are code, and skillscript is the language they write themselves in.** Not memory in the recall sense. Not prompt templates. Not configuration. Code, in the strict sense of named, typed, composable, executable artifacts that constitute capability.
|
|
62
50
|
|
|
63
|
-
|
|
64
|
-
skillfile run examples/hello.skill.md
|
|
65
|
-
# → Hello, world!
|
|
51
|
+
A skillscript skill is a declarative recipe, a small program with a dependency DAG of typed operations — that an agent authors once and the runtime fires many times. Where typical agent code is procedural (Python scripts, TypeScript handlers), skillscript is **orchestration-only**: it composes calls into tools, models, and memory stores through swappable connector contracts. Computation lives in tools; coordination lives in skills.
|
|
66
52
|
|
|
67
|
-
# 4. Override an input
|
|
68
|
-
skillfile run hello --input WHO=Scott
|
|
69
|
-
# → Hello, Scott!
|
|
70
53
|
```
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
```skillscript
|
|
75
|
-
# Skill: greet
|
|
76
|
-
# Status: Draft
|
|
54
|
+
# Skill: hello
|
|
55
|
+
# Status: Approved
|
|
56
|
+
# Description: The canonical first-run example.
|
|
77
57
|
# Vars: WHO=world
|
|
78
58
|
|
|
79
59
|
greet:
|
|
80
60
|
! Hello, $(WHO)!
|
|
61
|
+
! Welcome to Skillscript.
|
|
81
62
|
|
|
82
63
|
default: greet
|
|
83
64
|
```
|
|
84
65
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
Lint as you go:
|
|
88
|
-
|
|
89
|
-
```sh
|
|
90
|
-
skillfile lint ./greet.skill.md
|
|
91
|
-
```
|
|
66
|
+
That's a complete, runnable skill. Five lines, no dependencies, no boilerplate. The same shape scales to multi-stage DAGs that classify inputs, dispatch to local models, write to memory, branch on conditions, and orchestrate sub-agents, all in the same declarative grammar.
|
|
92
67
|
|
|
93
|
-
|
|
68
|
+
## Why a new language
|
|
94
69
|
|
|
95
|
-
|
|
96
|
-
skillfile compile ./greet.skill.md
|
|
97
|
-
# Writes greet.skill.provenance.json sidecar with content hashes
|
|
98
|
-
```
|
|
70
|
+
The obvious alternative is "let the agent write Python." Python is Turing-complete, has mature tooling, and models write it well. For one-shot exploratory work or where computation matters, Python is the right tool, and we're not proposing anyone stop using it for that.
|
|
99
71
|
|
|
100
|
-
|
|
72
|
+
But agent-authored *persistent* automation has a different shape:
|
|
101
73
|
|
|
102
|
-
|
|
74
|
+
- An **agent** (not a human) writes the code.
|
|
75
|
+
- The code runs **autonomously** — cron-fired, event-triggered — with no human in the loop at execution time.
|
|
76
|
+
- The work is **dispatch-shaped**: call a tool, classify a result, branch, call another tool. Not algorithmic computation.
|
|
77
|
+
- The code needs to be **auditable by humans at human tempo** even though it's authored at agent tempo.
|
|
103
78
|
|
|
104
|
-
|
|
79
|
+
For this shape, Python's strengths invert into liabilities:
|
|
105
80
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
| `compile <path\|name>` | Render the compiled artifact (no execution) |
|
|
111
|
-
| `audit <provenance-path>` | Detect recompile-staleness via `.provenance.json` sidecar |
|
|
112
|
-
| `lint <path\|name>` | Run static validation, print findings |
|
|
113
|
-
| `list` | List available skills in the configured SkillStore |
|
|
114
|
-
| `fires <skill>` | List recent trace records for a skill |
|
|
115
|
-
| `diagram <path\|name>` | Emit mermaid graph of the skill's control flow |
|
|
116
|
-
| `sign <path\|name>` | Content-hash sign the skill source (SHA-256) |
|
|
117
|
-
| `verify <path\|name> <hash>` | Verify the skill matches a signature |
|
|
118
|
-
| `replay <trace_id>` | Re-run a recorded trace mechanically |
|
|
119
|
-
| `health` | Aggregate runtime metrics across all traces |
|
|
120
|
-
| `dashboard` | Start the runtime host: scheduler + MCP server + browser dashboard SPA |
|
|
121
|
-
|
|
122
|
-
> Trigger registration is handled through the MCP server exposed by `skillfile dashboard` (`register_trigger` / `unregister_trigger` / `list_triggers` tools). The v0.2.0 CLI register-trigger family was removed in v0.2.1 — those commands constructed throwaway in-memory schedulers and never fired.
|
|
123
|
-
|
|
124
|
-
Environment variables:
|
|
125
|
-
|
|
126
|
-
| Var | Default | Purpose |
|
|
127
|
-
|---|---|---|
|
|
128
|
-
| `SKILLSCRIPT_HOME` | `~/.skillscript` | Config + data root |
|
|
129
|
-
| `OLLAMA_BASE_URL` | `http://localhost:11434` | Ollama endpoint for LocalModel dispatch |
|
|
81
|
+
- **Turing completeness becomes a liability.** An agent-authored script can do anything including things the agent didn't realize were dangerous. `subprocess.run`, arbitrary network calls, file writes. None of these are gated. The blast radius of a buggy agent-authored script is the whole host.
|
|
82
|
+
- **Mature tooling doesn't help when the author isn't human.** Debuggers and REPLs are for human iteration. Agents don't iterate that way.
|
|
83
|
+
- **Direct execution magnifies failure.** When an agent ships a broken Python script to production cron, there's no validation layer. The script fails silently at 3am and the human discovers it the next day.
|
|
84
|
+
- **The package ecosystem becomes an unbounded attack surface.** Agents that can `pip install` anything can install anything — including supply-chain-compromised packages. The package ecosystem assumes human review before adoption; agent adoption breaks that assumption.
|
|
130
85
|
|
|
131
|
-
|
|
86
|
+
Skillscript deliberately constrains expressiveness. It's not Turing complete. It can't `eval`, can't `subprocess`, can't import arbitrary code. **The constraint *is* the safety story** — enforced at the language level, not as an aspiration. In exchange:
|
|
132
87
|
|
|
133
|
-
|
|
88
|
+
- **Sandboxed grammar.** The language can only do what configured connectors permit.
|
|
89
|
+
- **Declarative legibility.** Skills are DAGs of typed dispatches. A human reading a skill sees exactly which tools get called, which memory writes happen, which model prompts fire. The same source produces the same audit diagram every time.
|
|
90
|
+
- **Connector-mediated capability.** Skills don't import packages, they invoke connectors, gated artifacts with curated tool surfaces. Python doesn't disappear from the system; it moves out of the agent's hands and into the connector implementations adopters write deliberately. The safety boundary moves to the connector edge.
|
|
91
|
+
- **Static validation before admission.** A skill that fails the linter can't enter the library. Structural issues , missing dependencies, undeclared variables, mutation paths without confirmation gates are caught at authorship time, not at 3am.
|
|
92
|
+
- **Asymmetric cost.** Routine work (classify, dispatch, transform) costs local-model tokens. The frontier model is reserved for the small fraction of work that actually needs frontier judgment.
|
|
134
93
|
|
|
135
|
-
|
|
94
|
+
## Why not just have the agent write a Skill?
|
|
136
95
|
|
|
137
|
-
|
|
138
|
-
skillfile dashboard
|
|
139
|
-
# → http://127.0.0.1:7878
|
|
140
|
-
```
|
|
96
|
+
Skills (Anthropic/OpenAI) are the existing convention for giving agents named, reusable capabilities, hand-authored markdown that loads instructions into the model's context. They work, and skillscript is complementary to them, not competing.
|
|
141
97
|
|
|
142
|
-
|
|
98
|
+
The problem with hand-authoring is that **both authoring populations produce badly-shaped artifacts when working in prose:**
|
|
143
99
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
skillfile dashboard --host 0.0.0.0 # bind all interfaces (container only)
|
|
147
|
-
```
|
|
100
|
+
- **Agents authoring markdown produce artifacts shaped for humans, not agents** — verbose explanations, hedging language, redundant context-setting, prose where structure would do. The result is expensive to load, noisy to parse, and hard to maintain.
|
|
101
|
+
- **Humans authoring markdown produce the opposite failure modes**. Either ultra-terse and missing context, or kitchen-sink comprehensive in ways that bury the actual procedure under hedges and edge cases.
|
|
148
102
|
|
|
149
|
-
|
|
103
|
+
Making this a programming problem disciplines both populations into the right shape. The grammar doesn't permit rambling. The compiler emits structure, not prose-pretending-to-be-structure.
|
|
150
104
|
|
|
151
|
-
|
|
105
|
+
A skillscript skill **compiles** into an artifact of the same shape as a hand-authored Skill — `# Skill: <name>` header, instructional markdown body — and that artifact can be loaded into an agent's context the same way. Skillscript is what you author *in*; the compiled Skill is what runs. Mature deployments use both: Skills as agent-facing capability descriptions, skillscript as the higher-leverage authoring layer underneath.
|
|
152
106
|
|
|
153
|
-
##
|
|
107
|
+
## Three kinds of skill
|
|
154
108
|
|
|
155
|
-
|
|
109
|
+
Every skillscript skill is one of three shapes, determined by the relationship to a frontier agent:
|
|
156
110
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
111
|
+
| Kind | Output goes to | Use case |
|
|
112
|
+
|---|---|---|
|
|
113
|
+
| **Headless** | a downstream system or human, consumed asynchronously | Cron-fired monitors, batch processors, autonomous workflows |
|
|
114
|
+
| **Augmenting** | a frontier agent's reasoning context, immediately at session start or wake | Session-start briefings, alerts, prepared context |
|
|
115
|
+
| **Template** | a frontier agent's execution loop, as a prompt the agent runs itself | Reusable recipes the agent fetches and follows |
|
|
161
116
|
|
|
162
|
-
|
|
117
|
+
The kinds compose. A Headless monitor fires on cron, evaluates a condition, and routes into an Augmenting skill that wakes an agent with context, which itself references a Template skill for the agent to execute. See the [Language Reference](https://github.com/sshwarts/skillscript-runtime/blob/main/docs/language-reference.md) §1 for the full taxonomy.
|
|
163
118
|
|
|
164
|
-
|
|
165
|
-
docker compose --profile tools run --rm tools lint my-skill.skill.md
|
|
166
|
-
docker compose --profile ollama up # adds Ollama for LocalModel
|
|
167
|
-
```
|
|
119
|
+
### Waking agents
|
|
168
120
|
|
|
169
|
-
|
|
121
|
+
Augmenting and Template skills don't just write somewhere; they deliver to a frontier agent through `AgentConnector`. The contract is substrate-neutral: a Headless monitor detects a condition, evaluates whether action is warranted, and either resolves silently or calls `AgentConnector.deliver(agent_id, payload)`. The implementation might write a memory the agent reads at next session, post to a chat thread the agent monitors, send a push notification, write to a tmux pane, or invoke a webhook. All the adopter's call.
|
|
170
122
|
|
|
171
|
-
|
|
123
|
+
The runtime ships `NoOpAgentConnector` by default; production deployments wire their own.
|
|
172
124
|
|
|
173
|
-
|
|
125
|
+
This is what makes *"Headless monitor → wake agent with context"* a real composition primitive, not just a pattern adopters bolt on. Skills don't know what substrate they're waking into; the substrate doesn't know what skill triggered it. The contract handles the seam.
|
|
174
126
|
|
|
175
|
-
|
|
176
|
-
docker pull ghcr.io/sshwarts/skillscript-runtime:latest
|
|
177
|
-
# or pin to a specific version
|
|
178
|
-
docker pull ghcr.io/sshwarts/skillscript-runtime:v0.2.4
|
|
179
|
-
```
|
|
127
|
+
### Local models as tools for the frontier
|
|
180
128
|
|
|
181
|
-
|
|
129
|
+
Most agent systems treat local models as *substitutes* for frontier inference. Call them instead of the frontier when latency or cost matters. Skillscript treats them as something different: *delegation targets the frontier orchestrates*. The frontier composes the workflow; each `~` op is the frontier dispatching a bounded sub-task (classify a message, extract a field, judge whether two strings refer to the same thing, summarize a chunk, format a response) to a local model and consuming the result.
|
|
182
130
|
|
|
183
|
-
|
|
131
|
+
In skillscript, this isn't a separate "local-model interplay" pattern adopters bolt on — it's a *first-class language operation*. `~ prompt="..." model="qwen" -> RESULT` lives next to `$ tool.call args="..." -> RESULT` in the skill body, with the same op-level discipline, the same trace surface, the same lint coverage. Local models become tools the frontier model can wield through skills, on the same footing as MCP tools and memory reads.
|
|
184
132
|
|
|
185
|
-
|
|
133
|
+
The cost shape that follows: routine work runs at local-model cost (free at scale, fast, private to the host); the frontier model intervenes only at orchestration boundaries and ambiguous cases. Customer data flowing through `~` ops never reaches an external API. The local-model layer becomes the privacy boundary, not a separate add-on.
|
|
186
134
|
|
|
187
|
-
|
|
135
|
+
## What you get
|
|
188
136
|
|
|
189
|
-
|
|
190
|
-
# Skill: weather-brief
|
|
191
|
-
# Status: Approved
|
|
192
|
-
# Vars: CITY=Asheville
|
|
193
|
-
# Requires: user-var:home_location -> CITY (fallback: Asheville)
|
|
194
|
-
# Triggers: cron: */30 * * * *
|
|
137
|
+
**For operators:**
|
|
195
138
|
|
|
196
|
-
|
|
197
|
-
|
|
139
|
+
- *Cost reduction at scale.* Routine operations stop hitting frontier inference. As the library matures, an increasing fraction of agent work executes on cheaper substrate, with the frontier model invoked only for orchestration and judgment.
|
|
140
|
+
- *Auditability.* Agent behavior becomes inspectable by reading skills, not by trusting agent narration. Renderer, linter, and conformance tests operate on parsed skillscript regardless of where it's stored.
|
|
141
|
+
- *Safety boundaries that scale.* The runtime bounds what skills can do via connector configuration, independent of what the authoring agent's tool surface looks like. Mutating operations require explicit user confirmation as a language primitive — visible to static analysis, not dependent on author discipline.
|
|
142
|
+
- *Behavioral consistency.* Procedures don't drift across invocations because the procedure is stored, not re-derived. When the procedure needs to change, the change is a versioned edit, not a hope that the agent reasons identically next time.
|
|
198
143
|
|
|
199
|
-
|
|
200
|
-
if $(CACHED):
|
|
201
|
-
$set FORECAST = $(CACHED)
|
|
202
|
-
else:
|
|
203
|
-
> local-model.complete prompt="Brief weather for $(CITY)" -> FORECAST
|
|
204
|
-
~ memory-store.set key="weather:$(CITY|url)" value=$(FORECAST)
|
|
144
|
+
**For agent capability:**
|
|
205
145
|
|
|
206
|
-
|
|
207
|
-
|
|
146
|
+
- *Reduced token budget on routine work.* Authoring a skill is a one-time cost paid against an indefinite stream of cheap executions.
|
|
147
|
+
- *Composition over re-derivation.* New tasks built by orchestrating existing skills rather than starting from scratch. Capability accumulates rather than evaporating at the end of each invocation.
|
|
208
148
|
|
|
209
|
-
|
|
210
|
-
```
|
|
149
|
+
## The bet
|
|
211
150
|
|
|
212
|
-
|
|
151
|
+
Skillscript bets that **the majority of agent-authored automation work is dispatch-shaped, not computation-shaped**. Neither agents nor humans produce well-shaped procedural artifacts when authoring in prose. Both populations need the structural discipline of a programming language to converge on the right shape for the work, the audience that runs it, and the audit tooling that has to operate on it.
|
|
213
152
|
|
|
214
|
-
|
|
153
|
+
If that bet is wrong, skillscript stays a nice niche tool. If it's right, skillscript becomes a default substrate for agent-fired automation in the same way SQL became the default substrate for data access: declarative, composable, auditable, and outliving any specific runtime underneath it.
|
|
215
154
|
|
|
216
155
|
---
|
|
217
156
|
|
|
218
|
-
##
|
|
219
|
-
|
|
220
|
-
The runtime depends on five pluggable connector contracts:
|
|
157
|
+
## Quickstart
|
|
221
158
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
| `MemoryStore` | Cache + query memory data with TTL | `SqliteMemoryStore` (`node:sqlite`) |
|
|
226
|
-
| `LocalModel` | Dispatch `>` and `~` ops to a local LLM | `OllamaLocalModel` (HTTP to Ollama) |
|
|
227
|
-
| `McpConnector` | Dispatch `$` and `~` ops via MCP tools | `CallbackMcpConnector` (in-process) |
|
|
228
|
-
| `AgentConnector` | Deliver to / wake a frontier agent (T7.1) | `NoOpAgentConnector` (warns + discards) |
|
|
229
|
-
|
|
230
|
-
Wire your own impls through `Registry`:
|
|
231
|
-
|
|
232
|
-
```typescript
|
|
233
|
-
import { Registry } from "skillscript-runtime";
|
|
234
|
-
import { MyRedisSkillStore } from "./my-adapter.js";
|
|
235
|
-
|
|
236
|
-
const registry = new Registry();
|
|
237
|
-
registry.registerSkillStore(new MyRedisSkillStore({ url: "redis://..." }));
|
|
238
|
-
registry.registerLocalModel(new OllamaLocalModel());
|
|
239
|
-
// ... use with execute() or Scheduler
|
|
240
|
-
```
|
|
159
|
+
```bash
|
|
160
|
+
# Install
|
|
161
|
+
npm install -g skillscript-runtime
|
|
241
162
|
|
|
242
|
-
|
|
163
|
+
# Author your first skill
|
|
164
|
+
mkdir -p ./skills && cat > ./skills/hello.skill.md <<'EOF'
|
|
165
|
+
# Skill: hello
|
|
166
|
+
# Status: Approved
|
|
167
|
+
# Vars: WHO=world
|
|
243
168
|
|
|
244
|
-
|
|
169
|
+
greet:
|
|
170
|
+
! Hello, $(WHO)!
|
|
245
171
|
|
|
246
|
-
|
|
172
|
+
default: greet
|
|
173
|
+
EOF
|
|
247
174
|
|
|
248
|
-
|
|
175
|
+
# Start the runtime + dashboard
|
|
176
|
+
SKILLSCRIPT_HOME=./skills skillfile dashboard --port 7878
|
|
249
177
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
SkillStore, MemoryStore, LocalModel, McpConnector, AgentConnector,
|
|
253
|
-
StaticCapabilities, ManifestInfo,
|
|
254
|
-
} from "skillscript-runtime/connectors";
|
|
178
|
+
# In another terminal, run the skill
|
|
179
|
+
skillfile run hello
|
|
255
180
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
return { connector_type: "memory-store", features: { ttl: true, query: true } };
|
|
259
|
-
}
|
|
260
|
-
// ... implement get / set / delete / query / snapshot / manifestInfo
|
|
261
|
-
}
|
|
181
|
+
# Open the dashboard
|
|
182
|
+
open http://localhost:7878
|
|
262
183
|
```
|
|
263
184
|
|
|
264
|
-
|
|
185
|
+
Or via Docker / GHCR:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
docker run -p 7878:7878 -v $(pwd)/skills:/skills \
|
|
189
|
+
-e SKILLSCRIPT_HOME=/skills \
|
|
190
|
+
ghcr.io/sshwarts/skillscript-runtime:latest
|
|
191
|
+
```
|
|
265
192
|
|
|
266
|
-
|
|
193
|
+
## Connector model
|
|
267
194
|
|
|
268
|
-
|
|
195
|
+
Skills don't know what they're talking to. Five contracts decouple language from substrate:
|
|
269
196
|
|
|
270
|
-
|
|
|
197
|
+
| Contract | Purpose | Routes |
|
|
271
198
|
|---|---|---|
|
|
272
|
-
|
|
|
273
|
-
|
|
|
274
|
-
|
|
|
275
|
-
|
|
|
276
|
-
|
|
|
199
|
+
| `SkillStore` | Skill source persistence | `.skill.md` files (filesystem default) |
|
|
200
|
+
| `MemoryStore` | Retrieval over an external knowledge store | `>` ops |
|
|
201
|
+
| `LocalModel` | Local LLM dispatch (Ollama default) | `~` ops |
|
|
202
|
+
| `McpConnector` | MCP tool invocation | `$` ops |
|
|
203
|
+
| `AgentConnector` | Delivery to a frontier agent | `prompt-context:` and `template:` outputs |
|
|
277
204
|
|
|
278
|
-
|
|
205
|
+
Wire your own by implementing the interface and registering in `connectors.json`. See [`docs/language-reference.md`](docs/language-reference.md) §10 for full contracts.
|
|
279
206
|
|
|
207
|
+
## CLI
|
|
280
208
|
|
|
281
|
-
|
|
282
|
-
import { describe } from "vitest";
|
|
283
|
-
import { SkillStoreConformance } from "skillscript-runtime/testing";
|
|
284
|
-
import { MyCloudSkillStore } from "./my-cloud-skill-store.js";
|
|
209
|
+
13 commands cover the full authoring + ops lifecycle:
|
|
285
210
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
211
|
+
| Command | Purpose |
|
|
212
|
+
|---|---|
|
|
213
|
+
| `skillfile compile <path\|name>` | Compile a skill to its rendered artifact |
|
|
214
|
+
| `skillfile audit <path\|name>` | Compile + content-hash check |
|
|
215
|
+
| `skillfile lint <path\|name>` | Tier-1/2/3 lint diagnostics |
|
|
216
|
+
| `skillfile run <path\|name>` | Execute a skill against configured connectors |
|
|
217
|
+
| `skillfile fires <skill>` | Recent fire history with trace IDs |
|
|
218
|
+
| `skillfile diagram <path\|name>` | Mermaid DAG visualization |
|
|
219
|
+
| `skillfile sign <path\|name>` | Generate content-hash signature |
|
|
220
|
+
| `skillfile verify <path\|name> <hash>` | Verify against a known signature |
|
|
221
|
+
| `skillfile replay <trace_id>` | Re-run from a captured trace |
|
|
222
|
+
| `skillfile health` | Aggregate runtime health metrics |
|
|
223
|
+
| `skillfile dashboard [--port N]` | Boot browser dashboard + MCP server |
|
|
224
|
+
| (Trigger management lives in the MCP surface, not the CLI) | |
|
|
225
|
+
|
|
226
|
+
Run `skillfile <command> --help` for per-command flags.
|
|
227
|
+
|
|
228
|
+
## MCP server surface
|
|
229
|
+
|
|
230
|
+
The runtime exposes 11 tools over MCP (HTTP at `/rpc`) for cold-client authoring + observability:
|
|
231
|
+
|
|
232
|
+
| Category | Tools |
|
|
233
|
+
|---|---|
|
|
234
|
+
| Skill management | `skill_list`, `skill_metadata`, `skill_status`, `skill_write` |
|
|
235
|
+
| Authoring | `lint_skill`, `compile_skill` |
|
|
236
|
+
| Triggers | `list_triggers`, `register_trigger`, `unregister_trigger` |
|
|
237
|
+
| Observability | `health_metrics` |
|
|
238
|
+
| Discovery | `runtime_capabilities` |
|
|
290
239
|
|
|
291
|
-
|
|
240
|
+
This is the "agent reaches MCP" path — an external agent (Claude, GPT, anything that speaks MCP) can author, validate, and deploy skills entirely over the wire.
|
|
292
241
|
|
|
293
|
-
##
|
|
242
|
+
## Examples
|
|
294
243
|
|
|
295
|
-
|
|
244
|
+
Seven curated example skills in [`examples/`](examples/), covering:
|
|
296
245
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
246
|
+
- Multi-target DAG with `needs:` dependencies
|
|
247
|
+
- Cron triggers with `# OnError:` fallback
|
|
248
|
+
- Session-start `prompt-context:` delivery
|
|
249
|
+
- `??` interactive ask-user pattern
|
|
250
|
+
- `# Requires:` cascade for compile-time data
|
|
251
|
+
- `&` skill composition
|
|
301
252
|
|
|
302
|
-
|
|
303
|
-
const traceStore = new FilesystemTraceStore("./traces");
|
|
304
|
-
const registry = new Registry();
|
|
305
|
-
registry.registerSkillStore(skillStore);
|
|
253
|
+
Each example is annotated with the language pattern it demonstrates. Authored from spec by cold-context sub-agents — they double as conformance fixtures.
|
|
306
254
|
|
|
307
|
-
|
|
308
|
-
const result = await scheduler.dispatchSkill("hello", { WHO: "Scott" });
|
|
309
|
-
console.log(result.emissions);
|
|
310
|
-
```
|
|
255
|
+
## Architecture and deep documentation
|
|
311
256
|
|
|
312
|
-
|
|
257
|
+
- **[Language Reference](docs/language-reference.md)** — canonical spec (1600+ lines, 13 sections). The single source of truth on syntax + semantics.
|
|
258
|
+
- **ROADMAP** — *coming soon to docs/*
|
|
313
259
|
|
|
314
|
-
|
|
315
|
-
|---|---|
|
|
316
|
-
| `skillscript-runtime` | Main barrel — everything |
|
|
317
|
-
| `skillscript-runtime/connectors` | Connector contracts + Registry + bundled impls |
|
|
318
|
-
| `skillscript-runtime/errors` | `OpError` + subclasses, `LintFailureError`, `ConnectorError` |
|
|
319
|
-
| `skillscript-runtime/runtime` | `execute()` + helpers |
|
|
320
|
-
| `skillscript-runtime/trace` | `TraceStore`, `FilesystemTraceStore`, sampling |
|
|
321
|
-
| `skillscript-runtime/metrics` | `healthMetrics()` aggregator |
|
|
322
|
-
| `skillscript-runtime/scheduler` | `Scheduler` + `TriggerRegistration` |
|
|
323
|
-
| `skillscript-runtime/mcp-server` | `McpServer` + JSON-RPC types |
|
|
324
|
-
| `skillscript-runtime/testing` | Contract conformance suites |
|
|
260
|
+
## Status
|
|
325
261
|
|
|
326
|
-
|
|
262
|
+
**v0.2.6** — pre-1.0, breaking changes expected. The language is stable enough to author production skills; the surrounding tooling (CLI, dashboard, MCP server contract) may evolve before v1.0.
|
|
263
|
+
|
|
264
|
+
Test coverage: 549/549 passing. Narrow-core LOC under the 5000/20-file ceiling per ERD.
|
|
265
|
+
|
|
266
|
+
What's coming next:
|
|
267
|
+
- Comparison operators (`<`, `>`, `<=`, `>=`) and `|length` filter — orchestration carve-out for numeric thresholds
|
|
268
|
+
- Persistent trigger registry on disk — imperative triggers survive process restart
|
|
269
|
+
- `skillfile serve` headless command — scheduler + MCP server without the SPA
|
|
327
270
|
|
|
328
271
|
## Contributing
|
|
329
272
|
|
|
330
|
-
|
|
273
|
+
Bug reports and feature requests welcome via Issues. PRs accepted but please open an Issue first to discuss the design — skillscript's value proposition rests on a constrained grammar, and not every "small extension" earns its keep.
|
|
331
274
|
|
|
332
|
-
|
|
275
|
+
For language design questions, see the cold-agent-driven precedent in [Open spec questions](docs/language-reference.md#open-spec-questions): if cold-context sub-agents writing skills from spec alone hit the same syntactic friction across multiple authors, that's a signal to extend the language.
|
|
333
276
|
|
|
334
|
-
|
|
335
|
-
pnpm run typecheck
|
|
336
|
-
pnpm run loc-check # enforces ERD §1 LOC ceiling
|
|
337
|
-
pnpm test # 473+ tests
|
|
338
|
-
```
|
|
277
|
+
## License
|
|
339
278
|
|
|
340
|
-
|
|
279
|
+
MIT. See [LICENSE](LICENSE).
|
|
341
280
|
|
|
342
281
|
---
|
|
343
282
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
MIT. See [`LICENSE`](./LICENSE).
|
|
283
|
+
*"Made by agents, for agents."* Skills are the agent's programming language.
|
package/dist/cli.js
CHANGED
|
@@ -30,7 +30,7 @@ const MEMORY_DB = join(HOME_DIR, "memory.db");
|
|
|
30
30
|
const EXAMPLES_DIR = join(HOME_DIR, "examples");
|
|
31
31
|
const PLUGINS_DIR = join(HOME_DIR, "plugins");
|
|
32
32
|
const TRACE_DIR = join(HOME_DIR, "traces");
|
|
33
|
-
const VERSION = "0.2.
|
|
33
|
+
const VERSION = "0.2.6";
|
|
34
34
|
const COMMAND_HELP = {
|
|
35
35
|
init: {
|
|
36
36
|
description: "Scaffold ~/.skillscript/ tree + bundled example",
|
|
@@ -1,18 +1,42 @@
|
|
|
1
1
|
import type { StaticCapabilities, ManifestInfo } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Provenance record threaded onto every `DeliveryPayload` so the receiving
|
|
4
|
+
* agent can disambiguate "what fired this delivery" — was it cron-scheduled?
|
|
5
|
+
* a session boundary? a user-triggered manual run? v0.2.6 addition per the
|
|
6
|
+
* AgentConnector polish in Perry's thread `f75477a4`.
|
|
7
|
+
*/
|
|
8
|
+
export interface TriggerProvenance {
|
|
9
|
+
source: "cron" | "session" | "event" | "agent-event" | "file-watch" | "sensor" | "manual";
|
|
10
|
+
/** Source-specific value: cron expression, session phase, event name, etc. */
|
|
11
|
+
name: string;
|
|
12
|
+
/** Unix-ms timestamp the trigger fired. */
|
|
13
|
+
fired_at_ms: number;
|
|
14
|
+
}
|
|
2
15
|
/**
|
|
3
16
|
* Discriminated payload union for `deliver`. The runtime picks `kind`
|
|
4
17
|
* based on the source declaration:
|
|
5
18
|
* - `# Output: prompt-context: <agent>` → `{ kind: "augment", ... }`
|
|
6
19
|
* - `# Output: template: <agent>` → `{ kind: "template", ... }`
|
|
20
|
+
*
|
|
21
|
+
* Common-shaped provenance + augmenting-context fields apply to both
|
|
22
|
+
* variants (v0.2.6 addition). `source_skill` was template-only in T7.1;
|
|
23
|
+
* now lives on both.
|
|
7
24
|
*/
|
|
8
25
|
export type DeliveryPayload = {
|
|
9
26
|
kind: "augment";
|
|
10
27
|
content: string;
|
|
11
28
|
format?: "text" | "markdown";
|
|
29
|
+
source_skill?: string;
|
|
30
|
+
triggered_by?: TriggerProvenance;
|
|
31
|
+
delivery_context?: string;
|
|
32
|
+
templates?: string[];
|
|
12
33
|
} | {
|
|
13
34
|
kind: "template";
|
|
14
35
|
prompt: string;
|
|
15
36
|
source_skill?: string;
|
|
37
|
+
triggered_by?: TriggerProvenance;
|
|
38
|
+
delivery_context?: string;
|
|
39
|
+
templates?: string[];
|
|
16
40
|
};
|
|
17
41
|
export interface DeliveryReceipt {
|
|
18
42
|
/** Unix-ms timestamp the substrate accepted the delivery. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/connectors/agent.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEnE;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GACvB;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/connectors/agent.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEnE;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,GAAG,YAAY,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC1F,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,eAAe,GACvB;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB,GACD;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAEN,MAAM,WAAW,eAAe;IAC9B,6DAA6D;IAC7D,YAAY,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,IAAI,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,aAAa,CAAC,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC,CAAC;CAC3E;AAED,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEnE;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,WAAW,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IAC1C,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAC9E,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9D,YAAY,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACtD,QAAQ,IAAI,OAAO,CAAC,YAAY,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,cAAc,CAAC;IACvC,kBAAkB,IAAI,kBAAkB,CAAC;CAC1C"}
|