total-recall-brain 3.1.0
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/LICENSE +21 -0
- package/README.md +173 -0
- package/bin/antigravity.mjs +212 -0
- package/bin/init.mjs +36 -0
- package/bin/oci-sniper.sh +69 -0
- package/bin/total-recall.mjs +229 -0
- package/docs/ARCHITECTURE.md +251 -0
- package/docs/IDE_INTEGRATION.md +112 -0
- package/package.json +71 -0
- package/scaffold/.agent/skills/total-recall/SKILL.md +195 -0
- package/scaffold/.agent/skills/total-recall/evals/evals.json +20 -0
- package/scaffold/.agent/skills/total-recall/memory-vault/concepts/cli-help-reference.md +145 -0
- package/scaffold/.agent/skills/total-recall/memory-vault/invariants/operating-instructions.md +75 -0
- package/scaffold/.agent/skills/total-recall/memory-vault/preferences/always-websearch-gap.md +16 -0
- package/scaffold/.agent/skills/total-recall/memory-vault/preferences/topic-research-sop.md +17 -0
- package/scaffold/.agent/skills/total-recall/references/api-reference.md +187 -0
- package/scaffold/.agent/skills/total-recall/references/architecture-reference.md +81 -0
- package/scaffold/.agent/skills/total-recall/references/cli-reference.md +103 -0
- package/scaffold/.agent/skills/total-recall/references/ssss-reference.md +88 -0
- package/scaffold/.agent/skills/total-recall/references/troubleshooting.md +68 -0
- package/scaffold/.agent/skills/total-recall/scripts/sync-repo.mjs +83 -0
- package/scaffold/.agent/skills/total-recall/skills/cli-agents/SKILL.md +122 -0
- package/scaffold/.agent/skills/total-recall/skills/cli-agents/agents.yml +27 -0
- package/scaffold/.agent/skills/total-recall/skills/cli-agents/references/antigravity.txt +20 -0
- package/scaffold/.agent/skills/total-recall/skills/cli-agents/references/claude.txt +58 -0
- package/scaffold/.agent/skills/total-recall/skills/cli-agents/references/codex.txt +81 -0
- package/scaffold/.agent/skills/total-recall/skills/cli-agents/references/gemini.txt +44 -0
- package/scaffold/.agent/skills/total-recall/skills/research/SKILL.md +337 -0
- package/scaffold/.agent/skills/total-recall/skills/skill/SKILL.md +281 -0
- package/scaffold/.agent/skills/total-recall/skills/skill/assets/skill-template/SKILL.md +20 -0
- package/scaffold/.agent/skills/total-recall/skills/skill/evals/evals.json +20 -0
- package/scaffold/.agent/skills/total-recall/skills/skill/hooks/on-skill-add.sh +14 -0
- package/scaffold/.agent/skills/total-recall/skills/skill/hooks/on-skill-delete.sh +14 -0
- package/scaffold/.agent/skills/total-recall/skills/skill/learnings/.gitkeep +0 -0
- package/scaffold/.agent/skills/total-recall/skills/skill/references/.gitkeep +0 -0
- package/scaffold/.agent/skills/total-recall/skills/skill/scripts/.gitkeep +0 -0
- package/scaffold/.agent/skills/total-recall/skills/skill/scripts/create-skill.sh +65 -0
- package/scaffold/.agent/skills/total-recall/skills/skill/scripts/enforce-skill-optimization.mjs +135 -0
- package/scaffold/.agent/skills/total-recall/skills/skill/scripts/find-skills.mjs +124 -0
- package/scaffold/.agent/skills/total-recall/skills/skill/scripts/scan-skill.mjs +207 -0
- package/scaffold/.agent/skills/total-recall/skills/skill/scripts/skill-watcher.mjs +64 -0
- package/scaffold/.agent/skills/total-recall/skills/skill/subagents/audit-all-skills.md +62 -0
- package/scaffold/.agent/skills/total-recall/skills/ssss/SKILL.md +27 -0
- package/scaffold/.agent/skills/total-recall/skills/ssss/evals/evals.json +17 -0
- package/scaffold/.agent/skills/total-recall/skills/ssss/references/ssss-spec.md +117 -0
- package/scaffold/.agent/skills/total-recall/skills/ssss/scripts/validate-schema.mjs +54 -0
- package/scaffold/.agent/skills/total-recall/skills/ssss/subagents/audit-ssss-node.md +9 -0
- package/scaffold/.agent/skills/total-recall/subagents/total-recall-diagnostician.md +13 -0
- package/src/cli/agent-dir.mjs +105 -0
- package/src/cli/backup.mjs +313 -0
- package/src/cli/brain.mjs +224 -0
- package/src/cli/chat.mjs +74 -0
- package/src/cli/config.mjs +247 -0
- package/src/cli/connect.mjs +872 -0
- package/src/cli/daemon.mjs +228 -0
- package/src/cli/deploy-ui.mjs +1793 -0
- package/src/cli/deploy.mjs +1726 -0
- package/src/cli/doctor.mjs +254 -0
- package/src/cli/dream.mjs +80 -0
- package/src/cli/forget.mjs +92 -0
- package/src/cli/friction.mjs +21 -0
- package/src/cli/generate-pat.mjs +65 -0
- package/src/cli/hash-password.mjs +22 -0
- package/src/cli/help.mjs +153 -0
- package/src/cli/import-rules.mjs +102 -0
- package/src/cli/ingest/index.mjs +318 -0
- package/src/cli/ingest/parsers/chrome-bookmarks.mjs +238 -0
- package/src/cli/ingest/parsers/google-keep.mjs +147 -0
- package/src/cli/ingest/parsers/search-history.mjs +142 -0
- package/src/cli/ingest/parsers/youtube-history.mjs +181 -0
- package/src/cli/ingest/utils/dedup.mjs +69 -0
- package/src/cli/ingest/utils/takeout-walker.mjs +101 -0
- package/src/cli/ingest.mjs +102 -0
- package/src/cli/init.mjs +736 -0
- package/src/cli/integration-dispatcher.mjs +128 -0
- package/src/cli/lint.mjs +166 -0
- package/src/cli/map.mjs +194 -0
- package/src/cli/migrate.mjs +87 -0
- package/src/cli/rebuild.mjs +88 -0
- package/src/cli/recall.mjs +219 -0
- package/src/cli/relay.mjs +518 -0
- package/src/cli/remember.mjs +306 -0
- package/src/cli/research.mjs +381 -0
- package/src/cli/reset-password.mjs +75 -0
- package/src/cli/restore.mjs +135 -0
- package/src/cli/setup.mjs +616 -0
- package/src/cli/share.mjs +180 -0
- package/src/cli/skill.mjs +313 -0
- package/src/cli/snapshot.mjs +108 -0
- package/src/cli/start.mjs +63 -0
- package/src/cli/status.mjs +296 -0
- package/src/cli/sync.mjs +383 -0
- package/src/cli/uninstall.mjs +613 -0
- package/src/cli/upgrade.mjs +141 -0
- package/src/cli/wizard.html +3682 -0
- package/src/core/blackboard.mjs +54 -0
- package/src/core/clarity-rewriter.mjs +770 -0
- package/src/core/conclusion-writer.mjs +259 -0
- package/src/core/config.mjs +277 -0
- package/src/core/conflict-detector.mjs +536 -0
- package/src/core/crypto.mjs +107 -0
- package/src/core/daemon-control.mjs +158 -0
- package/src/core/daemon-loop.mjs +364 -0
- package/src/core/dream.mjs +347 -0
- package/src/core/drift-detector.mjs +143 -0
- package/src/core/embeddings.mjs +632 -0
- package/src/core/emergency-alerts.mjs +137 -0
- package/src/core/evolution.mjs +107 -0
- package/src/core/fact-seeker.mjs +1602 -0
- package/src/core/friction.mjs +95 -0
- package/src/core/import-rules.mjs +308 -0
- package/src/core/inference-engine.mjs +367 -0
- package/src/core/logger.mjs +75 -0
- package/src/core/memory-layers.mjs +96 -0
- package/src/core/migrate.mjs +116 -0
- package/src/core/notifications.mjs +77 -0
- package/src/core/operation-validator.mjs +272 -0
- package/src/core/optimizer.mjs +330 -0
- package/src/core/pattern_detector.mjs +113 -0
- package/src/core/post-mortem.mjs +413 -0
- package/src/core/protect-instructions.mjs +148 -0
- package/src/core/quick-capture.mjs +145 -0
- package/src/core/research-queue.mjs +431 -0
- package/src/core/research.mjs +461 -0
- package/src/core/runtime.mjs +515 -0
- package/src/core/sandbox.mjs +163 -0
- package/src/core/scheduler.mjs +569 -0
- package/src/core/schema.mjs +333 -0
- package/src/core/search.mjs +219 -0
- package/src/core/semantic-index.mjs +276 -0
- package/src/core/session-watcher.mjs +850 -0
- package/src/core/snapshot.mjs +133 -0
- package/src/core/source-adapters.mjs +1038 -0
- package/src/core/steering.mjs +137 -0
- package/src/core/surface.mjs +444 -0
- package/src/core/task_runner.mjs +125 -0
- package/src/core/tts.mjs +142 -0
- package/src/core/usage-tracker.mjs +349 -0
- package/src/core/vault-cache.mjs +76 -0
- package/src/core/vault.mjs +273 -0
- package/src/core/watchdog.mjs +236 -0
- package/src/server/api.mjs +944 -0
- package/src/server/auth.mjs +410 -0
- package/src/server/index.mjs +868 -0
- package/src/server/keys.mjs +181 -0
- package/src/server/rest.mjs +1652 -0
- package/src/server/route-manifest.json +77 -0
- package/src/server/routes/_shared.mjs +93 -0
- package/src/server/routes/keys.mjs +55 -0
- package/src/server/routes/memory.mjs +249 -0
- package/src/server/routes/sessions.mjs +336 -0
- package/src/server/routes/share.mjs +138 -0
- package/src/server/tools.mjs +618 -0
- package/templates/Caddyfile +37 -0
- package/templates/com.totalrecall.backup.plist +42 -0
- package/templates/com.totalrecall.daemon.plist +40 -0
- package/templates/com.totalrecall.duckdns.plist +23 -0
- package/templates/com.totalrecall.server.plist +46 -0
- package/templates/default-config/budget.yml +6 -0
- package/templates/default-config/runtime.yml +11 -0
- package/templates/default-config/security.yml +53 -0
- package/templates/default-config/voice.yml +34 -0
- package/templates/obsidian-queries/conflicts.md +26 -0
- package/templates/obsidian-queries/daily.md +17 -0
- package/templates/obsidian-queries/index.md +38 -0
- package/templates/obsidian-queries/skills.md +14 -0
- package/templates/onboarding-interview.md +72 -0
- package/templates/skill_engineering.md +40 -0
- package/templates/total-recall-daemon.service +21 -0
- package/templates/total-recall-server.service +20 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: skill
|
|
3
|
+
description: "Use this skill when creating, auditing, or modifying any skill in the .agent/skills/ ecosystem. MANDATORY: You MUST read the full SKILL.md file before executing."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Skill Architecture — Canonical Format Guide
|
|
7
|
+
|
|
8
|
+
> **Version:** 2.0.0 | **Updated:** 2026-05-11
|
|
9
|
+
|
|
10
|
+
This is the definitive guide for how skills are structured, created, and maintained. Every agent that creates or modifies a skill MUST follow this spec exactly.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 1. What is a Skill?
|
|
15
|
+
|
|
16
|
+
A skill is a **self-contained knowledge package** that lives in `.agent/skills/<skill-name>/`. It gives an agent everything it needs to perform a specific domain task correctly: instructions, executable scripts, reference material, test criteria, and delegation prompts.
|
|
17
|
+
|
|
18
|
+
Skills are NOT documentation. They are **executable expertise.**
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 2. Required Directory Structure
|
|
23
|
+
|
|
24
|
+
Every skill MUST contain these items. No exceptions.
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
my-skill/
|
|
28
|
+
├── SKILL.md # REQUIRED — The master instruction file
|
|
29
|
+
├── scripts/ # REQUIRED — Automation scripts
|
|
30
|
+
├── references/ # REQUIRED — Domain knowledge, specs, docs
|
|
31
|
+
├── evals/ # REQUIRED — Success criteria and tests
|
|
32
|
+
└── subagents/ # REQUIRED — Delegation prompts for subtasks
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Why all five are required
|
|
36
|
+
|
|
37
|
+
Agents will skip optional folders without a second thought. By requiring all five, we force the agent to **stop and think** about what belongs in each one. Even a hastily written eval or a minimal reference doc is infinitely more valuable than nothing — it can always be improved later.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 3. SKILL.md — The Entrypoint
|
|
42
|
+
|
|
43
|
+
### Frontmatter (REQUIRED)
|
|
44
|
+
|
|
45
|
+
```yaml
|
|
46
|
+
---
|
|
47
|
+
name: my-skill-name
|
|
48
|
+
description: "Use this skill when [TRIGGER CONDITION]. MANDATORY: You MUST read the full SKILL.md file before executing."
|
|
49
|
+
---
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
| Field | Rules |
|
|
53
|
+
|:---|:---|
|
|
54
|
+
| `name` | **Lowercase kebab-case.** Must exactly match the folder name. |
|
|
55
|
+
| `description` | **Trigger-optimized.** Must clearly state WHAT it does and WHEN to use it. Under 1024 chars. The IDE uses this string to decide when to show the skill — vague descriptions mean the skill never gets activated. |
|
|
56
|
+
|
|
57
|
+
### ⛔ Frontmatter Anti-Patterns
|
|
58
|
+
|
|
59
|
+
```yaml
|
|
60
|
+
# ❌ WRONG — SSSS memory node fields. Skills are NOT memory nodes.
|
|
61
|
+
type: skill
|
|
62
|
+
slug: my-skill
|
|
63
|
+
category: architecture
|
|
64
|
+
title: "My Skill"
|
|
65
|
+
schema_version: 2
|
|
66
|
+
importance: 4
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
```yaml
|
|
70
|
+
# ✅ CORRECT — only name + description
|
|
71
|
+
name: my-skill
|
|
72
|
+
description: "Use this skill when doing X. MANDATORY: You MUST read the full SKILL.md file before executing."
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Body Content
|
|
76
|
+
|
|
77
|
+
The body of SKILL.md is the **master prompt** for the skill. Write it as procedural instructions that an agent can follow step-by-step. Include:
|
|
78
|
+
|
|
79
|
+
- **Context** — What problem does this skill solve?
|
|
80
|
+
- **Steps** — Numbered, concrete actions
|
|
81
|
+
- **Rules** — Hard constraints and invariants
|
|
82
|
+
- **Pitfalls** — What goes wrong and how to avoid it
|
|
83
|
+
- **Code examples** — Correct and incorrect patterns
|
|
84
|
+
- **References** — Pointers to files in `references/` for deeper context
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 4. scripts/ — Execution Layer
|
|
89
|
+
|
|
90
|
+
Contains executable code the agent runs via the sandbox to perform complex or deterministic operations.
|
|
91
|
+
|
|
92
|
+
**What belongs here:**
|
|
93
|
+
- Scaffolding scripts (e.g., `create-skill.sh`)
|
|
94
|
+
- Validation/linting scripts (e.g., `enforce-skill-optimization.mjs`)
|
|
95
|
+
- Watchers and cron-triggered automation (e.g., `watch.mjs`)
|
|
96
|
+
- Data transformation or migration scripts
|
|
97
|
+
- Any operation that should be deterministic rather than LLM-hallucinated
|
|
98
|
+
|
|
99
|
+
**Rules:**
|
|
100
|
+
- Scripts MUST be idempotent where possible
|
|
101
|
+
- Scripts MUST be self-contained (no implicit dependencies outside the skill)
|
|
102
|
+
- Scripts MUST handle errors gracefully with clear stderr output
|
|
103
|
+
- Use `console.error()` for logging, never `console.log()` in production scripts
|
|
104
|
+
|
|
105
|
+
**When creating a skill, ask yourself:** *"What operations in this domain should be automated with code instead of trusted to the LLM's judgment?"*
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 5. references/ — Domain Knowledge
|
|
110
|
+
|
|
111
|
+
Contains static reference documents the agent reads for context when the skill is activated.
|
|
112
|
+
|
|
113
|
+
**What belongs here:**
|
|
114
|
+
- API documentation or spec excerpts
|
|
115
|
+
- Schema definitions
|
|
116
|
+
- Configuration format guides
|
|
117
|
+
- Architecture decision records
|
|
118
|
+
- Links to external sources with cached key sections
|
|
119
|
+
- Example files or templates
|
|
120
|
+
|
|
121
|
+
**Rules:**
|
|
122
|
+
- Use Markdown (`.md`) files for text documentation
|
|
123
|
+
- Keep files focused — one topic per file
|
|
124
|
+
- Name files descriptively: `streamable-http-spec.md`, not `ref1.md`
|
|
125
|
+
- Include the source URL at the top of any extracted documentation
|
|
126
|
+
|
|
127
|
+
**When creating a skill, ask yourself:** *"What does an agent need to READ to understand this domain? What docs did I have to look up?"*
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 6. evals/ — Success Criteria
|
|
132
|
+
|
|
133
|
+
Contains assertions, test scripts, or evaluation criteria that verify the skill was executed correctly.
|
|
134
|
+
|
|
135
|
+
**What belongs here:**
|
|
136
|
+
- `evals.json` — Structured assertions (minimum 3)
|
|
137
|
+
- Test scripts that can be run in the sandbox
|
|
138
|
+
- Checklists of things to verify
|
|
139
|
+
- Expected output examples
|
|
140
|
+
|
|
141
|
+
**evals.json format:**
|
|
142
|
+
```json
|
|
143
|
+
[
|
|
144
|
+
{
|
|
145
|
+
"name": "frontmatter-has-name",
|
|
146
|
+
"assertion": "SKILL.md YAML frontmatter contains a 'name' field",
|
|
147
|
+
"severity": "error"
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"name": "description-is-trigger-optimized",
|
|
151
|
+
"assertion": "description field starts with 'Use this skill when'",
|
|
152
|
+
"severity": "warning"
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"name": "no-empty-directories",
|
|
156
|
+
"assertion": "All required directories contain at least one non-.gitkeep file",
|
|
157
|
+
"severity": "error"
|
|
158
|
+
}
|
|
159
|
+
]
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**When creating a skill, ask yourself:** *"How would I know if this skill was used correctly? What could go wrong? What should I check?"*
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## 7. subagents/ — Delegation Prompts
|
|
167
|
+
|
|
168
|
+
Contains standalone prompt files for subtasks that can be delegated to parallel agents or focused workers.
|
|
169
|
+
|
|
170
|
+
**What belongs here:**
|
|
171
|
+
- Audit prompts (e.g., `audit-all-skills.md`)
|
|
172
|
+
- Review prompts (e.g., `review-output.md`)
|
|
173
|
+
- Specialized generation prompts (e.g., `generate-tests.md`)
|
|
174
|
+
- Decomposed subtask prompts for complex workflows
|
|
175
|
+
|
|
176
|
+
**Rules:**
|
|
177
|
+
- Each file is a complete, self-contained prompt
|
|
178
|
+
- Include role, context, constraints, and expected output format
|
|
179
|
+
- Name files as verbs: `audit-X.md`, `generate-Y.md`, `validate-Z.md`
|
|
180
|
+
|
|
181
|
+
**When creating a skill, ask yourself:** *"What parts of this task could be delegated to a focused subagent? What parallel work would speed this up?"*
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## 8. Creating a New Skill
|
|
186
|
+
|
|
187
|
+
### Quick method (script):
|
|
188
|
+
```bash
|
|
189
|
+
bash .agent/skills/skill/scripts/create-skill.sh my-new-skill
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Manual method:
|
|
193
|
+
1. Create the folder: `.agent/skills/my-new-skill/`
|
|
194
|
+
2. Create `SKILL.md` with proper `name` + `description` frontmatter
|
|
195
|
+
3. Create `scripts/`, `references/`, `evals/`, `subagents/` directories
|
|
196
|
+
4. Populate each directory — think deeply about what belongs in each one
|
|
197
|
+
5. Write `evals/evals.json` with at least 3 assertions
|
|
198
|
+
|
|
199
|
+
### The Deliberation Checklist
|
|
200
|
+
|
|
201
|
+
Before committing a new skill, answer ALL of these:
|
|
202
|
+
|
|
203
|
+
| Folder | Question |
|
|
204
|
+
|:---|:---|
|
|
205
|
+
| `SKILL.md` | Is the description trigger-optimized? Will the IDE activate this skill at the right time? |
|
|
206
|
+
| `scripts/` | What operations should be deterministic code, not LLM guesses? |
|
|
207
|
+
| `references/` | What domain knowledge does the agent need? What docs did I have to look up? |
|
|
208
|
+
| `evals/` | How do I know if this skill was used correctly? What could go wrong? |
|
|
209
|
+
| `subagents/` | What subtasks could be parallelized or delegated to a focused worker? |
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## 9. Quality Enforcement
|
|
214
|
+
|
|
215
|
+
The enforcement script (`scripts/enforce-skill-optimization.mjs`) validates all skills on commit:
|
|
216
|
+
|
|
217
|
+
1. Every skill must have a `SKILL.md` with `name` and `description` frontmatter
|
|
218
|
+
2. All five directories must exist and contain at least one real file (`.gitkeep` alone doesn't count)
|
|
219
|
+
3. `evals/evals.json` must contain at least 3 assertions
|
|
220
|
+
4. No placeholder/TODO-only SKILL.md files in committed skills
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## 10. Safe Integration of External Skills
|
|
225
|
+
|
|
226
|
+
When downloading, importing, or adding external skills from registries like `skills.sh` (via `npx skills add <name>`), agents and developers MUST perform security audits before executing any scripts:
|
|
227
|
+
|
|
228
|
+
1. **Verify Executable Scripts**: Open and scan all scripts under `scripts/`. Look for shell template strings with dynamic interpolation or unchecked execution arguments.
|
|
229
|
+
2. **Restrict Path Operations**: Ensure path references are validated and match regular expressions (e.g. `SAFE_NAME` pattern) to prevent path traversal vulnerabilities.
|
|
230
|
+
3. **Assert Sandbox Isolation**: Prefer executing unfamiliar external skill scripts inside isolated sandbox environments or containers to guarantee zero adverse host system impact.
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## 11. Common Mistakes
|
|
235
|
+
|
|
236
|
+
| Mistake | Why It's Wrong | Fix |
|
|
237
|
+
|:---|:---|:---|
|
|
238
|
+
| Using `type`/`slug`/`category` in frontmatter | Those are SSSS memory node fields, not skill fields. IDE can't discover the skill. | Use only `name` and `description` |
|
|
239
|
+
| Empty `references/` with just `.gitkeep` | Agent loses critical domain context | Add at least one reference doc — even a short one |
|
|
240
|
+
| Empty `evals/` | No way to verify the skill worked | Write 3+ assertions in `evals.json` |
|
|
241
|
+
| Vague description | `"A skill for doing stuff"` → IDE never triggers it | `"Use this skill when X. Do NOT use for Y."` |
|
|
242
|
+
| Mixing format spec with implementation details | Contaminates portable knowledge with project-specific internals | Keep format docs generic, put project details in PRD |
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Changelog
|
|
247
|
+
|
|
248
|
+
### v2.0.0 (2026-05-11)
|
|
249
|
+
- **BREAKING**: Removed Total Recall-specific implementation details (surface.mjs routing, memory injection blocks, Gemma 4 references, P2 scheduling). This skill is now the universal format spec.
|
|
250
|
+
- Added deliberation checklist forcing agents to think about each folder
|
|
251
|
+
- Added "When creating a skill, ask yourself" prompts for each directory
|
|
252
|
+
- Added frontmatter anti-patterns section
|
|
253
|
+
- Added evals.json format example
|
|
254
|
+
- Added common mistakes table
|
|
255
|
+
|
|
256
|
+
### v1.0.0 (2026-05-10)
|
|
257
|
+
- Initial version. Mixed universal skill format with Total Recall memory compiler internals, causing agent confusion.
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
<!-- BEGIN INJECTED MEMORY: do not edit by hand; rebuilt by total-recall surface -->
|
|
261
|
+
<!-- @route: tfidf, generated_at: 2026-05-21T06:00:44.284Z -->
|
|
262
|
+
|
|
263
|
+
- **inviolable-ide-instruction-7a4d8913** (confidence 1, importance critical):
|
|
264
|
+
Inviolable IDE Instruction: # Temporary Cursor Rules for testing
|
|
265
|
+
|
|
266
|
+
- **always-reply-to-all-messages** (confidence 1, importance critical):
|
|
267
|
+
Always reply directly to all user messages without exception
|
|
268
|
+
|
|
269
|
+
- **chocolate-brownies** (confidence 0.95, importance 4):
|
|
270
|
+
Chocolate brownies must be fudgey and rich
|
|
271
|
+
|
|
272
|
+
- **security-audit-protocol** (confidence 1, importance 4):
|
|
273
|
+
Security audit protocol and hardening requirements
|
|
274
|
+
|
|
275
|
+
- **operating-instructions** (confidence 1, importance 5):
|
|
276
|
+
Total Recall Core Operating Protocol
|
|
277
|
+
|
|
278
|
+
- **no-cursor-or-windsurf-mentions** (confidence 1, importance critical):
|
|
279
|
+
Do not mention Cursor or Windsurf
|
|
280
|
+
|
|
281
|
+
<!-- END INJECTED MEMORY -->
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: SKILL_NAME_PLACEHOLDER
|
|
3
|
+
description: "Use this template when creating new skills to ensure trigger-optimized descriptions. MANDATORY: You MUST read this file before executing."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# SKILL_NAME_PLACEHOLDER
|
|
7
|
+
|
|
8
|
+
> TODO: Write procedural instructions for this skill.
|
|
9
|
+
|
|
10
|
+
## Step 1: [First Action]
|
|
11
|
+
|
|
12
|
+
TODO: Describe the first step.
|
|
13
|
+
|
|
14
|
+
## Step 2: [Second Action]
|
|
15
|
+
|
|
16
|
+
TODO: Describe the second step.
|
|
17
|
+
|
|
18
|
+
## References
|
|
19
|
+
|
|
20
|
+
- If you need X, see `references/X.md`
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "skill-eval-1",
|
|
4
|
+
"description": "SKILL.md exists",
|
|
5
|
+
"command": "test -f .agent/skills/skill/SKILL.md",
|
|
6
|
+
"expected_exit_code": 0
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"id": "skill-eval-2",
|
|
10
|
+
"description": "Evals validation",
|
|
11
|
+
"command": "test -f .agent/skills/skill/scripts/run-evals.mjs",
|
|
12
|
+
"expected_exit_code": 0
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "skill-eval-3",
|
|
16
|
+
"description": "Optimization enforcement",
|
|
17
|
+
"command": "test -f .agent/skills/skill/scripts/enforce-skill-optimization.mjs",
|
|
18
|
+
"expected_exit_code": 0
|
|
19
|
+
}
|
|
20
|
+
]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# on-skill-add.sh — Auto-regenerate the skill routing table when a new skill is added.
|
|
3
|
+
#
|
|
4
|
+
# Trigger: Run after creating a new skill via create-skill.sh or manually.
|
|
5
|
+
# Action: Runs update-skill-index.mjs to sync the routing table and INSTRUCTIONS.md.
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
10
|
+
ROOT="$(cd "$SCRIPT_DIR/../../../.." && pwd)"
|
|
11
|
+
|
|
12
|
+
echo "🔄 OnSkillAdd hook triggered — regenerating skill index..."
|
|
13
|
+
node "$ROOT/.agent/skills/skill/scripts/update-skill-index.mjs"
|
|
14
|
+
echo "✅ Routing table and INSTRUCTIONS.md updated."
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# on-skill-delete.sh — Auto-clean the skill routing table when a skill is removed.
|
|
3
|
+
#
|
|
4
|
+
# Trigger: Run after deleting a skill directory.
|
|
5
|
+
# Action: Runs update-skill-index.mjs to sync the routing table and INSTRUCTIONS.md.
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
10
|
+
ROOT="$(cd "$SCRIPT_DIR/../../../.." && pwd)"
|
|
11
|
+
|
|
12
|
+
echo "🧹 OnSkillDelete hook triggered — cleaning skill index..."
|
|
13
|
+
node "$ROOT/.agent/skills/skill/scripts/update-skill-index.mjs"
|
|
14
|
+
echo "✅ Routing table and INSTRUCTIONS.md cleaned."
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# create-skill.sh — Scaffold a new Dev Skill from the template
|
|
3
|
+
#
|
|
4
|
+
# Usage: bash .agent/skills/skill/scripts/create-skill.sh <skill-name>
|
|
5
|
+
# Example: bash .agent/skills/skill/scripts/create-skill.sh my-new-skill
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
SKILL_NAME="${1:-}"
|
|
10
|
+
|
|
11
|
+
if [ -z "$SKILL_NAME" ]; then
|
|
12
|
+
echo "❌ Usage: bash create-skill.sh <skill-name>"
|
|
13
|
+
echo " Example: bash create-skill.sh my-new-skill"
|
|
14
|
+
exit 1
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
18
|
+
ROOT="$(cd "$SCRIPT_DIR/../../../.." && pwd)"
|
|
19
|
+
SKILLS_DIR="$ROOT/.agent/skills"
|
|
20
|
+
TARGET="$SKILLS_DIR/$SKILL_NAME"
|
|
21
|
+
|
|
22
|
+
if [ -d "$TARGET" ]; then
|
|
23
|
+
echo "❌ Skill '$SKILL_NAME' already exists at $TARGET"
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
echo "📦 Creating skill: $SKILL_NAME"
|
|
28
|
+
|
|
29
|
+
# Create directory structure
|
|
30
|
+
mkdir -p "$TARGET"/{scripts,references}
|
|
31
|
+
|
|
32
|
+
# Create SKILL.md with frontmatter template
|
|
33
|
+
cat > "$TARGET/SKILL.md" << EOF
|
|
34
|
+
---
|
|
35
|
+
name: $SKILL_NAME
|
|
36
|
+
description: "TODO: Write a trigger-optimized description. Format: WHAT it does + WHEN to use it + WHEN NOT to use it. Under 1024 chars."
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
# $SKILL_NAME
|
|
40
|
+
|
|
41
|
+
> TODO: Write procedural instructions for this skill.
|
|
42
|
+
|
|
43
|
+
## Step 1: [First Action]
|
|
44
|
+
|
|
45
|
+
TODO: Describe the first step.
|
|
46
|
+
|
|
47
|
+
## Step 2: [Second Action]
|
|
48
|
+
|
|
49
|
+
TODO: Describe the second step.
|
|
50
|
+
|
|
51
|
+
## References
|
|
52
|
+
|
|
53
|
+
- If you need X, see \`references/X.md\`
|
|
54
|
+
EOF
|
|
55
|
+
|
|
56
|
+
echo "✅ Created $TARGET/SKILL.md"
|
|
57
|
+
echo "✅ Created $TARGET/scripts/"
|
|
58
|
+
echo "✅ Created $TARGET/references/"
|
|
59
|
+
echo ""
|
|
60
|
+
echo "📝 Next steps:"
|
|
61
|
+
echo " 1. Edit $TARGET/SKILL.md with real instructions"
|
|
62
|
+
echo " 2. Write a trigger-optimized description in the frontmatter"
|
|
63
|
+
echo " 3. Run: node .agent/skills/skill/scripts/update-skill-index.mjs"
|
|
64
|
+
echo ""
|
|
65
|
+
echo "🏁 Done."
|
package/scaffold/.agent/skills/total-recall/skills/skill/scripts/enforce-skill-optimization.mjs
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* enforce-skill-optimization.mjs
|
|
3
|
+
*
|
|
4
|
+
* Pre-commit validation for the skill ecosystem.
|
|
5
|
+
* Ensures every skill in .agent/skills/ meets the canonical format:
|
|
6
|
+
* - SKILL.md with proper name + description frontmatter
|
|
7
|
+
* - All required directories exist with real content
|
|
8
|
+
* - evals/evals.json has ≥3 assertions
|
|
9
|
+
*
|
|
10
|
+
* Exit code 1 = validation failed (blocks commit)
|
|
11
|
+
* Exit code 0 = all skills valid
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import fs from 'node:fs';
|
|
15
|
+
import path from 'node:path';
|
|
16
|
+
|
|
17
|
+
const SKILLS_DIR = path.join(process.cwd(), '.agent/skills');
|
|
18
|
+
const REQUIRED_DIRS = ['scripts', 'references', 'evals', 'subagents'];
|
|
19
|
+
|
|
20
|
+
function parseYamlFrontmatter(content) {
|
|
21
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
22
|
+
if (!match) return null;
|
|
23
|
+
|
|
24
|
+
const fields = {};
|
|
25
|
+
for (const line of match[1].split('\n')) {
|
|
26
|
+
const kv = line.match(/^(\w+):\s*(.+)/);
|
|
27
|
+
if (kv) {
|
|
28
|
+
fields[kv[1]] = kv[2].replace(/^["']|["']$/g, '');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return fields;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function hasRealContent(dirPath) {
|
|
35
|
+
if (!fs.existsSync(dirPath)) return false;
|
|
36
|
+
const entries = fs.readdirSync(dirPath);
|
|
37
|
+
return entries.some(e => e !== '.gitkeep');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function checkSkills() {
|
|
41
|
+
if (!fs.existsSync(SKILLS_DIR)) {
|
|
42
|
+
console.error('⚠️ No .agent/skills/ directory found. Skipping.');
|
|
43
|
+
process.exit(0);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const dirs = fs.readdirSync(SKILLS_DIR).filter(d =>
|
|
47
|
+
fs.statSync(path.join(SKILLS_DIR, d)).isDirectory()
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const errors = [];
|
|
51
|
+
const warnings = [];
|
|
52
|
+
|
|
53
|
+
for (const skillName of dirs) {
|
|
54
|
+
const skillPath = path.join(SKILLS_DIR, skillName);
|
|
55
|
+
const skillMd = path.join(skillPath, 'SKILL.md');
|
|
56
|
+
|
|
57
|
+
// ── SKILL.md must exist ──────────────────────────────────────────────
|
|
58
|
+
if (!fs.existsSync(skillMd)) {
|
|
59
|
+
errors.push(`${skillName}: Missing SKILL.md`);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const content = fs.readFileSync(skillMd, 'utf8');
|
|
64
|
+
const frontmatter = parseYamlFrontmatter(content);
|
|
65
|
+
|
|
66
|
+
// ── Frontmatter must have name + description ─────────────────────────
|
|
67
|
+
if (!frontmatter) {
|
|
68
|
+
errors.push(`${skillName}: SKILL.md has no YAML frontmatter`);
|
|
69
|
+
} else {
|
|
70
|
+
if (!frontmatter.name) {
|
|
71
|
+
errors.push(`${skillName}: frontmatter missing 'name' field (has '${Object.keys(frontmatter).join(', ')}' instead)`);
|
|
72
|
+
} else if (frontmatter.name !== skillName) {
|
|
73
|
+
warnings.push(`${skillName}: frontmatter name '${frontmatter.name}' doesn't match folder name '${skillName}'`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!frontmatter.description) {
|
|
77
|
+
errors.push(`${skillName}: frontmatter missing 'description' field`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Warn about SSSS memory node fields leaking into skill frontmatter
|
|
81
|
+
const badFields = ['type', 'slug', 'category', 'schema_version', 'importance', 'priority', 'modality'];
|
|
82
|
+
const found = badFields.filter(f => frontmatter[f]);
|
|
83
|
+
if (found.length > 0) {
|
|
84
|
+
errors.push(`${skillName}: frontmatter contains SSSS memory node fields (${found.join(', ')}). Skills use only 'name' and 'description'.`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ── Required directories ─────────────────────────────────────────────
|
|
89
|
+
for (const reqDir of REQUIRED_DIRS) {
|
|
90
|
+
const dirPath = path.join(skillPath, reqDir);
|
|
91
|
+
if (!fs.existsSync(dirPath)) {
|
|
92
|
+
errors.push(`${skillName}: missing required directory: ${reqDir}/`);
|
|
93
|
+
} else if (!hasRealContent(dirPath)) {
|
|
94
|
+
warnings.push(`${skillName}: ${reqDir}/ has no real content (only .gitkeep). Consider adding domain-specific files.`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ── evals.json quality check ─────────────────────────────────────────
|
|
99
|
+
const evalsPath = path.join(skillPath, 'evals', 'evals.json');
|
|
100
|
+
if (fs.existsSync(evalsPath)) {
|
|
101
|
+
try {
|
|
102
|
+
const evals = JSON.parse(fs.readFileSync(evalsPath, 'utf8'));
|
|
103
|
+
if (!Array.isArray(evals)) {
|
|
104
|
+
errors.push(`${skillName}: evals.json must be a JSON array`);
|
|
105
|
+
} else if (evals.length < 3) {
|
|
106
|
+
warnings.push(`${skillName}: evals.json has only ${evals.length} assertion(s) — minimum 3 recommended`);
|
|
107
|
+
}
|
|
108
|
+
} catch {
|
|
109
|
+
errors.push(`${skillName}: evals.json is invalid JSON`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ── Report ───────────────────────────────────────────────────────────────
|
|
115
|
+
if (warnings.length > 0) {
|
|
116
|
+
console.error('\n⚠️ Warnings:');
|
|
117
|
+
for (const w of warnings) console.error(` ${w}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (errors.length > 0) {
|
|
121
|
+
console.error('\n❌ Errors:');
|
|
122
|
+
for (const e of errors) console.error(` ${e}`);
|
|
123
|
+
console.error(`\n🚨 SKILL ENFORCEMENT FAILED — ${errors.length} error(s) found.`);
|
|
124
|
+
console.error(' Fix the errors above before committing.\n');
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
console.error(`\n✅ All ${dirs.length} skills passed enforcement checks.`);
|
|
129
|
+
if (warnings.length > 0) {
|
|
130
|
+
console.error(` (${warnings.length} warning(s) — not blocking)\n`);
|
|
131
|
+
}
|
|
132
|
+
process.exit(0);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
checkSkills();
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* find-skills.mjs — skills.sh Registry Search & Parser
|
|
3
|
+
*
|
|
4
|
+
* Parses the raw CLI output from `npx skills find <query>` into
|
|
5
|
+
* structured skill records. Used by the Sovereign Skill Manager to
|
|
6
|
+
* search, rank, and install community skills from skills.sh.
|
|
7
|
+
*
|
|
8
|
+
* Output format from `skills find`:
|
|
9
|
+
* Install with npx skills add <owner/repo@skill>
|
|
10
|
+
*
|
|
11
|
+
* steipete/clawdis@github 1.7K installs
|
|
12
|
+
* └ https://skills.sh/steipete/clawdis/github
|
|
13
|
+
*
|
|
14
|
+
* jiulingyun/openclaw-cn@github 21 installs
|
|
15
|
+
* └ https://skills.sh/jiulingyun/openclaw-cn/github
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { execSync } from 'node:child_process';
|
|
19
|
+
|
|
20
|
+
// ─── Install Count Parser ────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Convert a human-readable install count (e.g. "1.7" + "K") to an integer.
|
|
24
|
+
*
|
|
25
|
+
* @param {string} value - Numeric portion of the install count (e.g. "1.7", "21", "2.1")
|
|
26
|
+
* @param {string} unit - SI suffix: "K" (thousands), "M" (millions), or "" (raw count)
|
|
27
|
+
* @returns {number} Integer install count, or 0 if parsing fails
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* parseInstalls("1.7", "K") // → 1700
|
|
31
|
+
* parseInstalls("21.3", "K") // → 21300
|
|
32
|
+
* parseInstalls("2.1", "M") // → 2100000
|
|
33
|
+
* parseInstalls("120", "") // → 120
|
|
34
|
+
* parseInstalls("invalid", "K") // → 0
|
|
35
|
+
*/
|
|
36
|
+
export function parseInstalls(value, unit) {
|
|
37
|
+
const num = parseFloat(value);
|
|
38
|
+
if (isNaN(num)) return 0;
|
|
39
|
+
|
|
40
|
+
switch (unit.toUpperCase()) {
|
|
41
|
+
case 'K': return Math.round(num * 1_000);
|
|
42
|
+
case 'M': return Math.round(num * 1_000_000);
|
|
43
|
+
case 'B': return Math.round(num * 1_000_000_000);
|
|
44
|
+
default: return Math.round(num);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ─── CLI Output Parser ──────────────────────────────────────────────────────
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Parse the raw multi-line output of `npx skills find <query>` into
|
|
52
|
+
* an array of structured skill records.
|
|
53
|
+
*
|
|
54
|
+
* Each record in the output spans two lines:
|
|
55
|
+
* Line 1: `owner/repo@skill <count>[K|M] installs`
|
|
56
|
+
* Line 2: `└ https://skills.sh/owner/repo/skill`
|
|
57
|
+
*
|
|
58
|
+
* @param {string} rawOutput - Raw stdout from `npx skills find`
|
|
59
|
+
* @returns {Array<{ name: string, installs: number, url: string }>}
|
|
60
|
+
* Sorted by install count (highest first).
|
|
61
|
+
*/
|
|
62
|
+
export function parseFindOutput(rawOutput) {
|
|
63
|
+
const results = [];
|
|
64
|
+
const lines = rawOutput.split('\n');
|
|
65
|
+
|
|
66
|
+
for (let i = 0; i < lines.length; i++) {
|
|
67
|
+
const line = lines[i].trim();
|
|
68
|
+
if (!line) continue;
|
|
69
|
+
|
|
70
|
+
// Match skill line: "steipete/clawdis@github 1.7K installs"
|
|
71
|
+
// "jiulingyun/openclaw-cn@github 21 installs"
|
|
72
|
+
const skillMatch = line.match(
|
|
73
|
+
/^(\S+@\S+)\s+([\d.]+)\s*(K|M|B)?\s*installs?$/i
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
if (!skillMatch) continue;
|
|
77
|
+
|
|
78
|
+
const name = skillMatch[1];
|
|
79
|
+
const installs = parseInstalls(skillMatch[2], skillMatch[3] || '');
|
|
80
|
+
|
|
81
|
+
// Next non-empty line should be the URL (prefixed with └ or similar box-drawing chars)
|
|
82
|
+
let url = '';
|
|
83
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
84
|
+
const nextLine = lines[j].trim();
|
|
85
|
+
if (!nextLine) continue;
|
|
86
|
+
|
|
87
|
+
const urlMatch = nextLine.match(/^[└┗├│─\s]*(https?:\/\/\S+)/);
|
|
88
|
+
if (urlMatch) {
|
|
89
|
+
url = urlMatch[1];
|
|
90
|
+
i = j; // advance past the URL line
|
|
91
|
+
}
|
|
92
|
+
break; // only check the very next non-empty line
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
results.push({ name, installs, url });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return results;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ─── Live Registry Search ───────────────────────────────────────────────────
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Execute `npx skills find <query>` and return parsed results.
|
|
105
|
+
* Falls back gracefully if the `skills` CLI is not installed.
|
|
106
|
+
*
|
|
107
|
+
* @param {string} query - Search term for the skills.sh registry
|
|
108
|
+
* @param {object} [options]
|
|
109
|
+
* @param {number} [options.timeoutMs=15000] - Max execution time in ms
|
|
110
|
+
* @returns {Array<{ name: string, installs: number, url: string }>}
|
|
111
|
+
*/
|
|
112
|
+
export function searchRegistry(query, { timeoutMs = 15_000 } = {}) {
|
|
113
|
+
try {
|
|
114
|
+
const output = execSync(`npx -y skills find "${query.replace(/"/g, '\\"')}"`, {
|
|
115
|
+
timeout: timeoutMs,
|
|
116
|
+
encoding: 'utf8',
|
|
117
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
118
|
+
});
|
|
119
|
+
return parseFindOutput(output);
|
|
120
|
+
} catch (err) {
|
|
121
|
+
// skills CLI not installed or network error — degrade gracefully
|
|
122
|
+
return [];
|
|
123
|
+
}
|
|
124
|
+
}
|