@sous-io/sous 0.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.
Files changed (82) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +154 -0
  3. package/bin/run.js +17 -0
  4. package/bin/xcv +5 -0
  5. package/package.json +81 -0
  6. package/shared-prompts/_partials/resume-task.md +51 -0
  7. package/shared-prompts/_partials/sub-agent-delegation.md +32 -0
  8. package/shared-prompts/_partials/update-task-file.md +52 -0
  9. package/shared-prompts/memories/automated-browser-tasks/INDEX.tpl.md +52 -0
  10. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/SKILL.tpl.md +102 -0
  11. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/examples/auth-failure-handling.mjs +81 -0
  12. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/examples/chained-workflow.mjs +126 -0
  13. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/examples/simple-fetch.mjs +92 -0
  14. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/architecture.md +61 -0
  15. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/auth-and-sessions.md +65 -0
  16. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/ctx-api.md +96 -0
  17. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/installation.md +104 -0
  18. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/script-conventions.md +243 -0
  19. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/chrome-state.mjs +148 -0
  20. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/debug.mjs +383 -0
  21. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/debug.spec.mjs +267 -0
  22. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/eslint.config.mjs +56 -0
  23. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/harness.mjs +169 -0
  24. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/keyring.mjs +59 -0
  25. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/logger.mjs +25 -0
  26. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/params.mjs +140 -0
  27. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/run.mjs +140 -0
  28. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/settings.tpl.mjs +1 -0
  29. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/utils.mjs +185 -0
  30. package/shared-prompts/skills/automated-browser-tasks/create-automated-browser-task/SKILL.tpl.md +52 -0
  31. package/shared-prompts/skills/automated-browser-tasks/running-automated-browser-tasks/SKILL.tpl.md +59 -0
  32. package/shared-prompts/skills/automated-browser-tasks/update-automated-browser-task/SKILL.tpl.md +47 -0
  33. package/shared-prompts/skills/control-flow/approve/SKILL.tpl.md +26 -0
  34. package/shared-prompts/skills/control-flow/opine/SKILL.tpl.md +58 -0
  35. package/shared-prompts/skills/control-flow/repeat/SKILL.tpl.md +27 -0
  36. package/shared-prompts/skills/control-flow/research/SKILL.tpl.md +34 -0
  37. package/shared-prompts/skills/sous-skills/about-agent-skills/SKILL.tpl.md +177 -0
  38. package/shared-prompts/skills/sous-skills/about-agent-skills/examples/about-something.md +45 -0
  39. package/shared-prompts/skills/sous-skills/about-agent-skills/examples/do-something.md +33 -0
  40. package/shared-prompts/skills/sous-skills/about-agent-skills/references/advanced-patterns.md +87 -0
  41. package/shared-prompts/skills/sous-skills/about-agent-skills/references/commands.md +46 -0
  42. package/shared-prompts/skills/sous-skills/about-agent-skills/references/frontmatter.md +25 -0
  43. package/shared-prompts/skills/sous-skills/about-agent-skills/references/substitutions.md +50 -0
  44. package/shared-prompts/skills/sous-skills/about-liquid-templates/SKILL.tpl.md +268 -0
  45. package/shared-prompts/skills/sous-skills/about-liquid-templates/references/liquid-filters.md +82 -0
  46. package/shared-prompts/skills/sous-skills/about-sous/SKILL.tpl.md +51 -0
  47. package/shared-prompts/skills/sous-skills/create-skill/SKILL.tpl.md +114 -0
  48. package/shared-prompts/skills/task-files/about-task-files/SKILL.tpl.md +122 -0
  49. package/shared-prompts/skills/task-files/continue-task-in-new-branch/SKILL.tpl.md +80 -0
  50. package/shared-prompts/skills/task-files/go/SKILL.tpl.md +14 -0
  51. package/shared-prompts/skills/task-files/resume-task/SKILL.tpl.md +13 -0
  52. package/shared-prompts/skills/task-files/start-task/SKILL.tpl.md +93 -0
  53. package/shared-prompts/skills/task-files/update/SKILL.tpl.md +14 -0
  54. package/shared-prompts/skills/task-files/update-task-file/SKILL.tpl.md +13 -0
  55. package/src/base-command.ts +163 -0
  56. package/src/commands/build.ts +196 -0
  57. package/src/commands/clear.ts +71 -0
  58. package/src/commands/compile.ts +95 -0
  59. package/src/commands/launch.ts +111 -0
  60. package/src/commands/prune.ts +48 -0
  61. package/src/lib/build-service.ts +258 -0
  62. package/src/lib/config-discovery.ts +199 -0
  63. package/src/lib/env-local.ts +195 -0
  64. package/src/lib/include-resolver.ts +146 -0
  65. package/src/lib/markdown-compiler.ts +580 -0
  66. package/src/lib/pid-service.ts +88 -0
  67. package/src/lib/settings.ts +695 -0
  68. package/src/lib/state.ts +135 -0
  69. package/src/lib/watch-service.ts +115 -0
  70. package/src/templating/filters/bullet-list.ts +9 -0
  71. package/src/templating/filters/index.ts +8 -0
  72. package/src/templating/init-liquid-engine.ts +82 -0
  73. package/src/templating/lib/glob-files.ts +74 -0
  74. package/src/templating/lib/import-export.ts +32 -0
  75. package/src/templating/lib/tag-args.ts +19 -0
  76. package/src/templating/tags/exportScalarVarsJs.ts +43 -0
  77. package/src/templating/tags/getFiles.ts +89 -0
  78. package/src/templating/tags/index.ts +14 -0
  79. package/src/templating/tags/listFiles.ts +54 -0
  80. package/src/templating/tags/showVars.ts +22 -0
  81. package/src/utils/formatting.ts +338 -0
  82. package/src/utils/prompts.ts +19 -0
