semantu-agents 1.2.0 → 1.2.2
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 +80 -23
- package/cli.mjs +284 -42
- package/package.json +6 -5
- package/skills/public/explore/SKILL.md +34 -0
- package/skills/public/ideation/SKILL.md +19 -83
- package/skills/public/implementation/SKILL.md +4 -1
- package/skills/public/plan/SKILL.md +8 -1
- package/skills/public/review/SKILL.md +3 -0
- package/skills/public/tasks/SKILL.md +10 -2
- package/skills/public/workflow/SKILL.md +16 -0
- package/skills/public/wrapup/SKILL.md +7 -0
package/README.md
CHANGED
|
@@ -1,53 +1,110 @@
|
|
|
1
1
|
# semantu-agents
|
|
2
2
|
|
|
3
|
-
Reusable Claude Code
|
|
3
|
+
Reusable Claude Code and agent skills for Semantu projects.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Project setup
|
|
5
|
+
## Recommended: Global Install
|
|
8
6
|
|
|
9
7
|
```bash
|
|
10
|
-
npx semantu-agents
|
|
8
|
+
npx semantu-agents global
|
|
11
9
|
```
|
|
12
10
|
|
|
13
|
-
Syncs
|
|
11
|
+
Syncs the npm-packaged public skills to:
|
|
12
|
+
|
|
13
|
+
- `~/.claude/skills`
|
|
14
|
+
- `~/.agents/skills`
|
|
15
|
+
|
|
16
|
+
This is the default recommended setup. It keeps application repos clean and makes the shared skills available across projects. Project repos can still define app-specific skills separately.
|
|
17
|
+
|
|
18
|
+
## Updating Global Skills
|
|
19
|
+
|
|
20
|
+
For normal users, rerun:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npx semantu-agents global
|
|
24
|
+
```
|
|
14
25
|
|
|
15
|
-
|
|
26
|
+
For contributors with an editable checkout at `~/.agents-src`, run this from anywhere:
|
|
16
27
|
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
"scripts": {
|
|
20
|
-
"setup": "npx semantu-agents"
|
|
21
|
-
}
|
|
22
|
-
}
|
|
28
|
+
```bash
|
|
29
|
+
npx semantu-agents update
|
|
23
30
|
```
|
|
24
31
|
|
|
25
|
-
|
|
32
|
+
This updates `~/.agents-src/main`, syncs it to `~/.claude/skills` and `~/.agents/skills`, then restores your previous branch when possible. If `~/.agents-src` has uncommitted changes, commit or stash them first.
|
|
33
|
+
|
|
34
|
+
## Contributing Skill Changes
|
|
35
|
+
|
|
36
|
+
Install an editable source checkout:
|
|
26
37
|
|
|
27
38
|
```bash
|
|
28
|
-
npx semantu-agents
|
|
39
|
+
npx semantu-agents dev
|
|
29
40
|
```
|
|
30
41
|
|
|
31
|
-
|
|
42
|
+
This clones or pulls `github.com:Semantu/agents` into `~/.agents-src`, installs a post-merge hook, and syncs that checkout globally.
|
|
32
43
|
|
|
33
|
-
|
|
44
|
+
Dev mode requires repo access. If cloning fails, ask for access to the Semantu agents repo.
|
|
34
45
|
|
|
35
|
-
|
|
46
|
+
Make changes in the source checkout only:
|
|
36
47
|
|
|
37
48
|
```bash
|
|
38
|
-
cd
|
|
49
|
+
cd ~/.agents-src
|
|
39
50
|
git checkout -b my-change
|
|
40
|
-
# edit skills
|
|
41
|
-
|
|
51
|
+
# edit skills/public/... or skills/private/...
|
|
52
|
+
npm run sync
|
|
53
|
+
git add .
|
|
54
|
+
git commit -m "improve workflow skill"
|
|
42
55
|
git push -u origin my-change
|
|
56
|
+
gh pr create
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Do not edit these generated folders directly:
|
|
60
|
+
|
|
61
|
+
- `~/.claude/skills`
|
|
62
|
+
- `~/.agents/skills`
|
|
63
|
+
|
|
64
|
+
They are overwritten by `semantu-agents global`, `semantu-agents sync`, and `semantu-agents update`.
|
|
65
|
+
|
|
66
|
+
The dev post-merge hook runs `node cli.mjs sync` after pulls, so merged changes are synced globally automatically.
|
|
67
|
+
|
|
68
|
+
## Project Setup
|
|
69
|
+
|
|
70
|
+
Project-local setup is still available for repos that intentionally want checked-out helper files:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npx semantu-agents
|
|
43
74
|
```
|
|
44
75
|
|
|
45
|
-
|
|
76
|
+
Most projects should prefer the global install instead.
|
|
77
|
+
|
|
78
|
+
## Docs index
|
|
79
|
+
|
|
80
|
+
Print a markdown or JSON index of docs that use YAML frontmatter.
|
|
46
81
|
|
|
47
82
|
```bash
|
|
48
|
-
|
|
83
|
+
npx semantu-agents docs
|
|
84
|
+
npx semantu-agents docs ideas
|
|
85
|
+
npx semantu-agents docs architecture
|
|
86
|
+
npx semantu-agents docs --all
|
|
87
|
+
npx semantu-agents docs --format markdown
|
|
88
|
+
npx semantu-agents docs --all --format json
|
|
49
89
|
```
|
|
50
90
|
|
|
91
|
+
Supported scopes:
|
|
92
|
+
|
|
93
|
+
- `root` (default) -> `docs/*.md`
|
|
94
|
+
- `architecture` -> `docs/architecture/*.md`
|
|
95
|
+
- `ideas` -> `docs/ideas/*.md`
|
|
96
|
+
- `plans` -> `docs/plans/*.md`
|
|
97
|
+
- `reports` -> `docs/reports/*.md`
|
|
98
|
+
|
|
99
|
+
Notes:
|
|
100
|
+
|
|
101
|
+
- default output is text
|
|
102
|
+
- supported formats: `text`, `markdown`, `json`
|
|
103
|
+
- JSON uses short keys: `f` = file, `s` = summary, `d` = folder
|
|
104
|
+
- `--all` adds a folder column in markdown, or `d` in JSON
|
|
105
|
+
- `--fix` adds an empty `summary` field when frontmatter is missing it
|
|
106
|
+
- missing summaries stay blank; the command does not warn
|
|
107
|
+
|
|
51
108
|
## Skill layout
|
|
52
109
|
|
|
53
110
|
```
|
package/cli.mjs
CHANGED
|
@@ -1,29 +1,33 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
*
|
|
6
|
-
* Usage:
|
|
7
|
-
* npx semantu-agents — sync public skills + try git clone for private skills
|
|
8
|
-
* npx semantu-agents --global — sync to ~/.claude/ and ~/.agents/ for all projects
|
|
9
|
-
*
|
|
10
|
-
* Public skills are always available (shipped with the npm package).
|
|
11
|
-
* Private skills require git access to github.com:Semantu/agents.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import {cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync} from 'node:fs';
|
|
3
|
+
import {execSync} from 'node:child_process';
|
|
4
|
+
import {cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync} from 'node:fs';
|
|
15
5
|
import {homedir} from 'node:os';
|
|
16
6
|
import path from 'node:path';
|
|
17
|
-
import {execSync} from 'node:child_process';
|
|
18
7
|
import {fileURLToPath} from 'node:url';
|
|
19
8
|
|
|
20
9
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
const command = args[0];
|
|
12
|
+
|
|
13
|
+
const projectRoot = process.cwd();
|
|
21
14
|
const skillsRepo = 'git@github.com:Semantu/agents.git';
|
|
15
|
+
const DOC_FOLDERS = {
|
|
16
|
+
root: 'docs',
|
|
17
|
+
architecture: path.join('docs', 'architecture'),
|
|
18
|
+
ideas: path.join('docs', 'ideas'),
|
|
19
|
+
plans: path.join('docs', 'plans'),
|
|
20
|
+
reports: path.join('docs', 'reports'),
|
|
21
|
+
};
|
|
22
22
|
|
|
23
23
|
function run(cmd, opts) {
|
|
24
24
|
return execSync(cmd, {stdio: 'inherit', ...opts});
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
function output(cmd, opts) {
|
|
28
|
+
return execSync(cmd, {encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], ...opts}).trim();
|
|
29
|
+
}
|
|
30
|
+
|
|
27
31
|
function cloneOrPull(dir) {
|
|
28
32
|
if (existsSync(path.join(dir, '.git'))) {
|
|
29
33
|
console.log('Updating agents repo...');
|
|
@@ -34,11 +38,23 @@ function cloneOrPull(dir) {
|
|
|
34
38
|
}
|
|
35
39
|
}
|
|
36
40
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
function cloneIfMissing(dir) {
|
|
42
|
+
if (existsSync(path.join(dir, '.git'))) {
|
|
43
|
+
console.log('Using existing editable agents repo at ~/.agents-src');
|
|
44
|
+
} else {
|
|
45
|
+
console.log('Cloning agents repo...');
|
|
46
|
+
run(`git clone ${skillsRepo} ${dir}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function globalTargets() {
|
|
51
|
+
const home = homedir();
|
|
52
|
+
return [
|
|
53
|
+
path.join(home, '.claude', 'skills'),
|
|
54
|
+
path.join(home, '.agents', 'skills'),
|
|
55
|
+
];
|
|
56
|
+
}
|
|
57
|
+
|
|
42
58
|
function syncSkillsInto(skillsSource, targets) {
|
|
43
59
|
if (!existsSync(skillsSource)) return;
|
|
44
60
|
|
|
@@ -48,33 +64,81 @@ function syncSkillsInto(skillsSource, targets) {
|
|
|
48
64
|
}
|
|
49
65
|
}
|
|
50
66
|
|
|
51
|
-
function
|
|
52
|
-
const
|
|
53
|
-
const targets =
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
];
|
|
67
|
+
function syncFromSource(sourceDir, label = 'source checkout', options = {}) {
|
|
68
|
+
const includePrivate = options.includePrivate ?? true;
|
|
69
|
+
const targets = globalTargets();
|
|
70
|
+
const publicSkills = path.join(sourceDir, 'skills', 'public');
|
|
71
|
+
const privateSkills = path.join(sourceDir, 'skills', 'private');
|
|
57
72
|
|
|
58
|
-
// 1. Always sync public skills from the npm package
|
|
59
|
-
const publicSkills = path.join(__dirname, 'skills', 'public');
|
|
60
73
|
for (const dest of targets) {
|
|
61
74
|
rmSync(dest, {recursive: true, force: true});
|
|
62
75
|
}
|
|
63
|
-
syncSkillsInto(publicSkills, targets);
|
|
64
|
-
console.log('Synced public skills from npm package');
|
|
65
76
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
try {
|
|
69
|
-
cloneOrPull(srcDir);
|
|
70
|
-
const privateSkills = path.join(srcDir, 'skills', 'private');
|
|
77
|
+
syncSkillsInto(publicSkills, targets);
|
|
78
|
+
if (includePrivate) {
|
|
71
79
|
syncSkillsInto(privateSkills, targets);
|
|
72
|
-
console.log('Synced private skills from git repo');
|
|
73
|
-
} catch {
|
|
74
|
-
console.log('Skipped private skills — no git access to agents repo.');
|
|
75
80
|
}
|
|
76
81
|
|
|
77
|
-
console.log(
|
|
82
|
+
console.log(`Synced skills from ${label} -> ~/.claude/skills/ and ~/.agents/skills/`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function setupGlobal() {
|
|
86
|
+
syncFromSource(__dirname, 'npm package', {includePrivate: false});
|
|
87
|
+
console.log('\nDone. Public skills synced globally. Run `npx semantu-agents dev` to install an editable source checkout.');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function installPostMergeHook(repoDir) {
|
|
91
|
+
const hooksDir = path.join(repoDir, '.git', 'hooks');
|
|
92
|
+
const hookPath = path.join(hooksDir, 'post-merge');
|
|
93
|
+
const hook = `#!/bin/sh
|
|
94
|
+
cd "$(git rev-parse --show-toplevel)" && node cli.mjs sync
|
|
95
|
+
`;
|
|
96
|
+
|
|
97
|
+
mkdirSync(hooksDir, {recursive: true});
|
|
98
|
+
writeFileSync(hookPath, hook, {mode: 0o755});
|
|
99
|
+
console.log('Installed post-merge hook to sync global skills after pulls');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function setupDev() {
|
|
103
|
+
const srcDir = path.join(homedir(), '.agents-src');
|
|
104
|
+
|
|
105
|
+
cloneIfMissing(srcDir);
|
|
106
|
+
installPostMergeHook(srcDir);
|
|
107
|
+
syncFromSource(srcDir, '~/.agents-src');
|
|
108
|
+
|
|
109
|
+
console.log('\nDone. Edit skills in ~/.agents-src, run `node cli.mjs sync`, then commit and open a PR.');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function syncGlobalFromCurrentCheckout() {
|
|
113
|
+
syncFromSource(__dirname, 'current checkout');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function updateDevCheckout() {
|
|
117
|
+
const srcDir = path.join(homedir(), '.agents-src');
|
|
118
|
+
|
|
119
|
+
if (!existsSync(path.join(srcDir, '.git'))) {
|
|
120
|
+
console.log('No editable checkout found at ~/.agents-src.');
|
|
121
|
+
console.log('Run `npx semantu-agents dev` if you have access to github.com:Semantu/agents.');
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const currentBranch = output('git branch --show-current', {cwd: srcDir});
|
|
126
|
+
const dirty = output('git status --porcelain', {cwd: srcDir});
|
|
127
|
+
|
|
128
|
+
if (dirty) {
|
|
129
|
+
console.log('Cannot update ~/.agents-src because it has uncommitted changes.');
|
|
130
|
+
console.log('Commit, stash, or discard them, then rerun `npx semantu-agents update`.');
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
run('git fetch origin main', {cwd: srcDir});
|
|
135
|
+
run('git switch main', {cwd: srcDir});
|
|
136
|
+
run('git pull --ff-only origin main', {cwd: srcDir});
|
|
137
|
+
syncFromSource(srcDir, '~/.agents-src');
|
|
138
|
+
|
|
139
|
+
if (currentBranch && currentBranch !== 'main') {
|
|
140
|
+
run(`git switch ${currentBranch}`, {cwd: srcDir});
|
|
141
|
+
}
|
|
78
142
|
}
|
|
79
143
|
|
|
80
144
|
function setupProject() {
|
|
@@ -105,7 +169,6 @@ function setupProject() {
|
|
|
105
169
|
console.log('Skipped private skills — no git access to agents repo.');
|
|
106
170
|
}
|
|
107
171
|
|
|
108
|
-
// 3. Patch package.json scripts
|
|
109
172
|
const pkgPath = path.join(projectRoot, 'package.json');
|
|
110
173
|
if (existsSync(pkgPath)) {
|
|
111
174
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
|
|
@@ -128,7 +191,6 @@ function setupProject() {
|
|
|
128
191
|
}
|
|
129
192
|
}
|
|
130
193
|
|
|
131
|
-
// 4. Patch .gitignore
|
|
132
194
|
const ignorePath = path.join(projectRoot, '.gitignore');
|
|
133
195
|
const ignoreEntries = ['packages/', '.claude/', '.agents/'];
|
|
134
196
|
let ignoreContent = existsSync(ignorePath) ? readFileSync(ignorePath, 'utf8') : '';
|
|
@@ -146,7 +208,6 @@ function setupProject() {
|
|
|
146
208
|
console.log('Updated .gitignore');
|
|
147
209
|
}
|
|
148
210
|
|
|
149
|
-
// 5. Ensure docs directories exist
|
|
150
211
|
for (const dir of ['docs/ideas', 'docs/plans', 'docs/reports']) {
|
|
151
212
|
const fullPath = path.join(projectRoot, dir);
|
|
152
213
|
if (!existsSync(fullPath)) {
|
|
@@ -156,12 +217,193 @@ function setupProject() {
|
|
|
156
217
|
}
|
|
157
218
|
}
|
|
158
219
|
|
|
159
|
-
|
|
220
|
+
function parseDocsArgs(inputArgs) {
|
|
221
|
+
const options = {
|
|
222
|
+
format: 'text',
|
|
223
|
+
fix: false,
|
|
224
|
+
all: false,
|
|
225
|
+
scope: 'root',
|
|
226
|
+
dir: projectRoot,
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
for (let i = 0; i < inputArgs.length; i += 1) {
|
|
230
|
+
const arg = inputArgs[i];
|
|
231
|
+
|
|
232
|
+
if (arg === '--all') {
|
|
233
|
+
options.all = true;
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
if (arg === '--fix') {
|
|
237
|
+
options.fix = true;
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
if (arg === '--format') {
|
|
241
|
+
options.format = inputArgs[i + 1] || 'markdown';
|
|
242
|
+
i += 1;
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
if (arg === '--dir') {
|
|
246
|
+
options.dir = path.resolve(projectRoot, inputArgs[i + 1] || '.');
|
|
247
|
+
i += 1;
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
if (arg === 'json' || arg === 'markdown' || arg === 'text') {
|
|
251
|
+
options.format = arg;
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
if (arg === 'all') {
|
|
255
|
+
options.all = true;
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (Object.hasOwn(DOC_FOLDERS, arg)) {
|
|
259
|
+
options.scope = arg;
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return options;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function listMarkdownFiles(dirPath) {
|
|
268
|
+
if (!existsSync(dirPath)) {
|
|
269
|
+
return [];
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return readdirSync(dirPath)
|
|
273
|
+
.filter(name => name.endsWith('.md'))
|
|
274
|
+
.filter(name => statSync(path.join(dirPath, name)).isFile())
|
|
275
|
+
.sort()
|
|
276
|
+
.map(name => path.join(dirPath, name));
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
async function ensureSummary(filePath) {
|
|
280
|
+
const {default: matter} = await import('gray-matter');
|
|
281
|
+
const source = readFileSync(filePath, 'utf8');
|
|
282
|
+
const parsed = matter(source);
|
|
283
|
+
|
|
284
|
+
if (typeof parsed.data.summary === 'string') {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
writeFileSync(
|
|
289
|
+
filePath,
|
|
290
|
+
matter.stringify(parsed.content, {
|
|
291
|
+
summary: '',
|
|
292
|
+
...parsed.data,
|
|
293
|
+
}),
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function escapeCell(value) {
|
|
298
|
+
return String(value || '')
|
|
299
|
+
.replace(/\n+/g, ' ')
|
|
300
|
+
.replace(/\|/g, '\\|')
|
|
301
|
+
.trim();
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
async function loadEntries(scope, options) {
|
|
305
|
+
const {default: matter} = await import('gray-matter');
|
|
306
|
+
const folderPath = path.join(options.dir, DOC_FOLDERS[scope]);
|
|
307
|
+
const files = listMarkdownFiles(folderPath);
|
|
308
|
+
|
|
309
|
+
if (options.fix) {
|
|
310
|
+
for (const file of files) {
|
|
311
|
+
await ensureSummary(file);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return files.map(filePath => {
|
|
316
|
+
const parsed = matter(readFileSync(filePath, 'utf8'));
|
|
317
|
+
return {
|
|
318
|
+
folder: scope,
|
|
319
|
+
file: path.basename(filePath),
|
|
320
|
+
summary: typeof parsed.data.summary === 'string' ? parsed.data.summary : '',
|
|
321
|
+
};
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function renderMarkdown(entries, includeFolder) {
|
|
326
|
+
const header = includeFolder
|
|
327
|
+
? ['| folder | file | summary |', '|--------|------|---------|']
|
|
328
|
+
: ['| file | summary |', '|------|---------|'];
|
|
329
|
+
|
|
330
|
+
const rows = entries.map(entry =>
|
|
331
|
+
includeFolder
|
|
332
|
+
? `| ${escapeCell(entry.folder)} | ${escapeCell(entry.file)} | ${escapeCell(entry.summary)} |`
|
|
333
|
+
: `| ${escapeCell(entry.file)} | ${escapeCell(entry.summary)} |`,
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
return [...header, ...rows].join('\n');
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function renderText(entries, includeFolder) {
|
|
340
|
+
if (includeFolder) {
|
|
341
|
+
const lines = [];
|
|
342
|
+
let currentFolder = null;
|
|
343
|
+
|
|
344
|
+
for (const entry of entries) {
|
|
345
|
+
if (entry.folder !== currentFolder) {
|
|
346
|
+
if (lines.length > 0) {
|
|
347
|
+
lines.push('');
|
|
348
|
+
}
|
|
349
|
+
currentFolder = entry.folder;
|
|
350
|
+
lines.push(entry.folder);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
lines.push(` ${entry.file}`);
|
|
354
|
+
if (entry.summary) {
|
|
355
|
+
lines.push(` ${entry.summary}`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return lines.join('\n');
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
return entries
|
|
363
|
+
.flatMap(entry =>
|
|
364
|
+
entry.summary ? [entry.file, ` ${entry.summary}`] : [entry.file],
|
|
365
|
+
)
|
|
366
|
+
.join('\n');
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function renderJson(entries, includeFolder) {
|
|
370
|
+
const rows = entries.map(entry =>
|
|
371
|
+
includeFolder
|
|
372
|
+
? {d: entry.folder, f: entry.file, s: entry.summary}
|
|
373
|
+
: {f: entry.file, s: entry.summary},
|
|
374
|
+
);
|
|
375
|
+
|
|
376
|
+
return JSON.stringify(rows, null, 2);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
async function docs(inputArgs) {
|
|
380
|
+
const options = parseDocsArgs(inputArgs);
|
|
381
|
+
const scopes = options.all ? Object.keys(DOC_FOLDERS) : [options.scope];
|
|
382
|
+
const entries = (await Promise.all(scopes.map(scope => loadEntries(scope, options)))).flat();
|
|
383
|
+
const includeFolder = options.all;
|
|
384
|
+
|
|
385
|
+
const output =
|
|
386
|
+
options.format === 'json'
|
|
387
|
+
? renderJson(entries, includeFolder)
|
|
388
|
+
: options.format === 'markdown'
|
|
389
|
+
? renderMarkdown(entries, includeFolder)
|
|
390
|
+
: renderText(entries, includeFolder);
|
|
391
|
+
|
|
392
|
+
process.stdout.write(`${output}\n`);
|
|
393
|
+
}
|
|
160
394
|
|
|
161
395
|
const isGlobal = process.argv.includes('--global') || process.argv.includes('-g');
|
|
162
396
|
|
|
163
|
-
if (
|
|
397
|
+
if (command === 'docs') {
|
|
398
|
+
await docs(args.slice(1));
|
|
399
|
+
} else if (command === 'global' || isGlobal) {
|
|
164
400
|
setupGlobal();
|
|
401
|
+
} else if (command === 'dev') {
|
|
402
|
+
setupDev();
|
|
403
|
+
} else if (command === 'sync') {
|
|
404
|
+
syncGlobalFromCurrentCheckout();
|
|
405
|
+
} else if (command === 'update') {
|
|
406
|
+
updateDevCheckout();
|
|
165
407
|
} else {
|
|
166
408
|
setupProject();
|
|
167
409
|
}
|
package/package.json
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "semantu-agents",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Reusable Claude Code skills and hooks for Semantu projects",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"bin":
|
|
7
|
-
"semantu-agents": "cli.mjs"
|
|
8
|
-
},
|
|
6
|
+
"bin": "cli.mjs",
|
|
9
7
|
"files": [
|
|
10
8
|
"cli.mjs",
|
|
11
9
|
"skills/public"
|
|
12
10
|
],
|
|
13
11
|
"scripts": {
|
|
14
|
-
"sync": "node
|
|
12
|
+
"sync": "node cli.mjs sync"
|
|
15
13
|
},
|
|
16
14
|
"publishConfig": {
|
|
17
15
|
"access": "public"
|
|
@@ -19,5 +17,8 @@
|
|
|
19
17
|
"devDependencies": {
|
|
20
18
|
"@changesets/changelog-github": "^0.5.2",
|
|
21
19
|
"@changesets/cli": "^2.29.8"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"gray-matter": "^4.0.3"
|
|
22
23
|
}
|
|
23
24
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: explore
|
|
3
|
+
description: Deeply evaluate a topic with context, 3 viable approaches, tradeoffs, and a recommendation without forcing a full ideation-mode cycle.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Instructions
|
|
7
|
+
|
|
8
|
+
## Objective
|
|
9
|
+
|
|
10
|
+
Provide a reusable deep-dive format for `explore <topic>` in any mode, including decomposition of broad topics into concrete decisions.
|
|
11
|
+
|
|
12
|
+
## Entry gate
|
|
13
|
+
|
|
14
|
+
Run this skill when the user explicitly says `explore <topic>` (or clearly asks to explore a topic in this format).
|
|
15
|
+
|
|
16
|
+
## Steps
|
|
17
|
+
|
|
18
|
+
1. Confirm scope only if the topic is ambiguous; otherwise proceed directly.
|
|
19
|
+
2. Decompose the topic into decision candidates and unknowns.
|
|
20
|
+
3. For each decision, classify as `must decide now` or `can defer`.
|
|
21
|
+
4. For each `must decide now` decision, give concise context and assumptions, then provide exactly 3 viable approaches (A-C).
|
|
22
|
+
5. For each approach, list pros, cons, and risks.
|
|
23
|
+
6. Recommend one approach (A/B/C) with a one-line rationale.
|
|
24
|
+
7. If there are multiple decisions, present them in batches of 3 by default (use fewer only when fewer remain or when the user asks for a different batch size). Start with `Decision x-y of N`, and end with `Recap: 1A 2C 3B`; ask for agreement or edits.
|
|
25
|
+
8. Iterate until consent; no feedback on a decision counts as acceptance after an explicit agreement prompt.
|
|
26
|
+
9. Recurse only for nested decisions classified as `must decide now`; defer the rest. Default max depth is 2 unless the user asks for deeper drilldown.
|
|
27
|
+
10. After consent, ask whether to continue the current mode or switch modes.
|
|
28
|
+
|
|
29
|
+
## Guardrails
|
|
30
|
+
|
|
31
|
+
- Do not force a mode switch by default; this skill can run inside any active mode.
|
|
32
|
+
- Do not create ideation/plan artifacts unless the active mode requires them or the user asks.
|
|
33
|
+
- Keep outputs structured and concise; avoid repeating unchanged context.
|
|
34
|
+
- Do not recurse indefinitely; respect the depth cap and defer non-blocking items.
|
|
@@ -7,99 +7,35 @@ description: Explore and compare candidate implementation routes before committi
|
|
|
7
7
|
|
|
8
8
|
## Objective
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Surface unknowns, assumptions, and architecture choices before committing to a plan.
|
|
11
11
|
|
|
12
12
|
## Entry gate
|
|
13
13
|
|
|
14
|
-
Run this mode
|
|
14
|
+
Run this mode when the user explicitly chooses ideation, or when workflow routes brainstorming into ideation.
|
|
15
15
|
|
|
16
16
|
## Steps
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
```markdown
|
|
32
|
-
# <Topic> — Ideation
|
|
33
|
-
|
|
34
|
-
## Context
|
|
35
|
-
<problem statement, relevant code references>
|
|
36
|
-
|
|
37
|
-
## Goals
|
|
38
|
-
<what we're trying to achieve>
|
|
39
|
-
|
|
40
|
-
## Open Questions
|
|
41
|
-
- [ ] Question 1
|
|
42
|
-
- [ ] Question 2
|
|
43
|
-
|
|
44
|
-
## Decisions
|
|
45
|
-
| # | Decision | Chosen | Rationale |
|
|
46
|
-
|---|----------|--------|-----------|
|
|
47
|
-
|
|
48
|
-
## Notes
|
|
49
|
-
<scratchpad for explored approaches, discarded ideas>
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### 3. Identify everything that needs deciding
|
|
53
|
-
|
|
54
|
-
Before proposing solutions, discover and list all decision points:
|
|
55
|
-
- Open questions about scope and requirements
|
|
56
|
-
- Architecture decisions needed
|
|
57
|
-
- Technical unknowns requiring investigation
|
|
58
|
-
- Constraints and dependencies
|
|
59
|
-
|
|
60
|
-
Present this list to the user and ask if anything is missing.
|
|
61
|
-
|
|
62
|
-
### 4. Walk through decisions one at a time
|
|
63
|
-
|
|
64
|
-
For each decision point, present in chat:
|
|
65
|
-
- **Full context** — relevant code snippets, existing patterns, constraints
|
|
66
|
-
- **2–3 approaches** with concrete code examples where helpful
|
|
67
|
-
- **Pros/cons** for each approach
|
|
68
|
-
- **Recommended path** with reasoning
|
|
69
|
-
|
|
70
|
-
**Progress indicator:** Always tell the user where they are — e.g. "Decision 2 of 5" or "Gap 3 of 4" — so they know how many remain before the next mode.
|
|
71
|
-
|
|
72
|
-
When assessing the viability of a specific approach requires reading code or checking feasibility, spawn a research subagent for that investigation and incorporate its findings into the discussion. Do not spawn subagents for the creative work of generating approaches — that stays with the main agent.
|
|
73
|
-
|
|
74
|
-
Wait for the user's input before moving to the next decision. Do not batch multiple decisions into one message.
|
|
75
|
-
|
|
76
|
-
### 5. Record as you go
|
|
77
|
-
|
|
78
|
-
After each decision is made:
|
|
79
|
-
- Check off the resolved question in Open Questions
|
|
80
|
-
- Add a row to the Decisions table
|
|
81
|
-
- Update Notes with any useful context that came up
|
|
82
|
-
|
|
83
|
-
### 6. Check for completeness
|
|
84
|
-
|
|
85
|
-
After working through the list, review what remains:
|
|
86
|
-
- Are all open questions resolved?
|
|
87
|
-
- Are there new questions that surfaced during discussion?
|
|
88
|
-
- Does the user want to explore anything further?
|
|
89
|
-
|
|
90
|
-
Keep iterating until everything is decided.
|
|
18
|
+
1. Read relevant code, tests, and docs first.
|
|
19
|
+
2. Create/update `docs/ideas/<nnn>-<topic>.md`.
|
|
20
|
+
- For new ideation docs, `<nnn>` MUST be the next available 3-digit prefix in `docs/ideas`.
|
|
21
|
+
- Every new ideation doc MUST start with YAML frontmatter containing at least a summary key.
|
|
22
|
+
3. Discover impacted repo/package test surfaces:
|
|
23
|
+
- Locate changed package roots (root repo and/or `packages/<name>` roots as applicable).
|
|
24
|
+
- For each impacted package, identify quick test commands (target total runtime 1-2 minutes), full/slow test commands, and where each was found (`package.json` scripts first, README fallback).
|
|
25
|
+
- Record unknowns/gaps when no reliable quick regression command exists.
|
|
26
|
+
4. Build a decision map: list major decisions, unknowns, and research gaps.
|
|
27
|
+
5. Classify each item as `must decide now` (blocks planning) or `can defer`.
|
|
28
|
+
6. Use the `explore` skill for each `must decide now` decision/topic.
|
|
29
|
+
7. Record accepted choices, deferred unknowns, and discovered test surfaces in the ideation doc.
|
|
30
|
+
8. Continue until blocking decisions reach consent; then ask whether to switch to `plan` mode.
|
|
91
31
|
|
|
92
32
|
## Guardrails
|
|
93
33
|
|
|
94
|
-
- **Chat is the primary medium.** The ideation doc tracks progress — it is not the deliverable.
|
|
95
34
|
- Do not write implementation code in this mode.
|
|
96
|
-
- Do not
|
|
97
|
-
- Do not suggest plan mode until all open questions are resolved and the user confirms nothing is left.
|
|
35
|
+
- Do not convert ideation into a plan unless the user explicitly requests it.
|
|
98
36
|
|
|
99
37
|
## Exit criteria
|
|
100
38
|
|
|
101
|
-
-
|
|
102
|
-
-
|
|
103
|
-
- User has explicitly confirmed
|
|
104
|
-
- **Plan mode** (default) — continue manually through the workflow.
|
|
105
|
-
- **Automatic mode** — switch to automatic mode and run plan → tasks → implementation → review autonomously.
|
|
39
|
+
- Blocking decisions and deferred unknowns are documented.
|
|
40
|
+
- User feedback has narrowed choices.
|
|
41
|
+
- User has explicitly confirmed whether to switch to plan mode or stay in ideation mode.
|
|
@@ -14,12 +14,14 @@ Run only after explicit user confirmation to enter implementation mode, with an
|
|
|
14
14
|
1. Confirm the approved plan exists on disk at `docs/plans/<nnn>-<topic>.md`. Tool-native plan mode alone is not sufficient.
|
|
15
15
|
2. If this plan stems from an ideation doc, remove the originating ideation doc in `docs/ideas` when implementation begins.
|
|
16
16
|
3. Implement one planned phase at a time.
|
|
17
|
-
4. Run the phase validation criteria and record results.
|
|
17
|
+
4. Run the phase validation criteria and record results, including the quick regression gate for impacted packages (target total runtime 1-2 minutes).
|
|
18
18
|
5. After a phase is completed, update `docs/plans/<nnn>-<topic>.md` to reflect completed work and mark phase status. This update is mandatory before moving to the next phase.
|
|
19
19
|
6. Create one commit per phase, including code changes and the phase-completion plan update in the same commit.
|
|
20
20
|
7. Continue to next phase without pausing only if there are no deviations and no major problems.
|
|
21
21
|
8. If any deviation/blocker/major risk appears, pause and report.
|
|
22
22
|
|
|
23
|
+
Full/slow test suites may be deferred until review by default. Run deferred suites earlier only if the user requests it.
|
|
24
|
+
|
|
23
25
|
## Parallel execution
|
|
24
26
|
|
|
25
27
|
When the plan marks phases as parallelizable, use the Task tool (or any available sub-agent spawning tool) to run them concurrently:
|
|
@@ -47,6 +49,7 @@ When the plan marks phases as parallelizable, use the Task tool (or any availabl
|
|
|
47
49
|
- If the originating ideation doc is ambiguous, pause and ask the user which ideation file to remove.
|
|
48
50
|
- Do not skip plan updates between completed phases.
|
|
49
51
|
- Do not switch to review/wrapup implicitly; ask the user to explicitly confirm the next mode.
|
|
52
|
+
- Do not mark a phase complete if its quick regression gate fails.
|
|
50
53
|
|
|
51
54
|
## Exit criteria
|
|
52
55
|
|
|
@@ -13,6 +13,7 @@ Run only when the user explicitly confirms plan mode (for example: converting id
|
|
|
13
13
|
|
|
14
14
|
1. Create/update `docs/plans/<nnn>-<topic>.md`. This on-disk plan file is mandatory.
|
|
15
15
|
- When creating a new plan doc (including ideation -> plan conversion), `<nnn>` MUST be the next available 3-digit prefix in `docs/plans`.
|
|
16
|
+
- Every new plan doc MUST start with YAML frontmatter containing at least a summary key.
|
|
16
17
|
2. Focus on chosen route(s), not all explored options.
|
|
17
18
|
3. **Carry forward all decided features and details from the ideation doc.** Every feature, API surface, design detail, and example that was explored and not explicitly rejected must appear in the plan. No idea can be silently dropped. If unsure whether something was tentatively discussed or firmly decided, ask the user for clarification rather than omitting it.
|
|
18
19
|
4. Include:
|
|
@@ -22,8 +23,14 @@ Run only when the user explicitly confirms plan mode (for example: converting id
|
|
|
22
23
|
- Potential pitfalls
|
|
23
24
|
- Remaining unclear areas/decisions
|
|
24
25
|
- **Inter-component contracts**: When the architecture has separable parts (layers, modules, packages), make the contracts between them explicit — type definitions, function signatures, shared data structures. These contracts enable parallel implementation in tasks mode.
|
|
26
|
+
- **Test strategy**:
|
|
27
|
+
- impacted repo/package list
|
|
28
|
+
- quick regression gate commands (target total runtime 1-2 minutes) to run after each phase
|
|
29
|
+
- full/slow test commands deferred to review
|
|
30
|
+
- command source notes (`package.json` scripts and/or README)
|
|
31
|
+
- explicit skip/defer rationale for slow suites
|
|
25
32
|
5. Mention tradeoffs only to explain why chosen paths were selected.
|
|
26
|
-
|
|
33
|
+
6. Continuously refine the plan with user feedback until it is explicitly approved for implementation.
|
|
27
34
|
|
|
28
35
|
## Guardrails
|
|
29
36
|
|
|
@@ -16,6 +16,7 @@ Run only when the user explicitly confirms review mode.
|
|
|
16
16
|
3. Identify what is still missing to make this work more complete.
|
|
17
17
|
4. Identify gaps or risks in the current implementation.
|
|
18
18
|
5. Identify likely future work required for fuller completeness.
|
|
19
|
+
6. Re-run deferred full/slow test suites for all impacted repos/packages from the plan's test strategy, and report pass/fail with any skipped checks and reasons.
|
|
19
20
|
|
|
20
21
|
## Parallel review via subagents
|
|
21
22
|
|
|
@@ -102,12 +103,14 @@ The ideation within this section follows the same rules as the ideation skill:
|
|
|
102
103
|
- Only convert review findings into iteration content after the user confirms which gaps to address.
|
|
103
104
|
- For newly uncovered work, always go through ideation first — never skip straight to tasks or implementation.
|
|
104
105
|
- If the user's response involves clarifying approach or scope, treat this as still in the clarification loop — ask follow-ups for any remaining ambiguity.
|
|
106
|
+
- Do not claim review completion without test evidence for impacted packages (or explicit user-approved skips).
|
|
105
107
|
|
|
106
108
|
## Exit criteria
|
|
107
109
|
|
|
108
110
|
- Gaps are triaged with explicit user decisions (now vs defer).
|
|
109
111
|
- If iterating: ideation for all selected gaps is recorded in the plan doc, and user has confirmed next step.
|
|
110
112
|
- If deferring: ideation docs were created for deferred gaps.
|
|
113
|
+
- Deferred full/slow test suites for impacted packages were executed and reported, or explicitly skipped with user approval.
|
|
111
114
|
- User has explicitly confirmed whether to:
|
|
112
115
|
- **Iterate** — proceed to plan the ideated gaps (manually via plan mode, or via automatic mode for plan → tasks → implementation → review)
|
|
113
116
|
- **Wrapup** — no more work needed, move to wrapup mode
|
|
@@ -15,8 +15,12 @@ Run only when the user explicitly confirms tasks mode.
|
|
|
15
15
|
2. Define implementation phases.
|
|
16
16
|
3. Define concrete tasks under each phase.
|
|
17
17
|
4. Add explicit validation criteria per phase (for example: unit tests, integration tests, build/typecheck commands, targeted runtime checks).
|
|
18
|
-
5.
|
|
19
|
-
|
|
18
|
+
5. For every phase, define:
|
|
19
|
+
- phase-specific tests to add/update when behavior/API changes,
|
|
20
|
+
- a quick regression gate using discovered package test commands (target total runtime 1-2 minutes),
|
|
21
|
+
- full/slow suites deferred to review.
|
|
22
|
+
6. Write detailed test specifications for every phase (see **Test specification** below).
|
|
23
|
+
7. Ensure phases are commit-friendly (one commit per phase).
|
|
20
24
|
|
|
21
25
|
## Parallel execution
|
|
22
26
|
|
|
@@ -33,6 +37,10 @@ Phases should be designed for maximum parallelism — different agents may imple
|
|
|
33
37
|
|
|
34
38
|
Every phase must include a **Validation** section that describes the checks an implementing agent must perform and pass before considering the phase complete. Validation is not limited to coded tests — it includes any check that truly proves the work is correct.
|
|
35
39
|
|
|
40
|
+
Validation must separate:
|
|
41
|
+
- **Quick phase gate**: checks that should finish in 1-2 minutes total and must pass after each phase.
|
|
42
|
+
- **Full review gate**: slow suites deferred to review unless the user requests earlier execution.
|
|
43
|
+
|
|
36
44
|
**Types of validation checks** (use whichever are appropriate for the phase):
|
|
37
45
|
- **Unit/integration tests**: Coded test files with named test cases and concrete assertions.
|
|
38
46
|
- **Compilation/type-check**: e.g. `npm run compile` passes with no errors.
|
|
@@ -9,6 +9,12 @@ description: Enforce the explicit mode cadence (ideation -> plan -> tasks -> imp
|
|
|
9
9
|
|
|
10
10
|
- Default for any task that touches code or modifies planning/docs.
|
|
11
11
|
|
|
12
|
+
## Shortcut triggers
|
|
13
|
+
|
|
14
|
+
- If the user says `explore <topic>`, run the `explore` skill immediately, even when already inside another mode.
|
|
15
|
+
- `explore` is a deep-dive formatting shortcut, not a mode switch by itself.
|
|
16
|
+
- After finishing an `explore` pass, ask whether to continue the current mode or switch modes.
|
|
17
|
+
|
|
12
18
|
## Mode selection at task start
|
|
13
19
|
|
|
14
20
|
- If the user has already explicitly chosen a mode (or explicitly called a mode skill), enter that mode directly.
|
|
@@ -51,6 +57,16 @@ These transition gates apply to standard modes. `automatic` mode is an explicit
|
|
|
51
57
|
- `review`: emit findings in chat first; after user decisions, update plan with now-work tasks and/or create ideation docs for deferred future work
|
|
52
58
|
- `wrapup`: convert plan into a final report doc in `docs/reports`, then remove the plan doc after report approval
|
|
53
59
|
|
|
60
|
+
## Frontmatter requirements for docs
|
|
61
|
+
|
|
62
|
+
- Any new doc created under `docs/ideas`, `docs/plans`, `docs/reports`, or `docs/architecture` MUST start with YAML frontmatter.
|
|
63
|
+
- Minimum required frontmatter for new docs:
|
|
64
|
+
```yaml
|
|
65
|
+
---
|
|
66
|
+
summary: One or two lines describing the document.
|
|
67
|
+
---
|
|
68
|
+
```
|
|
69
|
+
|
|
54
70
|
## Global constraints
|
|
55
71
|
|
|
56
72
|
- Tool-native plan modes do NOT replace the on-disk plan file requirement.
|
|
@@ -24,6 +24,13 @@ Also treat any user request to prepare/open/update a PR, or draft PR title/body/
|
|
|
24
24
|
5. Update `docs/plans/<nnn>-<topic>.md` by appending a `## REVIEW` section at the end with wrapup outcomes and PR-readiness status.
|
|
25
25
|
6. Convert `docs/plans/<nnn>-<topic>.md` into a report doc in `docs/reports/<nnn>-<topic>.md`.
|
|
26
26
|
- For this conversion, the report `<nnn>` MUST be the next available 3-digit prefix in `docs/reports` (do not reuse the plan prefix when it conflicts).
|
|
27
|
+
- The report MUST start with YAML frontmatter containing a summary key.
|
|
28
|
+
```yaml
|
|
29
|
+
---
|
|
30
|
+
summary: One or two lines describing the final implemented outcome.
|
|
31
|
+
---
|
|
32
|
+
```
|
|
33
|
+
- When converting from a plan, rewrite the `summary` so it reflects the completed result and report scope, not the earlier proposed plan.
|
|
27
34
|
- Update any references to the report path after conversion.
|
|
28
35
|
7. **Report quality** — see the dedicated section below. The report is a condensed but comprehensive record of everything that was done. It is NOT a brief summary.
|
|
29
36
|
8. **Remove the plan doc** `docs/plans/<nnn>-<topic>.md` after the report is written. Do not wait until after the PR — the plan must be gone before the final commit.
|