@holt-os/holt 0.10.0 → 0.11.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/README.md +16 -1
- package/dist/cli.js +33 -18
- package/package.json +2 -1
- package/skills/action-items/SKILL.md +31 -0
- package/skills/brief/SKILL.md +25 -0
- package/skills/code-review/SKILL.md +24 -0
- package/skills/commit/SKILL.md +26 -0
- package/skills/decide/SKILL.md +28 -0
- package/skills/explain/SKILL.md +24 -0
- package/skills/explain-code/SKILL.md +27 -0
- package/skills/plan/SKILL.md +29 -0
- package/skills/rewrite/SKILL.md +27 -0
- package/skills/summarize/SKILL.md +27 -0
package/README.md
CHANGED
|
@@ -206,7 +206,7 @@ Wiki pages also participate in recall: each page is embedded and indexed like a
|
|
|
206
206
|
|
|
207
207
|
A skill is a folder with a `SKILL.md`: YAML frontmatter (`name`, `description`) plus Markdown instructions. Same convention as agentskills.io and Claude Code, so skills are portable both ways. Skills are prompt text only; Holt never executes their contents.
|
|
208
208
|
|
|
209
|
-
Holt looks in
|
|
209
|
+
Holt looks in three places, in precedence order (workspace shadows global shadows builtin on a name clash): `./.holt/skills/` for this folder, `~/.holt/skills/` for every folder (`--global`), and a read-only set of **built-in skills** that ship inside Holt and are available in every folder out of the box.
|
|
210
210
|
|
|
211
211
|
```
|
|
212
212
|
holt skill list list installed skills
|
|
@@ -220,6 +220,21 @@ holt skill remove <name> delete a skill
|
|
|
220
220
|
|
|
221
221
|
In chat, run one with `/skill <name> [your input]`. Available skills are also listed to the brain each turn, so it knows what it can be asked to follow.
|
|
222
222
|
|
|
223
|
+
### Built-in skills
|
|
224
|
+
|
|
225
|
+
Holt ships with a small, curated set of general-purpose skills, available in every folder with no setup. They are read-only (`holt skill remove` will not delete them); to change one, create a workspace or global skill with the same name and it takes over.
|
|
226
|
+
|
|
227
|
+
- **summarize**: condense a document, article, transcript, or pasted text into its key points.
|
|
228
|
+
- **explain**: explain a concept, error message, or piece of jargon in plain language.
|
|
229
|
+
- **action-items**: pull decisions, tasks, and owners out of messy notes or a meeting transcript.
|
|
230
|
+
- **brief**: a short briefing on the state of the current folder, using recalled memory plus your input.
|
|
231
|
+
- **code-review**: review a file or a diff for correctness bugs, edge cases, and simplifications.
|
|
232
|
+
- **explain-code**: walk through what a file or function does and how it fits into the wider system.
|
|
233
|
+
- **commit**: draft a clear commit message from staged changes or a described change.
|
|
234
|
+
- **plan**: break a goal into a concrete, ordered set of steps.
|
|
235
|
+
- **rewrite**: tighten and clarify a piece of text without changing its meaning.
|
|
236
|
+
- **decide**: weigh a decision and give a clear recommendation.
|
|
237
|
+
|
|
223
238
|
### Skill registry (`holt skill search` / `publish`)
|
|
224
239
|
|
|
225
240
|
Beyond pasting URLs, Holt can discover and share skills through a **git-based registry**: a single JSON index living in a git repo. No server, no infra, in keeping with the rest of Holt.
|
package/dist/cli.js
CHANGED
|
@@ -1032,9 +1032,15 @@ async function runApiBrain(brain, prompt, onChunk) {
|
|
|
1032
1032
|
|
|
1033
1033
|
// src/skills.ts
|
|
1034
1034
|
import { readFileSync as readFileSync6, readdirSync, existsSync as existsSync6, statSync as statSync2 } from "fs";
|
|
1035
|
-
import { join as join6 } from "path";
|
|
1035
|
+
import { join as join6, dirname as dirname2 } from "path";
|
|
1036
|
+
import { fileURLToPath } from "url";
|
|
1037
|
+
function builtinSkillsRoot() {
|
|
1038
|
+
return join6(dirname2(fileURLToPath(import.meta.url)), "..", "skills");
|
|
1039
|
+
}
|
|
1036
1040
|
function skillsRoot(scope) {
|
|
1037
|
-
|
|
1041
|
+
if (scope === "workspace") return join6(wsHoltDir(), "skills");
|
|
1042
|
+
if (scope === "builtin") return builtinSkillsRoot();
|
|
1043
|
+
return join6(GLOBAL_DIR, "skills");
|
|
1038
1044
|
}
|
|
1039
1045
|
function sanitizeName(name) {
|
|
1040
1046
|
return (name || "").trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").replace(/-{2,}/g, "-");
|
|
@@ -1114,6 +1120,7 @@ function listScope(scope) {
|
|
|
1114
1120
|
}
|
|
1115
1121
|
function listSkills() {
|
|
1116
1122
|
const byName = /* @__PURE__ */ new Map();
|
|
1123
|
+
for (const s of listScope("builtin")) byName.set(s.name, s);
|
|
1117
1124
|
for (const s of listScope("global")) byName.set(s.name, s);
|
|
1118
1125
|
for (const s of listScope("workspace")) byName.set(s.name, s);
|
|
1119
1126
|
return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -3702,7 +3709,7 @@ import { spawnSync as spawnSync2 } from "child_process";
|
|
|
3702
3709
|
// src/registry.ts
|
|
3703
3710
|
import { readFileSync as readFileSync12, writeFileSync as writeFileSync9, existsSync as existsSync11, mkdirSync as mkdirSync8, statSync as statSync4 } from "fs";
|
|
3704
3711
|
import { join as join11, isAbsolute as isAbsolute2, resolve as resolve2 } from "path";
|
|
3705
|
-
import { pathToFileURL, fileURLToPath } from "url";
|
|
3712
|
+
import { pathToFileURL, fileURLToPath as fileURLToPath2 } from "url";
|
|
3706
3713
|
var DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/holt-os/registry/main/registry.json";
|
|
3707
3714
|
var REGISTRY_REPO_URL = "https://github.com/holt-os/registry";
|
|
3708
3715
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
@@ -3767,7 +3774,7 @@ function writeCache(url, registry) {
|
|
|
3767
3774
|
function localPathFor(loc) {
|
|
3768
3775
|
if (loc.startsWith("file://")) {
|
|
3769
3776
|
try {
|
|
3770
|
-
return
|
|
3777
|
+
return fileURLToPath2(loc);
|
|
3771
3778
|
} catch {
|
|
3772
3779
|
return null;
|
|
3773
3780
|
}
|
|
@@ -3921,14 +3928,15 @@ function cmdList() {
|
|
|
3921
3928
|
}
|
|
3922
3929
|
const nameW = Math.max(4, ...skills.map((s) => s.name.length));
|
|
3923
3930
|
const scopeW = Math.max(5, ...skills.map((s) => s.scope.length));
|
|
3924
|
-
console.log("\n" + c.accent("Skills") + c.dim(" (workspace shadows global on name clash)"));
|
|
3931
|
+
console.log("\n" + c.accent("Skills") + c.dim(" (workspace shadows global shadows builtin on name clash)"));
|
|
3925
3932
|
console.log(
|
|
3926
3933
|
" " + c.dim("name".padEnd(nameW)) + " " + c.dim("scope".padEnd(scopeW)) + " " + c.dim("description")
|
|
3927
3934
|
);
|
|
3928
3935
|
for (const s of skills) {
|
|
3929
3936
|
const desc = s.description.length > 68 ? s.description.slice(0, 67) + "\u2026" : s.description;
|
|
3937
|
+
const scopeCol = s.scope === "workspace" ? c.cyan(s.scope.padEnd(scopeW)) : s.scope === "builtin" ? c.accent(s.scope.padEnd(scopeW)) : c.dim(s.scope.padEnd(scopeW));
|
|
3930
3938
|
console.log(
|
|
3931
|
-
" " + c.bold(s.name.padEnd(nameW)) + " " +
|
|
3939
|
+
" " + c.bold(s.name.padEnd(nameW)) + " " + scopeCol + " " + (desc || c.dim("(no description)"))
|
|
3932
3940
|
);
|
|
3933
3941
|
}
|
|
3934
3942
|
console.log(c.dim("\n holt skill show <name> print a skill"));
|
|
@@ -4181,6 +4189,13 @@ async function cmdRemove(name, ask) {
|
|
|
4181
4189
|
const globalDir = join12(skillsRoot("global"), clean);
|
|
4182
4190
|
const target = existsSync12(wsDir) ? wsDir : existsSync12(globalDir) ? globalDir : "";
|
|
4183
4191
|
if (!target) {
|
|
4192
|
+
if (existsSync12(join12(skillsRoot("builtin"), clean))) {
|
|
4193
|
+
console.error(c.red(`
|
|
4194
|
+
"${clean}" is a built-in skill and cannot be removed; it ships inside Holt.`));
|
|
4195
|
+
console.error(c.dim(" Override it instead: create a workspace or global skill with the same name.\n"));
|
|
4196
|
+
process.exitCode = 1;
|
|
4197
|
+
return;
|
|
4198
|
+
}
|
|
4184
4199
|
console.error(c.dim(`
|
|
4185
4200
|
No skill named "${clean}" found.
|
|
4186
4201
|
`));
|
|
@@ -4248,7 +4263,7 @@ async function skillCmd(sub, rest = []) {
|
|
|
4248
4263
|
|
|
4249
4264
|
// src/commands/graph.ts
|
|
4250
4265
|
import { writeFileSync as writeFileSync11, mkdirSync as mkdirSync10, existsSync as existsSync13 } from "fs";
|
|
4251
|
-
import { join as join14, dirname as
|
|
4266
|
+
import { join as join14, dirname as dirname4, resolve as resolve4 } from "path";
|
|
4252
4267
|
import { spawn as spawn4 } from "child_process";
|
|
4253
4268
|
|
|
4254
4269
|
// src/communities.ts
|
|
@@ -5046,7 +5061,7 @@ function renderGraphHtml(graph2, meta) {
|
|
|
5046
5061
|
|
|
5047
5062
|
// src/ingest.ts
|
|
5048
5063
|
import { readdirSync as readdirSync4, readFileSync as readFileSync14, statSync as statSync6 } from "fs";
|
|
5049
|
-
import { join as join13, relative, sep, extname, dirname as
|
|
5064
|
+
import { join as join13, relative, sep, extname, dirname as dirname3, basename as basename2 } from "path";
|
|
5050
5065
|
var CODE_EXT = /* @__PURE__ */ new Set([
|
|
5051
5066
|
"js",
|
|
5052
5067
|
"jsx",
|
|
@@ -5286,7 +5301,7 @@ function resolvePySpec(f, spec, byId) {
|
|
|
5286
5301
|
return null;
|
|
5287
5302
|
}
|
|
5288
5303
|
function toPosixDir(id) {
|
|
5289
|
-
const d = toPosix(
|
|
5304
|
+
const d = toPosix(dirname3(id));
|
|
5290
5305
|
return d === "" || d === "." ? "." : d;
|
|
5291
5306
|
}
|
|
5292
5307
|
var MD_LINK_RE = /\[[^\]]*\]\(([^)\s]+)(?:\s+["'][^"']*["'])?\)/g;
|
|
@@ -5489,7 +5504,7 @@ async function graph(args = []) {
|
|
|
5489
5504
|
if (opts.report) {
|
|
5490
5505
|
const md = renderReport(g, { workspace: workspace() });
|
|
5491
5506
|
const reportPath = opts.out ? resolve4(opts.out) : join14(workspace(), "GRAPH_REPORT.md");
|
|
5492
|
-
mkdirSync10(
|
|
5507
|
+
mkdirSync10(dirname4(reportPath), { recursive: true });
|
|
5493
5508
|
writeFileSync11(reportPath, md, "utf8");
|
|
5494
5509
|
const communities = new Set(g.nodes.map((n) => n.community ?? "0")).size;
|
|
5495
5510
|
console.log("\n" + c.accent("Graph report written") + c.dim(" (this folder)"));
|
|
@@ -5511,7 +5526,7 @@ async function graph(args = []) {
|
|
|
5511
5526
|
edges: g.edges.length
|
|
5512
5527
|
});
|
|
5513
5528
|
const outPath = opts.out ? resolve4(opts.out) : join14(wsHoltDir(), "graph.html");
|
|
5514
|
-
mkdirSync10(
|
|
5529
|
+
mkdirSync10(dirname4(outPath), { recursive: true });
|
|
5515
5530
|
writeFileSync11(outPath, html, "utf8");
|
|
5516
5531
|
console.log("\n" + c.accent("Memory graph built") + c.dim(" (this folder)"));
|
|
5517
5532
|
const parts = [`${turns.length} turns`, `${conceptCount} concepts`];
|
|
@@ -5800,7 +5815,7 @@ function holtTools() {
|
|
|
5800
5815
|
}
|
|
5801
5816
|
|
|
5802
5817
|
// src/version.ts
|
|
5803
|
-
var VERSION = "0.
|
|
5818
|
+
var VERSION = "0.11.0";
|
|
5804
5819
|
|
|
5805
5820
|
// src/commands/mcp.ts
|
|
5806
5821
|
function printSetup() {
|
|
@@ -5847,7 +5862,7 @@ async function mcp(sub, rest = []) {
|
|
|
5847
5862
|
|
|
5848
5863
|
// src/commands/hook.ts
|
|
5849
5864
|
import { readFileSync as readFileSync15, writeFileSync as writeFileSync12, existsSync as existsSync14, mkdirSync as mkdirSync11, copyFileSync, realpathSync as realpathSync2 } from "fs";
|
|
5850
|
-
import { join as join15, dirname as
|
|
5865
|
+
import { join as join15, dirname as dirname5 } from "path";
|
|
5851
5866
|
import { homedir as homedir3 } from "os";
|
|
5852
5867
|
var EVENT = {
|
|
5853
5868
|
inject: "UserPromptSubmit",
|
|
@@ -5873,7 +5888,7 @@ function readSettings(path) {
|
|
|
5873
5888
|
}
|
|
5874
5889
|
}
|
|
5875
5890
|
function writeSettings(path, settings) {
|
|
5876
|
-
mkdirSync11(
|
|
5891
|
+
mkdirSync11(dirname5(path), { recursive: true });
|
|
5877
5892
|
writeFileSync12(path, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
5878
5893
|
}
|
|
5879
5894
|
function backup(path) {
|
|
@@ -6319,7 +6334,7 @@ async function run(args) {
|
|
|
6319
6334
|
// src/commands/schedule.ts
|
|
6320
6335
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
6321
6336
|
import { writeFileSync as writeFileSync15, mkdirSync as mkdirSync13, rmSync as rmSync6, existsSync as existsSync15 } from "fs";
|
|
6322
|
-
import { dirname as
|
|
6337
|
+
import { dirname as dirname6 } from "path";
|
|
6323
6338
|
|
|
6324
6339
|
// src/scheduler.ts
|
|
6325
6340
|
import { homedir as homedir4 } from "os";
|
|
@@ -6483,7 +6498,7 @@ function parseAdd(rest) {
|
|
|
6483
6498
|
}
|
|
6484
6499
|
function installDarwin(job, holtPath) {
|
|
6485
6500
|
const path = plistPath(job.id);
|
|
6486
|
-
mkdirSync13(
|
|
6501
|
+
mkdirSync13(dirname6(path), { recursive: true });
|
|
6487
6502
|
writeFileSync15(path, buildLaunchdPlist(job, holtPath), "utf8");
|
|
6488
6503
|
const res = spawnSync4("launchctl", ["load", "-w", path], { encoding: "utf8" });
|
|
6489
6504
|
if (res.status === 0) {
|
|
@@ -6636,7 +6651,7 @@ async function schedule(sub, rest = []) {
|
|
|
6636
6651
|
// src/commands/routine.ts
|
|
6637
6652
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
6638
6653
|
import { writeFileSync as writeFileSync17, mkdirSync as mkdirSync15, rmSync as rmSync7, existsSync as existsSync16 } from "fs";
|
|
6639
|
-
import { dirname as
|
|
6654
|
+
import { dirname as dirname7, resolve as resolve6 } from "path";
|
|
6640
6655
|
|
|
6641
6656
|
// src/routines.ts
|
|
6642
6657
|
import { readFileSync as readFileSync17, writeFileSync as writeFileSync16, mkdirSync as mkdirSync14 } from "fs";
|
|
@@ -6717,7 +6732,7 @@ function routineJobId(name) {
|
|
|
6717
6732
|
}
|
|
6718
6733
|
function installDarwin2(job, holtPath) {
|
|
6719
6734
|
const path = plistPath(job.id);
|
|
6720
|
-
mkdirSync15(
|
|
6735
|
+
mkdirSync15(dirname7(path), { recursive: true });
|
|
6721
6736
|
writeFileSync17(path, buildLaunchdPlist(job, holtPath), "utf8");
|
|
6722
6737
|
const res = spawnSync5("launchctl", ["load", "-w", path], { encoding: "utf8" });
|
|
6723
6738
|
if (res.status === 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@holt-os/holt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "An open-source personal agent OS: any LLM, private memory you can see and walk.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"files": [
|
|
34
34
|
"dist",
|
|
35
|
+
"skills",
|
|
35
36
|
"README.md",
|
|
36
37
|
"LICENSE"
|
|
37
38
|
],
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: action-items
|
|
3
|
+
description: Pull decisions, tasks, and owners out of messy notes or a meeting transcript. Use to turn a raw log into a clean follow-up list.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# action-items
|
|
7
|
+
|
|
8
|
+
## When to use
|
|
9
|
+
|
|
10
|
+
The user pastes meeting notes, a call transcript, a chat log, or scattered notes and wants the concrete outcomes extracted so nothing gets lost.
|
|
11
|
+
|
|
12
|
+
## Instructions
|
|
13
|
+
|
|
14
|
+
1. Read the whole input and separate the substance from the chit-chat. Ignore greetings, tangents, and thinking-out-loud that led nowhere.
|
|
15
|
+
2. Sort what remains into three groups: DECISIONS (what was settled), TODOS (what someone will do), and OPEN QUESTIONS (what is unresolved).
|
|
16
|
+
3. Write each TODO as "owner: task (due date if stated)". If no owner is named, mark it "unassigned". Preserve names and dates exactly as written.
|
|
17
|
+
4. Write each DECISION as a short statement of what was chosen and, if given, why.
|
|
18
|
+
5. Keep each item to one line. Do not invent owners, dates, or actions that were not in the source.
|
|
19
|
+
6. Output the three lists in that order. Omit a list only if it is genuinely empty.
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
|
|
23
|
+
DECISIONS
|
|
24
|
+
- Ship the beta to the waitlist on Monday, not the public.
|
|
25
|
+
|
|
26
|
+
TODOS
|
|
27
|
+
- Sam: send the waitlist export to marketing (by Fri).
|
|
28
|
+
- unassigned: write the launch FAQ.
|
|
29
|
+
|
|
30
|
+
OPEN QUESTIONS
|
|
31
|
+
- Do we gate signups behind an invite code?
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: brief
|
|
3
|
+
description: A short briefing on the state of the current folder, using recalled memory plus the user's input. Use to get oriented fast.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# brief
|
|
7
|
+
|
|
8
|
+
## When to use
|
|
9
|
+
|
|
10
|
+
The user wants a quick read on what is going on here: what they were working on, what is decided, and what is next. This skill pairs with Holt's memory recall, which surfaces relevant past notes for the current folder.
|
|
11
|
+
|
|
12
|
+
## Instructions
|
|
13
|
+
|
|
14
|
+
1. Assume relevant past notes and facts have been injected as context above. Treat them as your source of truth for prior state; combine them with anything new in the user's input.
|
|
15
|
+
2. Synthesize the state into three threads: what is IN PROGRESS, what is DECIDED, and what is OPEN or NEXT.
|
|
16
|
+
3. Lead with the single most important thing: the item that most needs attention or that unblocks the rest.
|
|
17
|
+
4. Keep it scannable: a short intro line, then tight bullets. This is a briefing, not a report.
|
|
18
|
+
5. If the recalled context is thin or empty, say so plainly and ask the user for the one detail that would make the brief useful, rather than guessing.
|
|
19
|
+
6. Do not restate the raw notes; distill them into current status.
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
|
|
23
|
+
Most important: the migration is blocked on a schema review that has been open three days.
|
|
24
|
+
|
|
25
|
+
In progress: rewriting the importer; decided: drop the legacy CSV path; open: who signs off on the schema change.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-review
|
|
3
|
+
description: Review a file or a diff for correctness bugs, edge cases, and simplifications. Use before merging or when a change feels risky.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# code-review
|
|
7
|
+
|
|
8
|
+
## When to use
|
|
9
|
+
|
|
10
|
+
The user shares a file, a function, or a diff and wants a focused review. The goal is catching real problems, not restyling working code.
|
|
11
|
+
|
|
12
|
+
## Instructions
|
|
13
|
+
|
|
14
|
+
1. Read for real defects first: logic errors, off-by-one and boundary mistakes, unhandled error paths, null or empty cases, security holes (injection, unescaped input, secrets), and resource leaks (unclosed files, sockets, handles).
|
|
15
|
+
2. Then look for clarity and simplification: duplicated logic, dead code, overly clever constructs, and places a simpler shape would do the same job.
|
|
16
|
+
3. Then note style issues, but only if they hurt readability. Skip pure nits unless the user asks for them.
|
|
17
|
+
4. Report each finding as file:line, then what is wrong, then why it matters, then a concrete fix or the corrected snippet.
|
|
18
|
+
5. Rank findings by severity: bugs and security first, then simplifications, then minor. Put the most important at the top.
|
|
19
|
+
6. Be concise. If a change is clean, say so plainly instead of manufacturing feedback.
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
|
|
23
|
+
- api.ts:42 (bug): the loop uses <= arr.length, so the last iteration reads arr[arr.length] which is undefined. Change to <.
|
|
24
|
+
- api.ts:88 (simplify): this if/else both return the same object with one field flipped; collapse to one return with a ternary.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: commit
|
|
3
|
+
description: Draft a clear commit message from staged changes or a described change. Use when you want a clean, conventional message.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# commit
|
|
7
|
+
|
|
8
|
+
## When to use
|
|
9
|
+
|
|
10
|
+
The user has staged changes (or describes a change in words) and wants a well-formed commit message.
|
|
11
|
+
|
|
12
|
+
## Instructions
|
|
13
|
+
|
|
14
|
+
1. Write a concise subject line in the imperative mood ("add", "fix", "remove", not "added" or "fixes"). Keep it under about 72 characters and do not end it with a period.
|
|
15
|
+
2. If the change is trivial, the subject alone is enough. Stop there.
|
|
16
|
+
3. If the change is non-trivial, add a blank line, then a short body that explains what changed and why, not how. The diff already shows how.
|
|
17
|
+
4. If unrelated changes are bundled together, note that they would be cleaner as separate commits, but still give a usable message.
|
|
18
|
+
5. Write a plain message. Do not add tool-attribution footers, "generated by" lines, or co-author trailers unless the user explicitly asks.
|
|
19
|
+
6. If the intent is ambiguous from the changes, ask one clarifying question before guessing.
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
|
|
23
|
+
Subject: fix off-by-one in pagination cursor
|
|
24
|
+
|
|
25
|
+
Body:
|
|
26
|
+
The cursor advanced past the last page because the bound used <= instead of <, returning an empty final page. Correct the comparison so the last item is included.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: decide
|
|
3
|
+
description: Weigh a decision and give a clear recommendation. Use when the user is stuck between options and wants a reasoned call.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# decide
|
|
7
|
+
|
|
8
|
+
## When to use
|
|
9
|
+
|
|
10
|
+
The user faces a choice (which tool, which approach, whether to do something) and wants help thinking it through and a straight recommendation, not just a list of considerations.
|
|
11
|
+
|
|
12
|
+
## Instructions
|
|
13
|
+
|
|
14
|
+
1. Restate the decision and the options on the table in one line each, so you are answering the real question.
|
|
15
|
+
2. List the factors that actually matter for this choice: cost, time, risk, reversibility, effort, fit. Drop factors that do not move the decision.
|
|
16
|
+
3. For each option, give honest pros and cons against those factors. Do not stack the deck; name the real downside of the option you prefer.
|
|
17
|
+
4. Make a clear recommendation. State the main reason it wins and the biggest risk it carries.
|
|
18
|
+
5. If the call genuinely hinges on one unknown, do not guess: name that missing fact and ask for it before committing.
|
|
19
|
+
6. Keep it decisive. The user wants a lean, not a shrug.
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
|
|
23
|
+
Decision: build the export feature now, or ship without it.
|
|
24
|
+
|
|
25
|
+
Build it: pro, unblocks the biggest customer; con, adds a week.
|
|
26
|
+
Ship without: pro, launch on time; con, that customer may churn.
|
|
27
|
+
|
|
28
|
+
Recommendation: build it. Losing the anchor customer outweighs a week's delay. Biggest risk: the week slips to two. Missing fact: has the customer given a hard deadline?
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: explain
|
|
3
|
+
description: Explain a concept, error message, or piece of jargon in plain language. Use when the user wants to understand something unfamiliar.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# explain
|
|
7
|
+
|
|
8
|
+
## When to use
|
|
9
|
+
|
|
10
|
+
The user asks what something means: a concept, an acronym, an error message, a term of art, or a confusing sentence. They want clarity, not a lecture.
|
|
11
|
+
|
|
12
|
+
## Instructions
|
|
13
|
+
|
|
14
|
+
1. Say what it is in one plain sentence, no jargon. If you must use a technical term, define it in the same breath.
|
|
15
|
+
2. Say why it matters or where it shows up, so the user knows why they should care.
|
|
16
|
+
3. Give one concrete analogy or a small worked example that makes it click.
|
|
17
|
+
4. Match the level to the audience. If the user asks for "explain to a beginner" or "to a senior engineer", adjust depth, assumed background, and vocabulary accordingly. When unsure, aim for a smart non-expert.
|
|
18
|
+
5. Keep it short. Stop once the idea lands; offer to go deeper rather than front-loading everything.
|
|
19
|
+
|
|
20
|
+
## Example
|
|
21
|
+
|
|
22
|
+
Request: explain what a race condition is, to a beginner.
|
|
23
|
+
|
|
24
|
+
A race condition is when the result of your program depends on which of two things happens first, and you cannot control the order. It matters because it makes bugs that appear only sometimes. Think of two people editing the same shared doc line at the same time: whoever saves last wins, and the other edit silently vanishes.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: explain-code
|
|
3
|
+
description: Walk through what a file or function does and how it fits into the wider system. Use to onboard onto unfamiliar code.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# explain-code
|
|
7
|
+
|
|
8
|
+
## When to use
|
|
9
|
+
|
|
10
|
+
The user shares a file or function they did not write (or wrote a while ago) and wants to understand what it does, how it works, and how it connects to the rest of the code.
|
|
11
|
+
|
|
12
|
+
## Instructions
|
|
13
|
+
|
|
14
|
+
1. Start with a one-line purpose: what this code is for, in plain terms.
|
|
15
|
+
2. Describe the flow and structure: the main steps or branches, in the order they run. Explain intent, not every line.
|
|
16
|
+
3. Call out key dependencies and side effects: what it imports or calls, what state it reads or mutates, what it writes to disk, network, or the console.
|
|
17
|
+
4. Flag any gotchas: assumptions it makes, inputs it does not handle, and non-obvious behavior a reader would trip on.
|
|
18
|
+
5. Match depth to size. A small helper gets a few sentences; a large module gets a section per responsibility. Do not restate the code line by line.
|
|
19
|
+
6. If something is genuinely unclear or looks buggy, say so rather than inventing a rationale.
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
|
|
23
|
+
Purpose: parses a config file and returns a typed settings object.
|
|
24
|
+
|
|
25
|
+
Flow: reads the file, tries JSON.parse, falls back to defaults on any error, then validates required keys.
|
|
26
|
+
|
|
27
|
+
Gotcha: it swallows parse errors silently, so a malformed config looks identical to a missing one.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: plan
|
|
3
|
+
description: Break a goal into a concrete, ordered set of steps. Use when a task is big enough to need sequencing before starting.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# plan
|
|
7
|
+
|
|
8
|
+
## When to use
|
|
9
|
+
|
|
10
|
+
The user states a goal or a task and wants it broken into an actionable, ordered plan they can execute or hand off.
|
|
11
|
+
|
|
12
|
+
## Instructions
|
|
13
|
+
|
|
14
|
+
1. Restate the goal in one line so the target is unambiguous.
|
|
15
|
+
2. List the steps in the order they must happen. Each step gets a clear done-condition: how you will know it is finished.
|
|
16
|
+
3. Flag dependencies explicitly (step 4 needs step 2 done first) so the sequence is not just a wish list.
|
|
17
|
+
4. Call out the riskiest or most uncertain step, the one most likely to blow up the timeline, so it can be tackled or de-risked early.
|
|
18
|
+
5. Keep it actionable, not aspirational. Prefer "write the migration script and run it on a copy" over "improve the database".
|
|
19
|
+
6. End with the single immediate next action the user should take right now.
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
|
|
23
|
+
Goal: move the app from the old auth library to the new one.
|
|
24
|
+
|
|
25
|
+
1. Inventory every call site of the old library (done: a list exists).
|
|
26
|
+
2. Write an adapter matching the old interface (done: tests pass). RISKIEST: the token refresh path differs.
|
|
27
|
+
3. Swap call sites behind a flag (done: app runs on the flag).
|
|
28
|
+
|
|
29
|
+
Next action: run the inventory grep in step 1.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rewrite
|
|
3
|
+
description: Tighten and clarify a piece of text without changing its meaning. Use for a neutral clarity pass on text the user provides.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# rewrite
|
|
7
|
+
|
|
8
|
+
## When to use
|
|
9
|
+
|
|
10
|
+
The user pastes a paragraph, email, or passage and wants it cleaner and clearer while keeping the same meaning. This is a neutral clarity pass, distinct from a voice-anchored writing task: keep the author's own voice unless a tone is requested.
|
|
11
|
+
|
|
12
|
+
## Instructions
|
|
13
|
+
|
|
14
|
+
1. Preserve intent and every fact. Do not add claims, drop caveats, or change the point being made.
|
|
15
|
+
2. Cut filler and hedging: "just", "really", "I think that", "in order to", throat-clearing intros, and redundant phrases.
|
|
16
|
+
3. Prefer plain words over inflated ones ("use" not "utilize", "help" not "facilitate").
|
|
17
|
+
4. Vary sentence length so it reads naturally; break up run-ons, and do not make everything staccato.
|
|
18
|
+
5. Keep the author's voice and register. Only shift tone (more formal, warmer, punchier) if the user asks for it.
|
|
19
|
+
6. Return only the rewritten text, then one short line noting what you changed (for example: "tightened, cut hedging, split two long sentences").
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
|
|
23
|
+
Before: I just wanted to reach out in order to see if you might possibly have some availability to maybe hop on a quick call sometime.
|
|
24
|
+
|
|
25
|
+
After: Do you have time for a quick call this week?
|
|
26
|
+
|
|
27
|
+
Changed: cut hedging and filler, made it a direct ask.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: summarize
|
|
3
|
+
description: Condense a document, article, transcript, or pasted text into its key points. Use when the input is long and the user wants the gist fast.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# summarize
|
|
7
|
+
|
|
8
|
+
## When to use
|
|
9
|
+
|
|
10
|
+
The user pastes or points at a document, article, transcript, email thread, or any long block of text and wants a shorter version that keeps what matters.
|
|
11
|
+
|
|
12
|
+
## Instructions
|
|
13
|
+
|
|
14
|
+
1. Read the whole input first and identify its core purpose in one sentence (what it is and why it exists).
|
|
15
|
+
2. Open with a one-line TLDR that captures the single most important takeaway.
|
|
16
|
+
3. Pull the main points: arguments, decisions, numbers, dates, and named people or systems. Keep these verbatim where accuracy matters.
|
|
17
|
+
4. Drop filler: greetings, repetition, hedging, and asides that do not change the meaning.
|
|
18
|
+
5. Scale the output to the input. A few paragraphs get a short bulleted list; a long report gets tight prose grouped by theme. Do not pad.
|
|
19
|
+
6. Do not add facts, opinions, or conclusions that are not in the source.
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
|
|
23
|
+
TLDR: The team is shipping the payments rewrite next week despite one open risk.
|
|
24
|
+
|
|
25
|
+
- Decision: launch v2 on the 14th, feature-flagged to 10 percent of users.
|
|
26
|
+
- Open risk: the refund path is untested under load.
|
|
27
|
+
- Owner: Priya to run a load test before Friday.
|