@@ -0,0 +1,185 @@
1
+ /**
2
+ * ctx.utils — generic, site-agnostic helpers for automation scripts.
3
+ *
4
+ * These are the patterns proven during the POC, promoted out of any single
5
+ * script. Site-specific logic (dismissing a particular app's modals, parsing a
6
+ * particular tool's output) stays in the script as step functions.
7
+ *
8
+ * Built per-run and bound to the live `page`/`logger`, so scripts call them as
9
+ * `ctx.utils.foo(...)` without threading `page` through every call.
10
+ */
11
+
12
+ /**
13
+ * Build the utils object for a run.
14
+ *
15
+ * @param {import('playwright').Page} page
16
+ * @param {object} logger - The script's logger (a child is created per helper)
17
+ * @returns {object} the ctx.utils surface
18
+ */
19
+ export function createUtils(page, logger) {
20
+ const log = logger.child('utils');
21
+
22
+ return {
23
+ /**
24
+ * RECOMMENDED way to handle modals/banners that appear at an unpredictable
25
+ * time and would block later actions. Registers a Playwright locator handler:
26
+ * whenever `triggerLocator` is present and blocks an action, `dismiss` runs.
27
+ * This is fully timing-independent — no sleeps, no races. Prefer this over
28
+ * `dismissModals` for anything that may appear asynchronously.
29
+ *
30
+ * @param {import('playwright').Locator} triggerLocator - The modal/overlay.
31
+ * @param {(locator) => Promise<void>} dismiss - How to dismiss it.
32
+ * @returns {Promise<void>}
33
+ */
34
+ async autoDismiss(triggerLocator, dismiss) {
35
+ await page.addLocatorHandler(triggerLocator, dismiss);
36
+ log.info('registered auto-dismiss handler');
37
+ },
38
+
39
+ /**
40
+ * Best-effort one-shot dismissal of modals KNOWN to already be present. Clicks
41
+ * the first of each candidate selector that currently exists; failures are
42
+ * swallowed. Does NOT wait for modals that may appear later — use
43
+ * `autoDismiss` for those. No fixed delays.
44
+ *
45
+ * @param {string[]} selectors
46
+ * @param {object} [opts] - { timeout }
47
+ * @returns {Promise<number>} count of elements clicked
48
+ */
49
+ async dismissModals(selectors, opts = {}) {
50
+ const { timeout = 2000 } = opts;
51
+ let dismissed = 0;
52
+ for (const sel of selectors) {
53
+ const el = await page.$(sel);
54
+ if (!el) continue;
55
+ try {
56
+ await el.click({ timeout });
57
+ dismissed++;
58
+ } catch {
59
+ // best-effort; modal may have already closed or be non-actionable
60
+ }
61
+ }
62
+ if (dismissed) log.info(`dismissed ${dismissed} modal element(s)`);
63
+ return dismissed;
64
+ },
65
+
66
+ /**
67
+ * Click an element located by visible text (regex or string). Defaults to a
68
+ * NON-forced click so Playwright auto-waits for the element to be actionable
69
+ * (visible, stable, not covered) — the resilient default. Pass `force: true`
70
+ * only for the rare element a component library (e.g. Blueprint.js) wrongly
71
+ * reports as disabled, and verify the outcome afterward.
72
+ *
73
+ * @param {RegExp|string} text
74
+ * @param {object} [opts] - { force, timeout }
75
+ */
76
+ async clickByText(text, opts = {}) {
77
+ const { force = false, timeout = 15000 } = opts;
78
+ const locator = page.getByText(text).first();
79
+ await locator.waitFor({ timeout });
80
+ await locator.click({ force });
81
+ },
82
+
83
+ /**
84
+ * Wait for any element matching `text` (regex or string) to appear, without
85
+ * clicking. Useful for asserting a list/view has rendered.
86
+ *
87
+ * @param {RegExp|string} text
88
+ * @param {object} [opts] - { timeout }
89
+ */
90
+ async waitForText(text, opts = {}) {
91
+ const { timeout = 15000 } = opts;
92
+ await page.getByText(text).first().waitFor({ timeout });
93
+ },
94
+
95
+ /**
96
+ * Try each selector in order; return the longest text content found among
97
+ * all matches, or null if nothing exceeds `minLength`. Built for "find the
98
+ * log/output blob on the page" cases where the exact container is unknown.
99
+ *
100
+ * @param {string[]} selectors
101
+ * @param {object} [opts] - { minLength }
102
+ * @returns {Promise<string|null>}
103
+ */
104
+ async extractLongestText(selectors, opts = {}) {
105
+ const { minLength = 50 } = opts;
106
+ for (const sel of selectors) {
107
+ const els = await page.$$(sel);
108
+ if (!els.length) continue;
109
+ const texts = await Promise.all(els.map((el) => el.textContent()));
110
+ const longest = texts
111
+ .filter(Boolean)
112
+ .map((t) => t.trim())
113
+ .sort((a, b) => b.length - a.length)[0];
114
+ if (longest && longest.length >= minLength) return longest;
115
+ }
116
+ return null;
117
+ },
118
+
119
+ /**
120
+ * Extract the first match of a regex from page text (or supplied text).
121
+ * Returns the trimmed match string, or null.
122
+ *
123
+ * @param {RegExp} pattern
124
+ * @param {object} [opts] - { source: string, group: number }
125
+ * @returns {Promise<string|null>}
126
+ */
127
+ async extractTextByPattern(pattern, opts = {}) {
128
+ const { source = null, group = 0 } = opts;
129
+ const haystack = source ?? (await page.textContent('body')) ?? '';
130
+ const m = haystack.match(pattern);
131
+ return m ? m[group].trim() : null;
132
+ },
133
+
134
+ /**
135
+ * Capture a screenshot for debugging. No-op-safe: failures are logged, not
136
+ * thrown, so a debug aid never breaks a run.
137
+ *
138
+ * @param {string} path - Absolute file path for the PNG
139
+ * @param {object} [opts] - { fullPage }
140
+ */
141
+ async screenshot(path, opts = {}) {
142
+ const { fullPage = true } = opts;
143
+ try {
144
+ await page.screenshot({ path, fullPage });
145
+ log.info(`screenshot saved: ${path}`);
146
+ } catch (err) {
147
+ log.warn(`screenshot failed: ${err.message}`);
148
+ }
149
+ },
150
+
151
+ /**
152
+ * Scroll an element matching `selector` into view. Returns true if found.
153
+ *
154
+ * @param {string} selector
155
+ */
156
+ async scrollIntoView(selector) {
157
+ const el = await page.$(selector);
158
+ if (!el) return false;
159
+ await el.scrollIntoViewIfNeeded().catch(() => {});
160
+ return true;
161
+ },
162
+
163
+ /**
164
+ * Retry an async function until it succeeds or attempts are exhausted.
165
+ * Throws the last error on final failure.
166
+ *
167
+ * @param {Function} fn - async () => result
168
+ * @param {object} [opts] - { attempts, delay, label }
169
+ */
170
+ async retry(fn, opts = {}) {
171
+ const { attempts = 3, delay = 1000, label = 'operation' } = opts;
172
+ let lastErr;
173
+ for (let i = 1; i <= attempts; i++) {
174
+ try {
175
+ return await fn();
176
+ } catch (err) {
177
+ lastErr = err;
178
+ log.warn(`${label} failed (attempt ${i}/${attempts}): ${err.message}`);
179
+ if (i < attempts) await page.waitForTimeout(delay);
180
+ }
181
+ }
182
+ throw lastErr;
183
+ },
184
+ };
185
+ }
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: create-automated-browser-task
3
+ description: >
4
+ YOU MUST load this skill when you need to create a new headless browser
5
+ automation script — i.e. a browser task is required and no existing script
6
+ performs it. Produces a convention-compliant script in the project's
7
+ automation scripts directory.
8
+ ---
9
+
10
+ # Create an Automated Browser Task
11
+
12
+ A thin action skill. The architecture, `ctx` API, and full conventions live in
13
+ the parent topic skill; the agent performing this work MUST load
14
+ `about-automated-browser-tasks`.
15
+
16
+ ## Delegation
17
+
18
+ Per the sub-agent delegation pattern
19
+ (`~sous-shared/_partials/sub-agent-delegation.md`), writing and iterating on a script is
20
+ delegated work: one Opus sub-agent writes it, runs it, and iterates against the
21
+ real page until it works, then reports the script path and result. Give it the
22
+ target URL, the data to extract, and the params wanted.
23
+
24
+ ## Steps
25
+
26
+ 1. **Confirm none exists.** Search the project's automation scripts directory for
27
+ a script that already does this. If one is close, prefer
28
+ `update-automated-browser-task` instead.
29
+ 2. **Name the file** `verb-noun-qualifier.mjs` (e.g. `get-repo-ci-error.mjs`).
30
+ 3. **Declare `meta`** — `name`, a descriptive `description`, and `params`. For each
31
+ param set `required`, `default`, a genuinely descriptive `description`, and a
32
+ `validate` rule (RegExp or function) with an `invalidMessage`. Pull shared
33
+ values (URLs, resource IDs, profile) from `ctx.settings` rather than hardcoding.
34
+ 4. **Write `execute(ctx)`** as a thin orchestrator that calls small, named step
35
+ functions. Destructure off `ctx`/`params` at the top. Use `ctx.logger`, never
36
+ `console.log`. Use `ctx.utils` for generic patterns; keep site-specific logic
37
+ in step functions. Give EVERY function a full JSDoc block.
38
+ 5. **Return a result object** (`found`, `content`, `outputFile`, a URL, `message`).
39
+ 6. **Run it** to verify — see `running-automated-browser-tasks`. Iterate on the
40
+ real page; do not guess selectors.
41
+
42
+ ## Reference
43
+
44
+ The exact param spec, `ctx.utils` surface, return shape, and worked examples are
45
+ in the topic skill's references and `examples/`. Read them — do not improvise.
46
+
47
+ ## Source for this Skill
48
+
49
+ This skill was pulled from the `sous` project's "shared skills" library. It was compiled from a template and
50
+ the output file should not be edited directly.
51
+
52
+ - Source Path: {{ sousTemplatePath }}
@@ -0,0 +1,59 @@
1
+ ---
2
+ name: running-automated-browser-tasks
3
+ description: >
4
+ YOU MUST load this skill when you need to run an existing headless browser
5
+ automation script for the user — to execute a task, fetch data from a site, or
6
+ verify a script you just wrote or changed.
7
+ ---
8
+
9
+ # Run an Automated Browser Task
10
+
11
+ A thin action skill. The agent performing this work MUST load
12
+ `about-automated-browser-tasks` for the architecture and the meaning of `ctx`,
13
+ auth handling, and result shapes.
14
+
15
+ ## Delegation
16
+
17
+ Per the sub-agent delegation pattern
18
+ (`~sous-shared/_partials/sub-agent-delegation.md`), a browser run is a slow, multi-step
19
+ execution: delegate it to a background sub-agent, which runs the command,
20
+ interprets the outcome below, and reports the result plus any link or actionable
21
+ message. Run a one-off script inline only when its result blocks the very next
22
+ step.
23
+
24
+ ## Invocation
25
+
26
+ Run a script by its absolute path through the runner in this system's `scripts/`
27
+ directory:
28
+
29
+ ```bash
30
+ node <scriptsDir>/run.mjs <absolute-path-to-script.mjs> [--param=value ...]
31
+ ```
32
+
33
+ - Pass script params as `--paramName=value`.
34
+ - Harness options: `--profileName=<name>` (Chrome profile), `--timeout=<ms>`.
35
+ - The runner loads compiled project `settings.mjs` automatically and prints the
36
+ resolved params (marking which came from defaults/settings) before running.
37
+
38
+ ## Reading the outcome
39
+
40
+ - **Success** → `✓` and the result is printed; if the script returned an
41
+ `outputFile` + `content`, the runner writes the file and reports the path.
42
+ - **`error: params`** → a required param was missing or failed validation. Fix the
43
+ invocation; do not edit the script to bypass validation.
44
+ - **`error: auth`** → the session was redirected to a login page. The user must log
45
+ in to the site in their Chrome profile, then the SAME command is re-run; no
46
+ script change needed. A sub-agent cannot ask for this: return the actionable
47
+ message and the link to the orchestrator, which relays them to the user and
48
+ re-dispatches the run afterward.
49
+ - **`error: script`** → an unexpected failure with a stack. Inspect, then use
50
+ `update-automated-browser-task` to fix the root cause and re-run.
51
+
52
+ Never silently swallow a failure or fake a result. Report what happened.
53
+
54
+ ## Source for this Skill
55
+
56
+ This skill was pulled from the `sous` project's "shared skills" library. It was compiled from a template and
57
+ the output file should not be edited directly.
58
+
59
+ - Source Path: {{ sousTemplatePath }}
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: update-automated-browser-task
3
+ description: >
4
+ YOU MUST load this skill when you need to modify, fix, or extend an existing
5
+ headless browser automation script — for example when a script breaks because
6
+ a site's markup changed, or a new param/behavior is needed.
7
+ ---
8
+
9
+ # Update an Automated Browser Task
10
+
11
+ A thin action skill. The agent performing this work MUST load
12
+ `about-automated-browser-tasks` for the architecture, `ctx` API, and full
13
+ conventions.
14
+
15
+ ## Delegation
16
+
17
+ Per the sub-agent delegation pattern
18
+ (`~sous-shared/_partials/sub-agent-delegation.md`), the fix-and-re-run loop below
19
+ is delegated to one Opus sub-agent, which reports what broke, what it changed, and the verified
20
+ result. Give it the script path and the failing run output.
21
+
22
+ ## Steps
23
+
24
+ 1. **Read the script** and the run output. Identify the failing step from the
25
+ logger prefixes (`[script:section]`) in the output.
26
+ 2. **Reproduce** by running it (see `running-automated-browser-tasks`). For
27
+ selector/markup failures, inspect the live page — use `ctx.utils.screenshot`
28
+ or widen selectors; do not guess.
29
+ 3. **Make the smallest correct change.** Fix the root cause, not the symptom. Keep
30
+ the existing decomposition: edit the relevant step function, add a new one if a
31
+ new discrete action is needed.
32
+ 4. **Preserve conventions.** Maintain JSDoc blocks, `ctx`/`params` destructuring,
33
+ `ctx.logger` usage, and `meta.params` validation. If you add a param, give it a
34
+ description and a `validate` rule.
35
+ 5. **Re-run to verify** the fix end-to-end.
36
+
37
+ ## When NOT to update
38
+
39
+ If the change amounts to a different task, create a new script instead
40
+ (`create-automated-browser-task`). Keep each script focused on one job.
41
+
42
+ ## Source for this Skill
43
+
44
+ This skill was pulled from the `sous` project's "shared skills" library. It was compiled from a template and
45
+ the output file should not be edited directly.
46
+
47
+ - Source Path: {{ sousTemplatePath }}
@@ -0,0 +1,26 @@
1
+ ---
2
+ name: approve
3
+ description: Approve the current plan and instruct Claude to proceed with maximum parallelism.
4
+ disable-model-invocation: true
5
+ ---
6
+
7
+ Your plan looks good, and I approve.
8
+
9
+ While executing the plan, maximize parallelism:
10
+ - Delegate the steps that have any complexity to background sub-agents, per the sub-agent
11
+ delegation pattern (`~sous-shared/_partials/sub-agent-delegation.md`), batching independent
12
+ dispatches into one message.
13
+ - Batch independent investigations (searches, file reads, greps, listings) into concurrent tool
14
+ calls whenever practical.
15
+ - Keep dependent steps sequential (especially edits, formatting/linting, and tests that rely on
16
+ prior changes).
17
+
18
+ Use the best-fit tools for the job. If you can't parallelize a step, say why briefly and proceed
19
+ sequentially.
20
+
21
+ ## Source for this Skill
22
+
23
+ This skill was pulled from the `sous` project's "shared skills" library. It was compiled from a
24
+ template and the output file should not be edited directly.
25
+
26
+ - Source Path: {{ sousTemplatePath }}
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: opine
3
+ description: >
4
+ Used to send an idea or proposal to the agent and have it repeat it back, then offer an honest
5
+ analysis of viability, practicality, and overall merit. This is a discussion; no action is taken.
6
+ argument-hint: idea or proposal
7
+ disable-model-invocation: true
8
+ ---
9
+
10
+ New Idea/Proposal:
11
+ $ARGUMENTS
12
+
13
+ -
14
+
15
+ ## CRITICAL: DO NOT ACT ON THIS IDEA
16
+
17
+ This is a discussion, not a request. You must NOT take any action: do not write code, do not edit
18
+ files, do not create branches, do not modify anything. The user is thinking out loud and wants
19
+ your opinion. Your only output is text directed at the user.
20
+
21
+ ## Research
22
+
23
+ You may research the codebase and/or the web before responding if you think it would improve the
24
+ accuracy of your analysis. Most ideas won't need this; use your judgement. When you do research,
25
+ prefer sub-agents and run them in parallel where practical.
26
+
27
+ ## Step 1: Repeat
28
+
29
+ Repeat the idea or proposal back to me, in your own words and in a well-structured format so
30
+ that I know our understandings are aligned.
31
+
32
+ ## Step 2: Analyze
33
+
34
+ After repeating the idea back, offer your analysis in three parts:
35
+
36
+ 1. **Viability**: Is this idea technically feasible? Are there any fundamental blockers or
37
+ constraints that would prevent it from working?
38
+
39
+ 2. **Practicality**: Even if viable, is it practical? Would it require more steps, complexity,
40
+ or hacky code than I'm probably anticipating? Are there hidden costs (maintenance burden,
41
+ performance implications, edge cases)?
42
+
43
+ 3. **Opinion**: Is this a good idea? Give your honest take on whether this is the right approach.
44
+
45
+ ## Guidelines
46
+
47
+ - **No action.** This cannot be overstated. Do not act on the idea. Only discuss it.
48
+ - Be open and honest. Push back when you genuinely see problems.
49
+ - "Yes, that seems like a great idea" is an entirely valid response. Do not manufacture
50
+ objections or play devil's advocate just for the sake of it. If the idea is sound, say so.
51
+ If it has real problems, say that too.
52
+
53
+ ## Source for this Skill
54
+
55
+ This skill was pulled from the `sous` project's "shared skills" library. It was compiled from a
56
+ template and the output file should not be edited directly.
57
+
58
+ - Source Path: {{ sousTemplatePath }}
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: repeat
3
+ description: >
4
+ Used to send an instruction to the agent and have the agent repeat the instruction back to you
5
+ before acting, to ensure that you and the agent are aligned.
6
+ argument-hint: instruction
7
+ disable-model-invocation: true
8
+ ---
9
+
10
+ New Instruction:
11
+ $ARGUMENTS
12
+
13
+ -
14
+
15
+ DO NOT ACT, yet. Instead, I want you to repeat the instruction back to me, in your own words and
16
+ in a well-structured format so that I know our understandings are aligned. If I am satisfied with
17
+ your explanation, I will approve you to begin acting.
18
+
19
+ You may do a small amount of research before repeating the instruction back to me, if you think
20
+ it would allow you to be more precise or accurate in your explanation.
21
+
22
+ ## Source for this Skill
23
+
24
+ This skill was pulled from the `sous` project's "shared skills" library. It was compiled from a
25
+ template and the output file should not be edited directly.
26
+
27
+ - Source Path: {{ sousTemplatePath }}
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: research
3
+ description: Run a research task using background sub-agents
4
+ user-invocable-only: true
5
+ arguments-hint: what to research via background subagents
6
+ ---
7
+
8
+ Have a background sub-agent do the following:
9
+ $ARGUMENTS
10
+
11
+ ## Prefer Parallelism
12
+
13
+ If possible, practical, and reasonable, break the task into multiple parts and assign each part to a sub-agent.
14
+ Running background sub-agents in parallel usually makes things go much faster. Don't break tiny tasks up, though.
15
+
16
+ Batch the independent dispatches into one message so they run at once. Opus by default; Sonnet only
17
+ for rote extraction.
18
+
19
+ ## Sub-Agent Prompts
20
+
21
+ Per the sub-agent delegation pattern (`~sous-shared/_partials/sub-agent-delegation.md`), each prompt
22
+ must be self-contained: the question to answer, the
23
+ paths/IDs/facts needed, which skills to load, and the shape of the answer wanted. Sub-agents start
24
+ fresh and cannot see this conversation.
25
+
26
+ Each returns a concise summary, not a file dump. Do not fabricate or predict a pending result; wait
27
+ for the notification. Synthesis and reporting to the user are orchestrator-only.
28
+
29
+ ## Source for this Skill
30
+
31
+ This skill was pulled from the `sous` project's "shared skills" library. It was compiled from a
32
+ template and the output file should not be edited directly.
33
+
34
+ - Source Path: {{ sousTemplatePath }}
@@ -0,0 +1,177 @@
1
+ ---
2
+ name: about-agent-skills
3
+ description: >
4
+ YOU MUST load this skill when creating, editing, auditing, or reasoning about any
5
+ skill. Covers skill structure, frontmatter fields, invocation, topic vs action
6
+ patterns, naming conventions, and general principles.
7
+ user-invocable: false
8
+ ---
9
+
10
+ # About Agent Skills
11
+
12
+ A skill is a directory containing a `SKILL.md` file and optional supporting files.
13
+ Skills extend what a coding agent can do — invoke them directly with `/skill-name`,
14
+ or they load automatically when the agent's decision logic matches the `description`.
15
+
16
+ ## Where Skills Live
17
+
18
+ Skills for this project live at `{{ skillsRoot }}`. Create and edit skills there —
19
+ never in `.claude/skills/` or `.codex/skills/` directly. See `create-skill` for
20
+ step-by-step instructions.
21
+
22
+ ## Directory Structure
23
+
24
+ ```
25
+ my-skill/
26
+ ├── SKILL.md # Required. Frontmatter + instructions.
27
+ ├── references/ # Optional. Deep-dive docs loaded when needed.
28
+ ├── examples/ # Optional. Example outputs.
29
+ └── scripts/ # Optional. Executable scripts.
30
+ ```
31
+
32
+ Supporting files must be referenced from `SKILL.md` — the agent will not know they
33
+ exist otherwise. Keep `SKILL.md` under ~500 lines; move detailed reference material
34
+ to `references/` files.
35
+
36
+ ## Core Frontmatter
37
+
38
+ ```yaml
39
+ ---
40
+ name: my-skill
41
+ description: >
42
+ One or two sentences describing when the agent should invoke this skill.
43
+ Under 500 characters. Write as a trigger condition, not a title.
44
+ disable-model-invocation: true
45
+ user-invocable: false
46
+ ---
47
+ ```
48
+
49
+ **`name`** — becomes the `/slash-command`. Defaults to the directory name if omitted.
50
+
51
+ **`description`** — tells the agent when to invoke this skill. Use strong trigger
52
+ language: open with "YOU MUST load this skill when...". Under 500 chars.
53
+
54
+ **`disable-model-invocation`** — set `true` to prevent the agent from invoking the
55
+ skill automatically. Use this for command skills that represent intentional,
56
+ user-initiated actions (e.g. `/commit`, `/deploy`). If it makes sense for the agent
57
+ to invoke the skill on the user's behalf, omit it.
58
+
59
+ **`user-invocable`** — set `false` to hide the skill from the `/` menu. Use this on
60
+ all topic skills (`about-*`). They are reference material the agent loads
61
+ automatically, not commands for the user to invoke.
62
+
63
+ For all frontmatter fields, see [references/frontmatter.md](references/frontmatter.md).
64
+
65
+ ## Topic vs Action Skills
66
+
67
+ **Topic skills** hold reference material and background context for a concept, plus any
68
+ shared scripts the action skills draw from. They are moderately descriptive and reusable
69
+ across many workflows. Always set `user-invocable: false`. Use the `about-*` prefix when
70
+ the skill's primary purpose is background understanding.
71
+
72
+ A topic skill's body holds fundamental knowledge — what is needed in ~75%+ of use cases.
73
+ Deeper reference material (complete tables, edge cases, advanced patterns) goes in
74
+ `references/` files, loaded only when needed. When official documentation exists for the
75
+ topic, fetch it once and store distilled versions in `references/`, including the official
76
+ source URL so the agent can check anything not covered locally. This prevents repeated doc
77
+ fetches during work sessions.
78
+
79
+ **Action skills** perform a specific operation and are as thin as possible — they
80
+ contain only what is exclusive to that action. All shared knowledge belongs in the
81
+ parent topic skill. Action skills carry less cold-start context than topic skills: just
82
+ enough to not be opaque, then delegate depth upward with `YOU MUST load`. Name action
83
+ skills with a verb prefix: `create-`, `deploy-`, `run-`. If the skill operates on a
84
+ specific type, include it after the verb (e.g. `create-skill` operates on a "skill").
85
+ The verb-first pattern immediately distinguishes action skills from topic skills in any
86
+ skill listing.
87
+
88
+ Non-command action skills must NOT have `disable-model-invocation: true` — that flag
89
+ removes the skill from the agent's context entirely, making it undiscoverable. A
90
+ non-command action skill relies on its description to tell the agent when to invoke it
91
+ automatically; omitting the flag is what makes that possible.
92
+
93
+ ## Template Files (`.tpl.`)
94
+
95
+ Any file in a skill directory can use `.tpl.` naming to opt into LiquidJS processing
96
+ at compile time. The `.tpl.` segment is stripped from the output filename.
97
+ For when `SKILL.md` must be `SKILL.tpl.md`, see **Template-Compiled Skills** below.
98
+
99
+ YOU MUST load `about-liquid-templates` when deciding whether any file in a skill
100
+ directory needs `.tpl.` naming or when writing LiquidJS syntax.
101
+
102
+ ## General Principles
103
+
104
+ **Knowledge lives at the highest common ancestor.** If two skills need the same
105
+ knowledge, it belongs in the most general topic skill covering both — never
106
+ duplicated across skills. Before adding content anywhere, ask whether it belongs
107
+ higher up.
108
+
109
+ **Every skill provides minimal cold-start context.** Assume the agent knows nothing
110
+ about the concept until the skill is loaded, and will not load any other skill unless
111
+ explicitly told to. Include the briefest possible orientation, then point to deeper
112
+ resources.
113
+
114
+ **Never duplicate information that changes over time.** Do not create lists or tables
115
+ that inventory things which will evolve (e.g. available skills, current files in a
116
+ directory). Teach the agent where to look rather than providing a snapshot that will go
117
+ stale. Only document things stable by nature.
118
+
119
+ **Use strong trigger language.** Descriptions must open with `YOU MUST load this
120
+ skill when...`. Cross-references to other skills must use `YOU MUST load` — weak
121
+ language like "consult" or "see" is not sufficient. In a skill body, write the
122
+ requirement so it binds whichever agent executes ("The agent performing this work MUST
123
+ load `x`"), not just the main session: delegated sub-agents start with fresh context and
124
+ must load the skills themselves.
125
+
126
+ **Write steps for whoever executes them.** Do not assume the main session performs
127
+ a skill's steps inline. Say which steps are delegated to a sub-agent and which are
128
+ orchestrator-only (anything needing the user, or the chat conversation's own
129
+ contents). Never rely on "skip this if it is already in context" heuristics: a
130
+ sub-agent's context is always fresh. Steps that produce a link or question for the
131
+ user must return it to the orchestrator, which relays it.
132
+
133
+ **If no action skill exists for a task, ask the user.** Do not improvise an action
134
+ that warrants its own skill.
135
+
136
+ ## Template-Compiled Skills
137
+
138
+ Every skill distributed from a shared library — whether this library (`sous`) or any other
139
+ shared skill library — must use `SKILL.tpl.md`, not `SKILL.md`. This is required because
140
+ every distributed skill must end with a `## Source for this Skill` section (see below), and
141
+ that section uses a template variable for the source path, which requires LiquidJS rendering.
142
+ No exceptions.
143
+
144
+ Every such skill's `SKILL.md` must end with a `## Source for this Skill` section:
145
+
146
+ ```
147
+ ## Source for this Skill
148
+
149
+ This skill was pulled from the `sous` project's "shared skills" library. It was compiled from a template and
150
+ the output file should not be edited directly.
151
+
152
+ - Source Path: <resolved source path>
153
+ ```
154
+
155
+ This tells agents reading the compiled output where the skill originated and that the
156
+ file must not be edited directly. Because this footer is required, all shared skills must
157
+ use `SKILL.tpl.md` (not `SKILL.md`) so the source path variable can be rendered at
158
+ compile time.
159
+
160
+ ## Examples
161
+
162
+ - [examples/about-something.md](examples/about-something.md) — a complete example of a topic (`about-*`) skill
163
+ - [examples/do-something.md](examples/do-something.md) — a complete example of an action skill (command)
164
+
165
+ ## Reference Files
166
+
167
+ - [frontmatter.md](references/frontmatter.md) — complete frontmatter field table and invocation matrix
168
+ - [substitutions.md](references/substitutions.md) — `$ARGUMENTS`, `$ARGUMENTS[N]`, `$CLAUDE_SESSION_ID`, `$CLAUDE_SKILL_DIR`
169
+ - [commands.md](references/commands.md) — command-specific conventions: descriptions, headings, arguments, `argument-hint`
170
+ - [advanced-patterns.md](references/advanced-patterns.md) — dynamic context injection, subagent execution (`context: fork`), `allowed-tools`
171
+
172
+ ## Source for this Skill
173
+
174
+ This skill was pulled from the `sous` project's "shared skills" library. It was compiled from a template and
175
+ the output file should not be edited directly.
176
+
177
+ - Source Path: {{ sousTemplatePath }}