noskills 4.1.27 → 4.1.29
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 +659 -2
- package/chunks/approve-UATWGG53.js +1 -0
- package/chunks/{ask-Q7AVFBH5.js → ask-5YIOZTBI.js} +1 -1
- package/chunks/block-IDVJLPNV.js +1 -0
- package/chunks/chunk-52HFDP2R.js +39 -0
- package/chunks/chunk-6XR33H6Q.js +2 -0
- package/chunks/chunk-C2SQE5AG.js +1 -0
- package/chunks/chunk-D6Q2GR7X.js +1 -0
- package/chunks/chunk-FAK366X2.js +1 -0
- package/chunks/chunk-G2NW625V.js +4 -0
- package/chunks/{chunk-N4POD6ZW.js → chunk-G65TSD56.js} +1 -1
- package/chunks/chunk-LEPZPNTN.js +12 -0
- package/chunks/chunk-MJVACJ6D.js +144 -0
- package/chunks/chunk-O3PI76HM.js +3 -0
- package/chunks/chunk-OM4QJ24S.js +1 -0
- package/chunks/chunk-QHS53BRV.js +3 -0
- package/chunks/chunk-SBUQXH6U.js +1 -0
- package/chunks/{chunk-FEWVQ5CW.js → chunk-SOMEQCOS.js} +1 -1
- package/chunks/{chunk-RAI7PS2P.js → chunk-UWD66JGG.js} +1 -1
- package/chunks/chunk-UXRWSNVZ.js +1 -0
- package/chunks/chunk-XHFYREAD.js +1 -0
- package/chunks/{claude-code-AFPWU2BS.js → claude-code-Z7LYZDY5.js} +1 -1
- package/chunks/concern-JUE2IFQI.js +1 -0
- package/chunks/done-LOYNEBUX.js +1 -0
- package/chunks/init-FMAEQACG.js +1 -0
- package/chunks/invoke-hook-2VRIZ4VU.js +9 -0
- package/chunks/{kiro-WSWAMBP2.js → kiro-C7DKUCGL.js} +1 -1
- package/chunks/list-U5OS3WZ4.js +1 -0
- package/chunks/mod-RWDPEKPY.js +1 -0
- package/chunks/next-WEQWWHMJ.js +3 -0
- package/chunks/{ollama-ZD3BKKDE.js → ollama-HRLYSKFN.js} +1 -1
- package/chunks/{opencode-TJR46E7H.js → opencode-QKZUHQHY.js} +1 -1
- package/chunks/purge-AISADFMA.js +4 -0
- package/chunks/reset-2II5XIWI.js +1 -0
- package/chunks/rule-3UTOQ32B.js +2 -0
- package/chunks/run-EP6XJQXK.js +3 -0
- package/chunks/spec-BLGJLET3.js +1 -0
- package/chunks/status-K2DRYXDX.js +1 -0
- package/chunks/sync-NR33ZH7R.js +1 -0
- package/chunks/watch-DTNAKL6O.js +8 -0
- package/noskills.js +1 -1
- package/package.json +1 -1
- package/chunks/approve-JJTQKJU6.js +0 -1
- package/chunks/block-4I5XBXK7.js +0 -1
- package/chunks/chunk-BK2BDHKB.js +0 -1
- package/chunks/chunk-JYJTZEC4.js +0 -32
- package/chunks/chunk-LXVBR775.js +0 -1
- package/chunks/chunk-NGURBONB.js +0 -6
- package/chunks/chunk-PQQKC72V.js +0 -10
- package/chunks/init-QCOPTDGO.js +0 -1
- package/chunks/list-UVJ2Q5KF.js +0 -1
- package/chunks/next-DNJGG34Q.js +0 -3
- package/chunks/reset-WLKKKEUZ.js +0 -1
- package/chunks/rule-3VERAMM3.js +0 -2
- package/chunks/spec-P6YE224I.js +0 -1
- package/chunks/status-CJMMUOTY.js +0 -1
- package/chunks/sync-BZ3Z5YQP.js +0 -1
package/README.md
CHANGED
|
@@ -1,3 +1,660 @@
|
|
|
1
|
-
# noskills
|
|
1
|
+
# [@eser/noskills](./)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
State-machine orchestrator for AI coding agents. Instead of loading skills into
|
|
4
|
+
context and hoping the agent picks the right one, noskills pushes exactly the
|
|
5
|
+
right instruction at the right time — the agent never decides what to do next,
|
|
6
|
+
the state machine does.
|
|
7
|
+
|
|
8
|
+
## Why
|
|
9
|
+
|
|
10
|
+
AI coding agents have a context rot problem. The more skills, rules, and
|
|
11
|
+
conventions you load upfront, the worse the agent performs — its context window
|
|
12
|
+
fills with instructions it doesn't need yet, and it forgets the ones it does.
|
|
13
|
+
|
|
14
|
+
Skills are a "pull" model: the agent decides which skill to load. This creates
|
|
15
|
+
two failure modes — picking the wrong skill (wasted context) and needing
|
|
16
|
+
meta-knowledge to pick the right one (more context to waste).
|
|
17
|
+
|
|
18
|
+
noskills is a "push" model:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
Agent <- stdout (JSON) <- noskills CLI <- filesystem (state + concerns + rules)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The agent calls `noskills next`, gets exactly what it needs for the current
|
|
25
|
+
phase, acts on it, and calls `noskills next` again. No skill selection, no
|
|
26
|
+
context pollution, no forgetting.
|
|
27
|
+
|
|
28
|
+
## The Mental Model
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
.cursorrules -> .cursor/rules/*.mdc -> eser/rules + skills -> noskills
|
|
32
|
+
(1 file) (modular, 1 tool) (portable, curated) (state-driven)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Each generation solved one bottleneck and discovered the next:
|
|
36
|
+
|
|
37
|
+
1. **`.cursorrules`** — single file, single tool. Couldn't split, couldn't
|
|
38
|
+
scale, couldn't travel across tools.
|
|
39
|
+
2. **`.cursor/rules/*.mdc`** — modular, but still locked to Cursor.
|
|
40
|
+
3. **`eser/rules` + `eser-rules-manager`** — created as a portable,
|
|
41
|
+
tool-agnostic instruction system. This **predated** Anthropic's Skills spec.
|
|
42
|
+
When Skills arrived, eser/rules was adapted into skills format — validating
|
|
43
|
+
the ecosystem was heading where eser/rules had already gone.
|
|
44
|
+
4. **noskills** — Skills brought new limits: context rot as skills accumulated,
|
|
45
|
+
agents making wrong skill choices, manual sync across tools. noskills drops
|
|
46
|
+
skills entirely in favor of state-driven context injection.
|
|
47
|
+
|
|
48
|
+
The `eser/rules` repository
|
|
49
|
+
([github.com/eser/rules](https://github.com/eser/rules)) is now archived. Its
|
|
50
|
+
ideas live on in noskills, refined under
|
|
51
|
+
[github.com/eser/stack](https://github.com/eser/stack).
|
|
52
|
+
|
|
53
|
+
This is the **SW3** (Software Cubed) philosophy: build, discover limits, evolve,
|
|
54
|
+
share. noskills will discover its own limits too — and when it does, the next
|
|
55
|
+
step will emerge. If you want to discover those limits together, jump on board.
|
|
56
|
+
|
|
57
|
+
The name mirrors the SQL -> NoSQL shift: skills define everything upfront,
|
|
58
|
+
noskills determines what's needed at runtime.
|
|
59
|
+
|
|
60
|
+
## Quick Start
|
|
61
|
+
|
|
62
|
+
### With an agent (Claude Code, Cursor, etc.)
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
eser noskills init # Scaffold .eser/, detect tools
|
|
66
|
+
eser noskills concern add open-source # Activate concerns
|
|
67
|
+
eser noskills spec new "photo upload" # Start spec -> DISCOVERY
|
|
68
|
+
# Agent takes over: calls noskills next, answers questions,
|
|
69
|
+
# builds to spec, reports progress. You approve transitions.
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
After `init`, your CLAUDE.md (or .cursorrules, etc.) tells the agent to call
|
|
73
|
+
`noskills next` at every step. The agent follows the JSON output. You never need
|
|
74
|
+
to prompt-engineer the agent's behavior — noskills handles that.
|
|
75
|
+
|
|
76
|
+
### Without an agent (agentless CLI mode)
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
eser noskills init
|
|
80
|
+
eser noskills concern add beautiful-product
|
|
81
|
+
eser noskills spec new "photo upload"
|
|
82
|
+
eser noskills next -o text # Shows Q1 in plain text
|
|
83
|
+
eser noskills next --answer="users drag files manually" -o text
|
|
84
|
+
eser noskills next -o text # Shows Q2
|
|
85
|
+
# ... answer all 6 questions ...
|
|
86
|
+
eser noskills approve
|
|
87
|
+
eser noskills next --answer="start" -o text # Begin execution
|
|
88
|
+
eser noskills next --answer="task-1 done" -o text
|
|
89
|
+
# noskills asks for status report against acceptance criteria
|
|
90
|
+
eser noskills next --answer='{"completed":["endpoint works"],"remaining":["error UI"]}' -o text
|
|
91
|
+
# debt carries forward to next iteration
|
|
92
|
+
eser noskills status -o markdown
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The entire lifecycle works without any agent. noskills is the orchestrator —
|
|
96
|
+
agents and humans are both consumers.
|
|
97
|
+
|
|
98
|
+
Both CLI and agent write to the same state. You can start discovery via CLI
|
|
99
|
+
(answering questions in the terminal), close the terminal, open an agent session
|
|
100
|
+
later, and the agent picks up from the last answered question. Or start with an
|
|
101
|
+
agent and finish via CLI. noskills doesn't care who's driving — it checks state
|
|
102
|
+
and continues from wherever it left off.
|
|
103
|
+
|
|
104
|
+
### Autonomous execution (Ralph loop)
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
eser noskills run # Spawns fresh claude -p per iteration
|
|
108
|
+
eser noskills run --unattended # Stops at BLOCKED, logs to file
|
|
109
|
+
eser noskills run --max-iterations=20 # Safety valve
|
|
110
|
+
eser noskills run --max-turns=15 # Turns per agent process
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Each iteration is a fresh `claude -p` process with zero context accumulation.
|
|
114
|
+
State persists in `.eser/.state/state.json` between iterations. The Stop hook
|
|
115
|
+
snapshots git state automatically. Verification backpressure prevents advancing
|
|
116
|
+
past broken tests. When `autoCommit: true` in `manifest.yml`, the `noskills run`
|
|
117
|
+
CLI loop handles git commits between iterations — the agent never touches git.
|
|
118
|
+
Git write operations are the CLI's responsibility, never the agent's.
|
|
119
|
+
|
|
120
|
+
### Live monitoring
|
|
121
|
+
|
|
122
|
+
While an agent works, open another terminal:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
eser noskills watch # Live terminal dashboard
|
|
126
|
+
eser noskills watch -o json # JSON lines per state change (pipeable)
|
|
127
|
+
eser noskills watch -o markdown # Markdown per update
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The dashboard shows: active spec, phase, progress bar, iteration count, time
|
|
131
|
+
since last update, outstanding debt items, files changed this iteration, concern
|
|
132
|
+
list, and context warning. Entirely filesystem-driven — watches `.eser/.state/`
|
|
133
|
+
for changes. Zero LLM tokens. Exits automatically when phase reaches DONE.
|
|
134
|
+
|
|
135
|
+
## How It Works
|
|
136
|
+
|
|
137
|
+
### The State Machine
|
|
138
|
+
|
|
139
|
+
Every spec follows a deterministic phase flow:
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
IDLE -> DISCOVERY -> SPEC_DRAFT -> SPEC_APPROVED -> EXECUTING <-> BLOCKED
|
|
143
|
+
^ |
|
|
144
|
+
+------------------------- DONE <-----------------------+
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
| Phase | What happens |
|
|
148
|
+
| ----------------- | ---------------------------------------------------------------------- |
|
|
149
|
+
| **IDLE** | No active spec. Start one with `noskills spec new "..."` |
|
|
150
|
+
| **DISCOVERY** | 6 blended questions probe product, engineering, and QA simultaneously |
|
|
151
|
+
| **SPEC_DRAFT** | Spec generated from discovery answers. Human reviews |
|
|
152
|
+
| **SPEC_APPROVED** | Spec approved, waiting to start. A deliberate "ready but not yet" gate |
|
|
153
|
+
| **EXECUTING** | Agent works through the spec. Reports progress each iteration |
|
|
154
|
+
| **BLOCKED** | Agent hit a decision it can't make alone. Human resolves |
|
|
155
|
+
| **DONE** | Spec complete. Summary with iteration count and decisions |
|
|
156
|
+
|
|
157
|
+
### Phase Transition Protocol
|
|
158
|
+
|
|
159
|
+
Every phase transition follows the same structured cycle:
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
Human input -> Agent A evaluates -> Agent B validates (optional) -> Human approves -> Next phase
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
This is universal — DISCOVERY -> SPEC_DRAFT, SPEC_DRAFT -> SPEC_APPROVED,
|
|
166
|
+
BLOCKED -> EXECUTING, every transition. The human always has final say.
|
|
167
|
+
|
|
168
|
+
Agent B validation is opt-in per command (`noskills next --validate`) or as a
|
|
169
|
+
project default in `manifest.yml`. When validation is active, noskills spawns
|
|
170
|
+
Agent B via the Agent Bridge with completely isolated context — Agent B never
|
|
171
|
+
sees Agent A's conversation history. This is real generator/judge separation,
|
|
172
|
+
not role-played.
|
|
173
|
+
|
|
174
|
+
### The JSON Output
|
|
175
|
+
|
|
176
|
+
Every `noskills next` call returns a structured JSON payload:
|
|
177
|
+
|
|
178
|
+
```jsonc
|
|
179
|
+
{
|
|
180
|
+
"phase": "EXECUTING",
|
|
181
|
+
"instruction": "Execute the current task. When done, report progress.",
|
|
182
|
+
"task": {
|
|
183
|
+
"id": "task-2",
|
|
184
|
+
"title": "Add photo upload endpoint with validation",
|
|
185
|
+
"totalTasks": 5,
|
|
186
|
+
"completedTasks": 1
|
|
187
|
+
},
|
|
188
|
+
"meta": {
|
|
189
|
+
"protocol": "Run `eser noskills next --answer=\"...\"` to submit results and advance",
|
|
190
|
+
"spec": "photo-upload",
|
|
191
|
+
"branch": null,
|
|
192
|
+
"iteration": 3,
|
|
193
|
+
"lastProgress": "implemented auth module",
|
|
194
|
+
"activeConcerns": ["open-source", "beautiful-product"],
|
|
195
|
+
"resumeHint": "Executing \"photo-upload\", iteration 3. Last progress: implemented auth module. Continue with the current task."
|
|
196
|
+
},
|
|
197
|
+
"behavioral": {
|
|
198
|
+
"rules": [
|
|
199
|
+
"NEVER run git write commands. Git is read-only for agents.",
|
|
200
|
+
"Do not explore the codebase beyond what the current task requires.",
|
|
201
|
+
"Do not refactor, improve, or modify code outside this task's scope.",
|
|
202
|
+
"Complete the task, then report progress. The user handles git."
|
|
203
|
+
],
|
|
204
|
+
"tone": "Direct. No preamble. Start coding immediately."
|
|
205
|
+
},
|
|
206
|
+
"context": {
|
|
207
|
+
"rules": ["Use Deno for all TypeScript"],
|
|
208
|
+
"concernReminders": [
|
|
209
|
+
"open-source: Endpoint should be documented in API docs",
|
|
210
|
+
"beautiful-product: Loading and error states must be designed, not placeholder"
|
|
211
|
+
]
|
|
212
|
+
},
|
|
213
|
+
"transition": {
|
|
214
|
+
"onComplete": "eser noskills next --answer=\"...\"",
|
|
215
|
+
"onBlocked": "eser noskills block \"reason\"",
|
|
216
|
+
"iteration": 3
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
The `meta.resumeHint` is designed for cold starts — a fresh agent (or human)
|
|
222
|
+
reading the output for the first time can orient themselves without any prior
|
|
223
|
+
context. On stale sessions (>5 min since last call), a `protocolGuide` block
|
|
224
|
+
appears explaining what noskills is and how phases work.
|
|
225
|
+
|
|
226
|
+
When concerns conflict, the output includes a tension block:
|
|
227
|
+
|
|
228
|
+
```jsonc
|
|
229
|
+
{
|
|
230
|
+
"phase": "EXECUTING",
|
|
231
|
+
"concernTensions": [{
|
|
232
|
+
"between": ["move-fast", "compliance"],
|
|
233
|
+
"issue": "Skipping audit log saves ~2h but violates compliance concern."
|
|
234
|
+
}]
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Tensions require human resolution — noskills never auto-resolves them.
|
|
239
|
+
|
|
240
|
+
### Output Formats
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
noskills next # JSON (default, for agents and pipes)
|
|
244
|
+
noskills next -o json # Explicit JSON
|
|
245
|
+
noskills next -o markdown # Human-readable with headings and checklists
|
|
246
|
+
noskills next -o text # Plain text, no formatting
|
|
247
|
+
noskills status -o json # Structured status for scripts
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Behavioral Guardrails
|
|
251
|
+
|
|
252
|
+
Every `noskills next` output includes a `behavioral` block with phase-specific
|
|
253
|
+
rules. These tell the agent HOW to behave, not just WHAT to do:
|
|
254
|
+
|
|
255
|
+
| Phase | Behavioral tone | Key rules |
|
|
256
|
+
| ---------- | ------------------------------ | ------------------------------------------------------------ |
|
|
257
|
+
| DISCOVERY | "You are a messenger" | Don't rephrase questions, relay answers verbatim, don't code |
|
|
258
|
+
| SPEC_DRAFT | "The user is reviewing" | Don't modify the spec, don't start coding |
|
|
259
|
+
| EXECUTING | "Start coding immediately" | Don't explore beyond scope, don't refactor, timebox reading |
|
|
260
|
+
| BLOCKED | "Brief. Decision time." | Present decision as-is, don't suggest preferences |
|
|
261
|
+
| DONE | "Celebrate briefly, then stop" | Don't start new work |
|
|
262
|
+
|
|
263
|
+
**Git is read-only** for agents (configurable via `allowGit: true` in manifest).
|
|
264
|
+
Agents may read (`git log`, `git diff`, `git status`) but never write
|
|
265
|
+
(`git commit`, `git push`, `git checkout`). This is enforced at three levels:
|
|
266
|
+
behavioral rules, CLAUDE.md instruction, and PreToolUse hook.
|
|
267
|
+
|
|
268
|
+
When the agent's iteration count exceeds `maxIterationsBeforeRestart` (default
|
|
269
|
+
15), an `urgency` message warns that context is degrading and recommends a fresh
|
|
270
|
+
session.
|
|
271
|
+
|
|
272
|
+
**Convention discovery:** When the agent identifies a recurring pattern,
|
|
273
|
+
receives a correction from the user, or discovers a preference during work, the
|
|
274
|
+
behavioral rules instruct it to ask: _"Should this be a permanent rule for this
|
|
275
|
+
project, or just for this task?"_ If permanent, the agent runs
|
|
276
|
+
`noskills rule add`. If just this task, it notes and moves on. The agent never
|
|
277
|
+
writes to `.eser/rules/` directly — noskills handles file creation and sync.
|
|
278
|
+
|
|
279
|
+
### Concerns — The Project's DNA
|
|
280
|
+
|
|
281
|
+
Concerns define what your project IS. They stack on top of each other and affect
|
|
282
|
+
discovery questions, spec sections, execution reminders, and acceptance
|
|
283
|
+
criteria:
|
|
284
|
+
|
|
285
|
+
| Concern | Effect |
|
|
286
|
+
| --------------------- | --------------------------------------------------------------------- |
|
|
287
|
+
| **open-source** | Prioritize contributor experience, default to permissive choices |
|
|
288
|
+
| **beautiful-product** | Every UI state specified — empty, loading, error, success. No AI slop |
|
|
289
|
+
| **long-lived** | Favor boring technology, every shortcut needs justification |
|
|
290
|
+
| **move-fast** | Good enough is good enough, defer polish to v2 |
|
|
291
|
+
| **compliance** | Every state change must be traceable, verification is mandatory |
|
|
292
|
+
| **learning-project** | Experimentation encouraged, document learnings over polish |
|
|
293
|
+
|
|
294
|
+
Concerns inject:
|
|
295
|
+
|
|
296
|
+
- **Discovery extras** — sub-questions per concern per question
|
|
297
|
+
- **Spec sections** — e.g., beautiful-product adds "Design States (empty,
|
|
298
|
+
loading, error, success)"
|
|
299
|
+
- **Execution reminders** — per-iteration context hints
|
|
300
|
+
- **Acceptance criteria** — checked during status reports before task is
|
|
301
|
+
accepted
|
|
302
|
+
|
|
303
|
+
When concerns conflict (e.g., move-fast + compliance), noskills surfaces the
|
|
304
|
+
tension to the human rather than resolving it silently.
|
|
305
|
+
|
|
306
|
+
### Decision Lifecycle
|
|
307
|
+
|
|
308
|
+
When an agent encounters a decision during any phase:
|
|
309
|
+
|
|
310
|
+
1. Agent reports it needs a decision (via `noskills block` or within `next`
|
|
311
|
+
output).
|
|
312
|
+
2. noskills routes the decision to the human.
|
|
313
|
+
3. Human answers.
|
|
314
|
+
4. noskills asks: _"Should this be a permanent rule for this project, or just
|
|
315
|
+
for this spec?"_
|
|
316
|
+
5. If permanent -> `noskills rule add` is called internally -> writes to
|
|
317
|
+
`.eser/rules/` -> triggers sync.
|
|
318
|
+
6. If just this spec -> recorded in the spec's decisions table only.
|
|
319
|
+
|
|
320
|
+
This creates an organic growth loop: as you build specs, your rule set evolves.
|
|
321
|
+
New team members and AI agents automatically inherit accumulated decisions.
|
|
322
|
+
One-time decisions stay scoped to their spec — they never leak into other specs.
|
|
323
|
+
|
|
324
|
+
The spec file tracks decisions:
|
|
325
|
+
|
|
326
|
+
```markdown
|
|
327
|
+
## Decisions
|
|
328
|
+
|
|
329
|
+
| # | Decision | Choice | Type |
|
|
330
|
+
| - | ------------------ | ------------- | --------------- |
|
|
331
|
+
| 1 | Validation library | Zod | rule (promoted) |
|
|
332
|
+
| 2 | Image API provider | OpenAI Vision | one-time |
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Verification Backpressure
|
|
336
|
+
|
|
337
|
+
When the agent reports a task complete, noskills doesn't take its word for it.
|
|
338
|
+
|
|
339
|
+
1. **Automated verification** runs first (configurable via `verifyCommand` in
|
|
340
|
+
manifest, e.g., `"deno test"`). If tests fail, the task is rejected and the
|
|
341
|
+
failure output is returned as the next instruction.
|
|
342
|
+
|
|
343
|
+
2. **Status report** requested against acceptance criteria — items from the spec
|
|
344
|
+
plus concern-injected criteria (e.g., "All UI states designed" from
|
|
345
|
+
beautiful-product). The agent checks off what's done and reports what
|
|
346
|
+
remains.
|
|
347
|
+
|
|
348
|
+
3. **Debt carry-forward** — remaining items persist across iterations as debt.
|
|
349
|
+
Every subsequent `noskills next` output includes the debt with "Address these
|
|
350
|
+
BEFORE starting new work." Debt is never silently removed — only an explicit
|
|
351
|
+
status report listing items as completed clears them. If debt items remain
|
|
352
|
+
unaddressed for 3+ iterations, noskills escalates — the debt block gains an
|
|
353
|
+
urgency field warning that these items have been outstanding for N iterations
|
|
354
|
+
and must be addressed before any new work.
|
|
355
|
+
|
|
356
|
+
4. **Context clearing** — when debt is zero and verification passes, noskills
|
|
357
|
+
emits a `clearContext` action telling the agent to `/clear` for fresh context
|
|
358
|
+
on the next task. A `pendingClear` flag blocks all file edits until the agent
|
|
359
|
+
complies.
|
|
360
|
+
|
|
361
|
+
### Scoped Folder Rules
|
|
362
|
+
|
|
363
|
+
In monorepos, different packages have different constraints. Drop a
|
|
364
|
+
`.folder-rules.md` in any directory with markdown bullet rules:
|
|
365
|
+
|
|
366
|
+
```markdown
|
|
367
|
+
- Generated CLAUDE.md must preserve existing content outside noskills:start/end
|
|
368
|
+
markers
|
|
369
|
+
- All command references must use dynamic noskillsCmd prefix
|
|
370
|
+
- Sync output must be idempotent
|
|
371
|
+
- Hook scripts must be self-contained
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
When the agent modifies files in that directory (tracked via the post-file-write
|
|
375
|
+
hook log), noskills adds those rules to the acceptance criteria during status
|
|
376
|
+
reports:
|
|
377
|
+
|
|
378
|
+
```
|
|
379
|
+
(folder: pkg/@eser/noskills/sync) Sync output must be idempotent
|
|
380
|
+
(folder: pkg/@eser/noskills/sync) Hook scripts must be self-contained
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
Rules stack upward — `.folder-rules.md` files in parent directories also apply,
|
|
384
|
+
like CSS specificity. A rule at `pkg/` applies to all files under `pkg/`, while
|
|
385
|
+
a rule at `pkg/@eser/streams/` applies only to that package. Zero token cost —
|
|
386
|
+
derived from filesystem, not LLM.
|
|
387
|
+
|
|
388
|
+
### Discovery Questions
|
|
389
|
+
|
|
390
|
+
Six questions, each probing product + engineering + QA at once:
|
|
391
|
+
|
|
392
|
+
1. **What does the user do today without this feature?**
|
|
393
|
+
2. **Describe the 1-star and 10-star versions.**
|
|
394
|
+
3. **Does this change involve an irreversible decision?**
|
|
395
|
+
4. **Does this change affect existing users' behavior?**
|
|
396
|
+
5. **How do you verify this works correctly?**
|
|
397
|
+
6. **What should this feature NOT do?**
|
|
398
|
+
|
|
399
|
+
Active concerns inject sub-questions. For example, with `open-source` active,
|
|
400
|
+
question 1 also asks: _"Is this workaround common in the community?"_
|
|
401
|
+
|
|
402
|
+
### Spec Classification
|
|
403
|
+
|
|
404
|
+
After discovery answers are submitted, noskills asks the user to classify the
|
|
405
|
+
spec along four boolean axes:
|
|
406
|
+
|
|
407
|
+
| Flag | What it controls |
|
|
408
|
+
| ---------------------- | ------------------------------------------------------- |
|
|
409
|
+
| `involvesUI` | UI state sections from beautiful-product concern |
|
|
410
|
+
| `involvesPublicAPI` | API documentation sections from open-source concern |
|
|
411
|
+
| `involvesMigration` | Migration checklist sections from compliance/long-lived |
|
|
412
|
+
| `involvesDataHandling` | Data safety sections from compliance concern |
|
|
413
|
+
|
|
414
|
+
Classification determines which concern sections appear in the generated spec.
|
|
415
|
+
Irrelevant sections are skipped entirely — a backend API change won't get UI
|
|
416
|
+
state checklists, and a CSS tweak won't get migration warnings. This replaces
|
|
417
|
+
keyword-based guessing with explicit user input.
|
|
418
|
+
|
|
419
|
+
The classification is submitted as JSON via `noskills next`:
|
|
420
|
+
|
|
421
|
+
```bash
|
|
422
|
+
noskills next --answer='{"involvesUI":true,"involvesPublicAPI":false,"involvesMigration":false,"involvesDataHandling":false}'
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### Hooks — Zero-Token Bookkeeping
|
|
426
|
+
|
|
427
|
+
noskills installs Claude Code hooks that handle state bookkeeping without
|
|
428
|
+
spending LLM tokens:
|
|
429
|
+
|
|
430
|
+
| Hook | Event | What it does |
|
|
431
|
+
| ------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
432
|
+
| **pre-tool-use** | PreToolUse | Blocks file edits outside EXECUTING phase. Blocks git write commands. Blocks edits when pendingClear is set. |
|
|
433
|
+
| **stop** | Stop | Increments iteration counter, snapshots `git diff` into state, checks restart threshold. The Ralph loop's heartbeat. |
|
|
434
|
+
| **post-file-write** | PostToolUse | Logs modified file paths to `.eser/.state/files-changed.jsonl` |
|
|
435
|
+
| **post-bash** | PostToolUse | Logs noskills CLI invocations for observability |
|
|
436
|
+
|
|
437
|
+
Hooks are CLI subcommands (`noskills invoke-hook <name>`), not generated script
|
|
438
|
+
files. This avoids ESM/CJS issues — the same Deno entry point handles
|
|
439
|
+
everything.
|
|
440
|
+
|
|
441
|
+
The agent is completely unaware hooks exist. Hooks derive progress from
|
|
442
|
+
filesystem and git state — the agent doesn't waste tokens summarizing what it
|
|
443
|
+
did.
|
|
444
|
+
|
|
445
|
+
### Tool Sync — One Source of Truth
|
|
446
|
+
|
|
447
|
+
noskills generates instruction files for every AI tool your team uses:
|
|
448
|
+
|
|
449
|
+
```
|
|
450
|
+
.eser/ (single source of truth)
|
|
451
|
+
+-- noskills sync
|
|
452
|
+
|-- -> CLAUDE.md (Claude Code)
|
|
453
|
+
|-- -> .cursorrules (Cursor)
|
|
454
|
+
|-- -> .kiro/steering/ (Kiro)
|
|
455
|
+
|-- -> .github/copilot-instructions.md (GitHub Copilot)
|
|
456
|
+
+-- -> .windsurfrules (Windsurf)
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
Write your rules once in `.eser/rules/`, run `noskills sync`, and every tool
|
|
460
|
+
gets the same instructions in its native format.
|
|
461
|
+
|
|
462
|
+
Generated CLAUDE.md includes:
|
|
463
|
+
|
|
464
|
+
- Protocol instructions with 5 concrete trigger points
|
|
465
|
+
- Git read-only section (unless `allowGit: true`)
|
|
466
|
+
- Active rules
|
|
467
|
+
- JSON output explanation
|
|
468
|
+
|
|
469
|
+
### Spec Management
|
|
470
|
+
|
|
471
|
+
```bash
|
|
472
|
+
# Create with auto-generated slug
|
|
473
|
+
noskills spec new "photo upload feature"
|
|
474
|
+
# -> .eser/specs/photo-upload-feature/spec.md
|
|
475
|
+
|
|
476
|
+
# Create with explicit name
|
|
477
|
+
noskills spec new --name=SPC0001 "photo upload feature"
|
|
478
|
+
# -> .eser/specs/SPC0001/spec.md
|
|
479
|
+
|
|
480
|
+
# List all specs with status
|
|
481
|
+
noskills spec list
|
|
482
|
+
# . photo-upload-feature EXECUTING iteration 3
|
|
483
|
+
# fix-login-bug SPEC_DRAFT
|
|
484
|
+
# SPC0001 DONE
|
|
485
|
+
|
|
486
|
+
# Switch between specs (preserves state)
|
|
487
|
+
noskills spec switch fix-login-bug
|
|
488
|
+
# Active spec: fix-login-bug (SPEC_DRAFT)
|
|
489
|
+
|
|
490
|
+
# JSON output for scripts
|
|
491
|
+
noskills spec list -o json
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
Multiple specs can exist at different stages. Switching away from an EXECUTING
|
|
495
|
+
spec preserves everything — iteration, debt, verification result, progress.
|
|
496
|
+
Switching back resumes exactly where it left off.
|
|
497
|
+
|
|
498
|
+
## CLI Reference
|
|
499
|
+
|
|
500
|
+
```bash
|
|
501
|
+
# Via eser CLI
|
|
502
|
+
eser noskills <command>
|
|
503
|
+
|
|
504
|
+
# Standalone
|
|
505
|
+
deno run --allow-all jsr:@eser/noskills <command>
|
|
506
|
+
|
|
507
|
+
# Alias
|
|
508
|
+
eser nos <command>
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
### Commands
|
|
512
|
+
|
|
513
|
+
| Command | Description |
|
|
514
|
+
| ----------------------------- | ------------------------------------------------------------------ |
|
|
515
|
+
| `init` | Scaffold `.eser/`, detect project traits, install hooks |
|
|
516
|
+
| `status [-o format]` | Show current phase, spec name, progress, debt |
|
|
517
|
+
| `spec new "..." [--name=N]` | Start a new spec, enter DISCOVERY |
|
|
518
|
+
| `spec list [-o format]` | List all specs with phase info |
|
|
519
|
+
| `spec switch <name>` | Switch active spec (preserves state) |
|
|
520
|
+
| `next [-o format]` | Get instruction for current phase |
|
|
521
|
+
| `next --answer="..." [-o f]` | Submit answer and advance state |
|
|
522
|
+
| `approve` | Approve spec draft -> SPEC_APPROVED |
|
|
523
|
+
| `done` | Complete execution -> DONE |
|
|
524
|
+
| `block "reason"` | Mark execution as blocked |
|
|
525
|
+
| `reset` | Reset current spec to IDLE |
|
|
526
|
+
| `run [--unattended]` | Autonomous execution loop (Ralph loop) |
|
|
527
|
+
| `watch [-o format]` | Live dashboard monitoring agent progress |
|
|
528
|
+
| `concern add/remove/list` | Manage active concerns |
|
|
529
|
+
| `rule add/list/promote` | Manage permanent rules |
|
|
530
|
+
| `sync` | Regenerate tool-specific instruction files + hooks |
|
|
531
|
+
| `purge [--force]` | Remove all noskills content (specs, rules, concerns, hooks, state) |
|
|
532
|
+
|
|
533
|
+
### Output Formats
|
|
534
|
+
|
|
535
|
+
All commands that produce output support `-o` / `--output`:
|
|
536
|
+
|
|
537
|
+
| Format | Flag | Use case |
|
|
538
|
+
| -------- | ------------------- | ---------------------- |
|
|
539
|
+
| JSON | `-o json` (default) | Agents, pipes, scripts |
|
|
540
|
+
| Markdown | `-o markdown` | Human reading |
|
|
541
|
+
| Text | `-o text` | Simple terminal output |
|
|
542
|
+
|
|
543
|
+
## Configuration
|
|
544
|
+
|
|
545
|
+
noskills config lives inside `.eser/manifest.yml` as a `noskills:` section:
|
|
546
|
+
|
|
547
|
+
```yaml
|
|
548
|
+
noskills:
|
|
549
|
+
command: "eser noskills" # auto-detected during init
|
|
550
|
+
concerns:
|
|
551
|
+
- open-source
|
|
552
|
+
- beautiful-product
|
|
553
|
+
tools:
|
|
554
|
+
- claude-code
|
|
555
|
+
- cursor
|
|
556
|
+
providers:
|
|
557
|
+
- anthropic
|
|
558
|
+
project:
|
|
559
|
+
languages: [typescript]
|
|
560
|
+
frameworks: [react]
|
|
561
|
+
ci: [github-actions]
|
|
562
|
+
testRunner: deno
|
|
563
|
+
maxIterationsBeforeRestart: 15
|
|
564
|
+
verifyCommand: "deno test" # runs before accepting task completion
|
|
565
|
+
allowGit: false # true = agents can run git write commands
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
During `init`, noskills detects how it was invoked (via `@eser/standards`
|
|
569
|
+
runtime) and stores it as `command`. All generated output — `CLAUDE.md`
|
|
570
|
+
instructions, hook remediation messages, behavioral rules, transition hints —
|
|
571
|
+
uses this prefix. Users who invoke via `deno run`, `npx`, homebrew, or global
|
|
572
|
+
install all get correct command references.
|
|
573
|
+
|
|
574
|
+
**Tools vs Providers:**
|
|
575
|
+
|
|
576
|
+
- **Tools** = the IDE or agent environment (`claude-code`, `cursor`, `kiro`,
|
|
577
|
+
`copilot`, `windsurf`). Affects which sync output files are generated.
|
|
578
|
+
- **Providers** = AI model access methods (`anthropic`, `openai`, `ollama`,
|
|
579
|
+
`claude-code` CLI). Used by the Agent Bridge for validation and
|
|
580
|
+
`noskills run`.
|
|
581
|
+
|
|
582
|
+
## Directory Structure
|
|
583
|
+
|
|
584
|
+
```
|
|
585
|
+
.eser/ # unified toolchain directory
|
|
586
|
+
|-- manifest.yml # workflows, scripts, AND noskills config
|
|
587
|
+
|-- concerns/ # Concern definitions (built-in + custom)
|
|
588
|
+
| |-- 001-open-source.json
|
|
589
|
+
| |-- 002-beautiful-product.json
|
|
590
|
+
| +-- ... # Numeric prefixes control ordering
|
|
591
|
+
|-- rules/ # Permanent rules (*.md, *.txt)
|
|
592
|
+
|-- specs/
|
|
593
|
+
| +-- photo-upload/
|
|
594
|
+
| +-- spec.md # Generated spec from discovery
|
|
595
|
+
|-- workflows/
|
|
596
|
+
|-- .state/ # git-ignored (runtime only)
|
|
597
|
+
| |-- state.json # Current phase, answers, progress, active spec
|
|
598
|
+
| |-- specs/ # Per-spec state snapshots
|
|
599
|
+
| | |-- photo-upload.json
|
|
600
|
+
| | +-- fix-login-bug.json
|
|
601
|
+
| |-- files-changed.jsonl # File modification log (from hooks)
|
|
602
|
+
| +-- noskills-calls.jsonl # CLI invocation log (from hooks)
|
|
603
|
+
+-- .gitignore # Excludes .state/
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
Configuration and specs are git-tracked for PR review. Runtime state is
|
|
607
|
+
gitignored — each agent session reads fresh state from the filesystem.
|
|
608
|
+
|
|
609
|
+
## Library API
|
|
610
|
+
|
|
611
|
+
```typescript
|
|
612
|
+
import * as noskills from "@eser/noskills/mod";
|
|
613
|
+
|
|
614
|
+
// State machine
|
|
615
|
+
const state = noskills.machine.startSpec(
|
|
616
|
+
noskills.createInitialState(),
|
|
617
|
+
"my-feature",
|
|
618
|
+
"spec/my-feature",
|
|
619
|
+
);
|
|
620
|
+
|
|
621
|
+
// Questions with concern extras
|
|
622
|
+
const qs = noskills.questions.getQuestionsWithExtras(activeConcerns);
|
|
623
|
+
|
|
624
|
+
// Compile instruction for current phase
|
|
625
|
+
const output = noskills.compiler.compile(state, activeConcerns, rules, config);
|
|
626
|
+
|
|
627
|
+
// Concern tension detection
|
|
628
|
+
const tensions = noskills.concerns.detectTensions(activeConcerns);
|
|
629
|
+
|
|
630
|
+
// Output formatting
|
|
631
|
+
const text = noskills.formatter.format(output, "markdown");
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
## Agent Bridge
|
|
635
|
+
|
|
636
|
+
noskills can call AI agents for validation via a fallback chain:
|
|
637
|
+
|
|
638
|
+
1. **@eser/ai** — Programmatic API call (cross-model, configurable)
|
|
639
|
+
2. **Claude CLI** — Spawns `claude -p "..."` locally (zero additional cost)
|
|
640
|
+
3. **Manual** — Returns null, caller handles human review
|
|
641
|
+
|
|
642
|
+
## Init Detection
|
|
643
|
+
|
|
644
|
+
`noskills init` auto-detects:
|
|
645
|
+
|
|
646
|
+
- **Languages** — TypeScript, Go, Rust, Python (from config files)
|
|
647
|
+
- **Frameworks** — React, Vue, Svelte, Next.js, Express, Hono (from
|
|
648
|
+
package.json)
|
|
649
|
+
- **CI** — GitHub Actions, GitLab CI, Jenkins, CircleCI
|
|
650
|
+
- **Test runner** — Deno, Vitest, Jest, Playwright
|
|
651
|
+
- **Coding tools** — Claude Code, Cursor, Kiro, Copilot, Windsurf (from existing
|
|
652
|
+
config files in repo)
|
|
653
|
+
|
|
654
|
+
Detected coding tools are auto-synced on init, including hook installation for
|
|
655
|
+
Claude Code. Invocation method is auto-detected and stored in `manifest.yml` as
|
|
656
|
+
`noskills.command` — all output references use this prefix.
|
|
657
|
+
|
|
658
|
+
## License
|
|
659
|
+
|
|
660
|
+
Apache-2.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as C}from"./chunk-QHS53BRV.js";import"./chunk-6XR33H6Q.js";import{a as P,d as R}from"./chunk-O3PI76HM.js";import{e as y}from"./chunk-OM4QJ24S.js";import{a as p}from"./chunk-UXRWSNVZ.js";import{e as h,f as S,k as g,o as v}from"./chunk-MJVACJ6D.js";import{c as n,d as c,f as l,g as m,k as d,o as f,q as u,r as w}from"./chunk-52HFDP2R.js";import{a as i}from"./chunk-2N4GTHXQ.js";import{a as o}from"./chunk-FPO2JRU3.js";import"./chunk-SG4G3OOO.js";import"./chunk-FDZP7B5Y.js";import"./chunk-ACQUINWH.js";import"./chunk-DXB73IDG.js";var $=async E=>{let r=f({renderer:w.ansi(),sink:u.stdout()}),s=o.process.cwd(),e=await h(s),a=await g(s);if(e.phase==="SPEC_DRAFT"){if(e.classification===null&&e.spec!==null){let A=(await v(s)).filter(D=>a?.concerns.includes(D.id)??!1);try{await C(s,e,A)}catch{}}let t=y(e);await S(s,t),t.spec!==null&&(await P(s,t.spec,"approved"),await R(s,t.spec,"approved")),r.writeln(m("\u2714")," Spec approved. Phase: ",d("SPEC_APPROVED")),r.writeln("When ready, run ",n(`${p('next --answer="start"',a)}`)," to begin execution.")}else e.phase==="DISCOVERY"&&e.discovery.completed?(r.writeln(c("Discovery complete. Spec draft already generated.")),r.writeln("Review the spec and run ",n(p("approve",a))," again when in SPEC_DRAFT phase.")):r.writeln(l(`Cannot approve in phase: ${e.phase}`));return await r.close(),i(void 0)};export{$ as main};
|