@smitdev/ai-skills 0.1.0 → 0.3.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 CHANGED
@@ -14,7 +14,8 @@ No global install needed — run it with `npx`:
14
14
  # See what's available
15
15
  npx @smitdev/ai-skills list
16
16
 
17
- # Interactive: pick assistant(s) and skill(s)
17
+ # Interactive: pick assistant(s) and skill(s) with the keyboard
18
+ # ↑/↓ move · space or tab toggle · a select all · enter confirm
18
19
  npx @smitdev/ai-skills install
19
20
 
20
21
  # Non-interactive examples
@@ -43,6 +44,11 @@ Use `--dry-run` to preview without writing anything.
43
44
 
44
45
  - **contract** — Create a build-ready spec / PRD for a feature before any code
45
46
  is written, so a coding assistant can build it without guessing.
47
+ - **understand** — Read a whole codebase and write a connected set of
48
+ plain-language docs (a map plus one doc per aspect) to onboard fast.
49
+ - **gistly** — Answer a question so it's correct, dense, and easy to hold in
50
+ your head: the answer first, the mental model that makes it stick, fewest
51
+ tokens it honestly needs.
46
52
 
47
53
  ## Authoring your own skills
48
54
 
package/bin/cli.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
- const readline = require('readline');
5
4
  const path = require('path');
6
5
  const { listSkills } = require('../lib/skills');
7
6
  const { adapters } = require('../lib/adapters');
8
7
  const { install } = require('../lib/install');
8
+ const { multiselect, select } = require('../lib/prompt');
9
9
 
10
10
  const ASSISTANT_IDS = Object.keys(adapters);
11
11
 
@@ -31,10 +31,6 @@ function parseArgs(argv) {
31
31
  return args;
32
32
  }
33
33
 
34
- function ask(rl, question) {
35
- return new Promise((resolve) => rl.question(question, (a) => resolve(a.trim())));
36
- }
37
-
38
34
  function parseList(val, valid) {
39
35
  if (val === true || !val) return [];
40
36
  const items = String(val)
@@ -55,6 +51,8 @@ Usage:
55
51
  Commands:
56
52
  list List the skills bundled in this package
57
53
  install Install skills for one or more assistants
54
+ (run with no flags for an interactive picker:
55
+ ↑/↓ move · space/tab toggle · a all · enter confirm)
58
56
 
59
57
  Options for "install":
60
58
  --assistant <ids> Comma-separated: ${ASSISTANT_IDS.join(', ')} (or "all")
@@ -73,20 +71,6 @@ Examples:
73
71
  `);
74
72
  }
75
73
 
76
- async function pickFromList(rl, label, options) {
77
- console.log(`\n${label}`);
78
- options.forEach((o, i) => console.log(` ${i + 1}. ${o.label}`));
79
- console.log(` (comma-separated numbers, or "a" for all)`);
80
- const ans = await ask(rl, '> ');
81
- if (ans.toLowerCase() === 'a' || ans === '') return options.map((o) => o.id);
82
- const picked = ans
83
- .split(',')
84
- .map((s) => parseInt(s.trim(), 10))
85
- .filter((n) => n >= 1 && n <= options.length)
86
- .map((n) => options[n - 1].id);
87
- return [...new Set(picked)];
88
- }
89
-
90
74
  async function runInstall(args) {
91
75
  const skills = listSkills();
92
76
  if (skills.length === 0) {
@@ -98,31 +82,43 @@ async function runInstall(args) {
98
82
  typeof args.flags.dir === 'string' ? args.flags.dir : process.cwd()
99
83
  );
100
84
  const dryRun = !!args.flags['dry-run'];
101
- const scope = args.flags.global ? 'global' : 'project';
85
+ const scopeFlagged = !!args.flags.global || !!args.flags.project;
86
+ let scope = args.flags.global ? 'global' : 'project';
102
87
 
103
88
  let assistants = parseList(args.flags.assistant, ASSISTANT_IDS);
104
89
  let skillNames = parseList(args.flags.skill, skills.map((s) => s.name));
105
90
 
106
- const nonInteractive =
107
- args.flags.yes || (assistants.length > 0);
91
+ const nonInteractive = args.flags.yes || assistants.length > 0;
108
92
 
109
93
  if (!nonInteractive && process.stdin.isTTY) {
110
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
111
94
  if (assistants.length === 0) {
112
- assistants = await pickFromList(
113
- rl,
114
- 'Which assistant(s)?',
115
- ASSISTANT_IDS.map((id) => ({ id, label: adapters[id].label }))
116
- );
95
+ assistants = await multiselect({
96
+ title: 'Which assistant(s)? (Claude Code, Copilot, Cursor, Windsurf)',
97
+ options: ASSISTANT_IDS.map((id) => ({ id, label: adapters[id].label })),
98
+ initial: ['claude'],
99
+ });
117
100
  }
118
101
  if (skillNames.length === 0) {
119
- skillNames = await pickFromList(
120
- rl,
121
- 'Which skill(s)?',
122
- skills.map((s) => ({ id: s.name, label: `${s.name} — ${truncate(s.description, 60)}` }))
123
- );
102
+ skillNames = await multiselect({
103
+ title: 'Which skill(s)?',
104
+ options: skills.map((s) => ({
105
+ id: s.name,
106
+ label: `${s.name} — ${truncate(s.description, 60)}`,
107
+ })),
108
+ initial: skills.map((s) => s.name),
109
+ });
110
+ }
111
+ // Only Claude Code supports a global scope; ask when relevant.
112
+ if (!scopeFlagged && assistants.includes('claude')) {
113
+ scope = await select({
114
+ title: 'Install scope for Claude Code?',
115
+ options: [
116
+ { id: 'project', label: 'This project (./.claude/skills)' },
117
+ { id: 'global', label: 'Global (~/.claude/skills, available everywhere)' },
118
+ ],
119
+ initial: 'project',
120
+ });
124
121
  }
125
- rl.close();
126
122
  }
127
123
 
128
124
  if (assistants.length === 0) assistants = ASSISTANT_IDS.slice();
package/lib/prompt.js ADDED
@@ -0,0 +1,185 @@
1
+ 'use strict';
2
+
3
+ const readline = require('readline');
4
+
5
+ // Tiny zero-dependency interactive prompts (checkbox + radio) built on
6
+ // readline keypress events. Falls back to nothing in non-TTY environments —
7
+ // callers should guard with process.stdin.isTTY.
8
+
9
+ const useColor = !!process.stdout.isTTY && !process.env.NO_COLOR;
10
+ const paint = (code) => (s) => (useColor ? `\x1b[${code}m${s}\x1b[0m` : String(s));
11
+ const dim = paint('2');
12
+ const bold = paint('1');
13
+ const cyan = paint('36');
14
+ const green = paint('32');
15
+
16
+ function setupKeys() {
17
+ const input = process.stdin;
18
+ readline.emitKeypressEvents(input);
19
+ if (input.isTTY) input.setRawMode(true);
20
+ input.resume();
21
+ return input;
22
+ }
23
+
24
+ function teardownKeys(input, onKey) {
25
+ input.removeListener('keypress', onKey);
26
+ if (input.isTTY) input.setRawMode(false);
27
+ input.pause();
28
+ }
29
+
30
+ function hideCursor() {
31
+ if (useColor) process.stdout.write('\x1b[?25l');
32
+ }
33
+ function showCursor() {
34
+ if (useColor) process.stdout.write('\x1b[?25h');
35
+ }
36
+
37
+ /**
38
+ * Multi-select checkbox prompt.
39
+ * options: [{ id, label }]
40
+ * initial: array of pre-selected ids
41
+ * Resolves to an array of selected ids (in option order). Always returns at
42
+ * least one (the highlighted item) so callers never get an empty selection.
43
+ */
44
+ function multiselect({ title, options, initial }) {
45
+ return new Promise((resolve) => {
46
+ const selected = new Set(initial || []);
47
+ let cursor = 0;
48
+ let rendered = 0;
49
+ const output = process.stdout;
50
+
51
+ const hint = dim(
52
+ '↑/↓ move · space/tab toggle · a all · enter confirm'
53
+ );
54
+
55
+ function render(first) {
56
+ if (!first) output.write(`\x1b[${rendered}A`);
57
+ const lines = [bold(title), hint];
58
+ options.forEach((o, i) => {
59
+ const active = i === cursor;
60
+ const pointer = active ? cyan('›') : ' ';
61
+ const box = selected.has(o.id) ? green('◉') : dim('◯');
62
+ const label = active ? cyan(o.label) : o.label;
63
+ lines.push(`${pointer} ${box} ${label}`);
64
+ });
65
+ output.write(lines.map((l) => '\x1b[2K' + l).join('\n') + '\n');
66
+ rendered = lines.length;
67
+ }
68
+
69
+ const input = setupKeys();
70
+ hideCursor();
71
+
72
+ function finish() {
73
+ if (selected.size === 0) selected.add(options[cursor].id);
74
+ teardownKeys(input, onKey);
75
+ showCursor();
76
+ resolve(options.filter((o) => selected.has(o.id)).map((o) => o.id));
77
+ }
78
+
79
+ function onKey(_str, key) {
80
+ if (!key) return;
81
+ if (key.ctrl && key.name === 'c') {
82
+ teardownKeys(input, onKey);
83
+ showCursor();
84
+ output.write('\n');
85
+ process.exit(130);
86
+ }
87
+ switch (key.name) {
88
+ case 'up':
89
+ case 'k':
90
+ cursor = (cursor - 1 + options.length) % options.length;
91
+ break;
92
+ case 'down':
93
+ case 'j':
94
+ cursor = (cursor + 1) % options.length;
95
+ break;
96
+ case 'space':
97
+ case 'tab':
98
+ if (selected.has(options[cursor].id)) selected.delete(options[cursor].id);
99
+ else selected.add(options[cursor].id);
100
+ break;
101
+ case 'a': {
102
+ if (selected.size === options.length) selected.clear();
103
+ else options.forEach((o) => selected.add(o.id));
104
+ break;
105
+ }
106
+ case 'return':
107
+ case 'enter':
108
+ finish();
109
+ return;
110
+ default:
111
+ return;
112
+ }
113
+ render(false);
114
+ }
115
+
116
+ input.on('keypress', onKey);
117
+ render(true);
118
+ });
119
+ }
120
+
121
+ /**
122
+ * Single-select radio prompt.
123
+ * options: [{ id, label }]
124
+ * Resolves to one id.
125
+ */
126
+ function select({ title, options, initial }) {
127
+ return new Promise((resolve) => {
128
+ let cursor = Math.max(0, options.findIndex((o) => o.id === initial));
129
+ if (cursor < 0) cursor = 0;
130
+ let rendered = 0;
131
+ const output = process.stdout;
132
+ const hint = dim('↑/↓ move · enter select');
133
+
134
+ function render(first) {
135
+ if (!first) output.write(`\x1b[${rendered}A`);
136
+ const lines = [bold(title), hint];
137
+ options.forEach((o, i) => {
138
+ const active = i === cursor;
139
+ const pointer = active ? cyan('›') : ' ';
140
+ const dot = active ? green('◉') : dim('◯');
141
+ const label = active ? cyan(o.label) : o.label;
142
+ lines.push(`${pointer} ${dot} ${label}`);
143
+ });
144
+ output.write(lines.map((l) => '\x1b[2K' + l).join('\n') + '\n');
145
+ rendered = lines.length;
146
+ }
147
+
148
+ const input = setupKeys();
149
+ hideCursor();
150
+
151
+ function onKey(_str, key) {
152
+ if (!key) return;
153
+ if (key.ctrl && key.name === 'c') {
154
+ teardownKeys(input, onKey);
155
+ showCursor();
156
+ output.write('\n');
157
+ process.exit(130);
158
+ }
159
+ switch (key.name) {
160
+ case 'up':
161
+ case 'k':
162
+ cursor = (cursor - 1 + options.length) % options.length;
163
+ break;
164
+ case 'down':
165
+ case 'j':
166
+ cursor = (cursor + 1) % options.length;
167
+ break;
168
+ case 'return':
169
+ case 'enter':
170
+ teardownKeys(input, onKey);
171
+ showCursor();
172
+ resolve(options[cursor].id);
173
+ return;
174
+ default:
175
+ return;
176
+ }
177
+ render(false);
178
+ }
179
+
180
+ input.on('keypress', onKey);
181
+ render(true);
182
+ });
183
+ }
184
+
185
+ module.exports = { multiselect, select };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smitdev/ai-skills",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Install reusable AI assistant skills (Claude Code, GitHub Copilot, Cursor, Windsurf) with one command.",
5
5
  "bin": {
6
6
  "ai-skills": "bin/cli.js"
@@ -1,150 +1,150 @@
1
- ---
2
- name: contract
3
- description: Create a contract - a spec or PRD that fully explains a feature before any code is written, so a coding assistant or engineer can build it without guessing. Use this whenever the user wants to plan or spec a feature before building - things like "spec this out", "write a PRD", "let's plan this feature first", "make an implementation doc", "write the contract for X", or "I want a plan before we touch the code". Trigger it even if the user doesn't say the word "contract" - any time they want a build-ready description of a feature instead of the code itself.
4
- ---
5
-
6
- # Contract
7
-
8
- A contract is a plan that you and the user agree on before any code is written. It is the one document a coding assistant reads to build the feature without guessing or making things up. Your job here is to make that document - not to write the feature code.
9
-
10
- Do these three steps in order: understand the codebase, then ask the user questions, then write the contract. Don't jump straight to writing - a contract built on guesses is worse than no contract.
11
-
12
- ## Step 1 - Understand the codebase
13
-
14
- Before you ask the user anything, read the parts of the codebase the feature will touch. You want real files, not a vague idea of the project.
15
-
16
- Find and read the files that will likely change, or that the new code has to work with. For each one, note what it does now, the patterns it follows (naming, error handling, how state and APIs are done), and where the new feature would fit in.
17
-
18
- By the end of this step you should have a short list of real file paths, what each one does today, and where the new feature connects. You'll use this directly in the contract, so write down the real paths - never write a spec that isn't connected to the real code.
19
-
20
- ## Step 2 - Ask the user questions
21
-
22
- Now fill in the gaps. The user knows what they want; you know the code. The questions bring the two together and find the decisions that shape the design.
23
-
24
- Ask one question at a time - never a big list at once. After each answer, ask the next one. This keeps it easy for the user and lets each answer guide the next question.
25
-
26
- For each question, give a short list of simple answer options to pick from, not an open question. Keep the options non-technical - describe what happens, not how it's built. Mark the option you recommend and say in one line why you'd pick it, then ask if they're okay with it. Always add an "other - let me explain" option so they're not stuck with your choices.
27
-
28
- Across the questions, cover: what the feature should do for the user, what's not included (the limits of the work), edge cases and error states, and any spot where two reasonable choices exist. Stop once you can explain the whole feature start to finish with no "it depends" left.
29
-
30
- **Example of how a question should look:**
31
-
32
- > When a search returns no results, what should the user see?
33
- >
34
- > - **A - A short "nothing found" message** (recommended: simplest, and it matches how the rest of the app handles empty states)
35
- > - **B - The empty state plus a few suggestions on what to try next**
36
- > - **C - Keep the last results on screen and just show a small note**
37
- > - **D - Something else - tell me what you have in mind**
38
- >
39
- > I'd go with A. Want to go with that, or pick another?
40
-
41
- ## Step 3 - Check, then write the contract
42
-
43
- Before you write the full document, say your understanding back in a few sentences and get a yes. This is a cheap way to avoid writing a long doc based on a wrong idea.
44
-
45
- Then write the contract using the template below. Leave out any section that doesn't apply (for example, no "Data model" section for a simple styling change) instead of filling it with fluff - but keep the numbers on the sections you do use. Write it so that an engineer or coding assistant who never saw the conversation could build the feature correctly from this document alone.
46
-
47
- ### Contract template
48
-
49
- ```markdown
50
- # Contract: <Feature name>
51
-
52
- **Status:** Draft
53
- **Date:** <YYYY-MM-DD>
54
- **Area:** <which part of the product / module>
55
-
56
- ## 1. Summary
57
-
58
- One short paragraph, plain words: what we're building and why.
59
-
60
- ## 2. Problem
61
-
62
- The problem this solves. What happens now and why that's not good enough.
63
-
64
- ## 3. Goals
65
-
66
- Clear bullets - what success looks like.
67
-
68
- ## 4. Not included (out of scope)
69
-
70
- What this feature does NOT do. This is just as important as the goals - it
71
- stops a coding assistant from adding extra work or features no one asked for.
72
-
73
- ## 5. The code today (what's there now)
74
-
75
- The real files involved and what they do now:
76
-
77
- - `path/to/file.ts` - what it does today; what changes here
78
- - `path/to/other.py` - ...
79
- Patterns and conventions the new code should follow.
80
-
81
- ## 6. The plan
82
-
83
- The approach in a sentence or two, then broken down:
84
-
85
- ### 6.1 UI and UX
86
-
87
- What the user sees and does. Every state: normal, loading, empty, error,
88
- success. Note accessibility where it matters.
89
-
90
- ### 6.2 Data model
91
-
92
- New or changed data: entities, fields, types, how they relate. (Skip if none.)
93
-
94
- ### 6.3 API / interface
95
-
96
- For each endpoint or function: the signature or method + path, what goes in,
97
- what comes back, and the error cases. For frontend: component props, events,
98
- and the state it gives back.
99
-
100
- ### 6.4 Logic and edge cases
101
-
102
- The step-by-step behavior. List the edge cases and say how each is handled -
103
- this is where most of the confusion hides.
104
-
105
- ## 7. Performance and optimization
106
-
107
- How fast and how cheap this has to be, made concrete (real numbers where you
108
- can). Cover what applies:
109
-
110
- - Expected load / scale - how many requests, rows, items, or users, etc.
111
- - The hot paths - the parts that run a lot or work on big data, and the target
112
- (e.g. "the list should load in under X seconds with 10,000 rows").
113
- - Caching, batching, rate limits, concurrency - what to reuse or throttle.
114
- - Cost - any API quota or money limits, and how to stay under them.
115
- Skip this only if the feature has no real performance concern.
116
-
117
- ## 8. Other requirements
118
-
119
- Only the ones that apply: security and access, logging/monitoring, easy to
120
- maintain, reusable.
121
-
122
- ## 9. Files to change (checklist)
123
-
124
- A checklist the coding assistant can follow:
125
-
126
- - [ ] `path/to/file.ts` - what to change
127
- - [ ] `path/to/new_file.py` - new; what it holds
128
-
129
- ## 10. Done when (acceptance criteria)
130
-
131
- How we know it's done, written as things you can test:
132
-
133
- - Given <situation>, when <action>, then <result>.
134
-
135
- ## 11. Risks and open questions
136
-
137
- Guesses you made, choices left for later, anything still unclear.
138
- ```
139
-
140
- ## Where to save it
141
-
142
- Save the contract as a Markdown file. Use the project's existing folder if there is one - look for a `specs/`, `contracts/`, `docs/specs/`, or `.specify/` folder and put it there. If there isn't one, make a `specs/` folder.
143
-
144
- Name the file after the feature, in kebab-case: `specs/<feature-slug>.md` (for example `specs/user-profile-page.md`). Tell the user the path when you're done.
145
-
146
- ## Rules to keep in mind
147
-
148
- - Make the contract, not the code. If the user also wants the code, finish and confirm the contract first - that's the thing they'll read and reuse.
149
- - Keep the user-facing parts (Summary, Problem, Goals) in plain words, and the build-facing parts (API, done-when) exact. The coding assistant needs the exact parts to be exact.
150
- - If you hit a decision while writing that you didn't settle in the questions, stop and ask instead of guessing - then write the answer into the doc.
1
+ ---
2
+ name: contract
3
+ description: Create a contract - a spec or PRD that fully explains a feature before any code is written, so a coding assistant or engineer can build it without guessing. Use this whenever the user wants to plan or spec a feature before building - things like "spec this out", "write a PRD", "let's plan this feature first", "make an implementation doc", "write the contract for X", or "I want a plan before we touch the code". Trigger it even if the user doesn't say the word "contract" - any time they want a build-ready description of a feature instead of the code itself.
4
+ ---
5
+
6
+ # Contract
7
+
8
+ A contract is a plan that you and the user agree on before any code is written. It is the one document a coding assistant reads to build the feature without guessing or making things up. Your job here is to make that document - not to write the feature code.
9
+
10
+ Do these three steps in order: understand the codebase, then ask the user questions, then write the contract. Don't jump straight to writing - a contract built on guesses is worse than no contract.
11
+
12
+ ## Step 1 - Understand the codebase
13
+
14
+ Before you ask the user anything, read the parts of the codebase the feature will touch. You want real files, not a vague idea of the project.
15
+
16
+ Find and read the files that will likely change, or that the new code has to work with. For each one, note what it does now, the patterns it follows (naming, error handling, how state and APIs are done), and where the new feature would fit in.
17
+
18
+ By the end of this step you should have a short list of real file paths, what each one does today, and where the new feature connects. You'll use this directly in the contract, so write down the real paths - never write a spec that isn't connected to the real code.
19
+
20
+ ## Step 2 - Ask the user questions
21
+
22
+ Now fill in the gaps. The user knows what they want; you know the code. The questions bring the two together and find the decisions that shape the design.
23
+
24
+ Ask one question at a time - never a big list at once. After each answer, ask the next one. This keeps it easy for the user and lets each answer guide the next question.
25
+
26
+ For each question, give a short list of simple answer options to pick from, not an open question. Keep the options non-technical - describe what happens, not how it's built. Mark the option you recommend and say in one line why you'd pick it, then ask if they're okay with it. Always add an "other - let me explain" option so they're not stuck with your choices.
27
+
28
+ Across the questions, cover: what the feature should do for the user, what's not included (the limits of the work), edge cases and error states, and any spot where two reasonable choices exist. Stop once you can explain the whole feature start to finish with no "it depends" left.
29
+
30
+ **Example of how a question should look:**
31
+
32
+ > When a search returns no results, what should the user see?
33
+ >
34
+ > - **A - A short "nothing found" message** (recommended: simplest, and it matches how the rest of the app handles empty states)
35
+ > - **B - The empty state plus a few suggestions on what to try next**
36
+ > - **C - Keep the last results on screen and just show a small note**
37
+ > - **D - Something else - tell me what you have in mind**
38
+ >
39
+ > I'd go with A. Want to go with that, or pick another?
40
+
41
+ ## Step 3 - Check, then write the contract
42
+
43
+ Before you write the full document, say your understanding back in a few sentences and get a yes. This is a cheap way to avoid writing a long doc based on a wrong idea.
44
+
45
+ Then write the contract using the template below. Leave out any section that doesn't apply (for example, no "Data model" section for a simple styling change) instead of filling it with fluff - but keep the numbers on the sections you do use. Write it so that an engineer or coding assistant who never saw the conversation could build the feature correctly from this document alone.
46
+
47
+ ### Contract template
48
+
49
+ ```markdown
50
+ # Contract: <Feature name>
51
+
52
+ **Status:** Draft
53
+ **Date:** <YYYY-MM-DD>
54
+ **Area:** <which part of the product / module>
55
+
56
+ ## 1. Summary
57
+
58
+ One short paragraph, plain words: what we're building and why.
59
+
60
+ ## 2. Problem
61
+
62
+ The problem this solves. What happens now and why that's not good enough.
63
+
64
+ ## 3. Goals
65
+
66
+ Clear bullets - what success looks like.
67
+
68
+ ## 4. Not included (out of scope)
69
+
70
+ What this feature does NOT do. This is just as important as the goals - it
71
+ stops a coding assistant from adding extra work or features no one asked for.
72
+
73
+ ## 5. The code today (what's there now)
74
+
75
+ The real files involved and what they do now:
76
+
77
+ - `path/to/file.ts` - what it does today; what changes here
78
+ - `path/to/other.py` - ...
79
+ Patterns and conventions the new code should follow.
80
+
81
+ ## 6. The plan
82
+
83
+ The approach in a sentence or two, then broken down:
84
+
85
+ ### 6.1 UI and UX
86
+
87
+ What the user sees and does. Every state: normal, loading, empty, error,
88
+ success. Note accessibility where it matters.
89
+
90
+ ### 6.2 Data model
91
+
92
+ New or changed data: entities, fields, types, how they relate. (Skip if none.)
93
+
94
+ ### 6.3 API / interface
95
+
96
+ For each endpoint or function: the signature or method + path, what goes in,
97
+ what comes back, and the error cases. For frontend: component props, events,
98
+ and the state it gives back.
99
+
100
+ ### 6.4 Logic and edge cases
101
+
102
+ The step-by-step behavior. List the edge cases and say how each is handled -
103
+ this is where most of the confusion hides.
104
+
105
+ ## 7. Performance and optimization
106
+
107
+ How fast and how cheap this has to be, made concrete (real numbers where you
108
+ can). Cover what applies:
109
+
110
+ - Expected load / scale - how many requests, rows, items, or users, etc.
111
+ - The hot paths - the parts that run a lot or work on big data, and the target
112
+ (e.g. "the list should load in under X seconds with 10,000 rows").
113
+ - Caching, batching, rate limits, concurrency - what to reuse or throttle.
114
+ - Cost - any API quota or money limits, and how to stay under them.
115
+ Skip this only if the feature has no real performance concern.
116
+
117
+ ## 8. Other requirements
118
+
119
+ Only the ones that apply: security and access, logging/monitoring, easy to
120
+ maintain, reusable.
121
+
122
+ ## 9. Files to change (checklist)
123
+
124
+ A checklist the coding assistant can follow:
125
+
126
+ - [ ] `path/to/file.ts` - what to change
127
+ - [ ] `path/to/new_file.py` - new; what it holds
128
+
129
+ ## 10. Done when (acceptance criteria)
130
+
131
+ How we know it's done, written as things you can test:
132
+
133
+ - Given <situation>, when <action>, then <result>.
134
+
135
+ ## 11. Risks and open questions
136
+
137
+ Guesses you made, choices left for later, anything still unclear.
138
+ ```
139
+
140
+ ## Where to save it
141
+
142
+ Save the contract as a Markdown file. Use the project's existing folder if there is one - look for a `specs/`, `contracts/`, `docs/specs/`, or `.specify/` folder and put it there. If there isn't one, make a `specs/` folder.
143
+
144
+ Name the file after the feature, in kebab-case: `specs/<feature-slug>.md` (for example `specs/user-profile-page.md`). Tell the user the path when you're done.
145
+
146
+ ## Rules to keep in mind
147
+
148
+ - Make the contract, not the code. If the user also wants the code, finish and confirm the contract first - that's the thing they'll read and reuse.
149
+ - Keep the user-facing parts (Summary, Problem, Goals) in plain words, and the build-facing parts (API, done-when) exact. The coding assistant needs the exact parts to be exact.
150
+ - If you hit a decision while writing that you didn't settle in the questions, stop and ask instead of guessing - then write the answer into the doc.
@@ -0,0 +1,55 @@
1
+ ---
2
+ name: gistly
3
+ description: Answer a question so it is correct, dense, and easy to hold in your head - the right answer first, the mental model that makes it stick, and as few tokens as it takes to get there. Use this whenever the user asks a question and wants a clear answer rather than code or a document - things like "explain X", "how does Y work", "what's the difference between A and B", "why does Z happen", "help me understand this", or any plain question where a tight, well-modeled answer beats a long one. Not for documenting a codebase (use understand) or speccing a feature (use contract).
4
+ ---
5
+
6
+ # Gistly
7
+
8
+ The job is to answer a question so the person both gets the correct answer and walks away with a mental model they can reuse - using as few tokens as the answer honestly needs. Dense, not terse. Every sentence should carry information the reader didn't already have.
9
+
10
+ Token-efficient does not mean short for its own sake. It means high signal per word: cut the filler, keep the substance. A wrong-but-short answer fails. A correct-but-bloated answer wastes the reader's attention. Aim for correct, modeled, and lean - in that order.
11
+
12
+ ## Answer in this order
13
+
14
+ 1. **Direct answer first.** Open with the actual answer in one or two sentences - the thing they asked for, before any setup. No preamble, no restating the question, no "great question".
15
+ 2. **The mental model.** Give the one organizing idea, analogy, or rule that makes the rest derivable - the "now I get it" sentence. This is the part that makes the answer stick, so it's worth the tokens even when everything else is trimmed.
16
+ 3. **Just enough detail to act on it.** The few specifics, steps, or caveats they need and no more. Stop when the question is answered, not when you run out of things to say.
17
+
18
+ ## What to cut
19
+
20
+ - Preamble and filler: "Great question", "It's worth noting", "As you may know", "In order to", "Basically".
21
+ - Restating the question back before answering it.
22
+ - Hedging and apology: say the thing. If you're unsure, see the rule below - that's different from hedging.
23
+ - Repeating the same point in three phrasings. Make it once, well.
24
+ - Caveats nobody asked about and edge cases that don't change the answer.
25
+ - Throat-clearing closers: "I hope this helps", "Let me know if you have questions".
26
+
27
+ ## What to keep
28
+
29
+ - The mental model - never cut the idea that makes it click to save a sentence.
30
+ - A concrete example when it teaches faster than the abstract rule. One sharp example beats a paragraph of theory.
31
+ - The caveat that would actually bite them if left out.
32
+ - The "why", when knowing why lets them figure out the next case themselves instead of asking again.
33
+
34
+ ## Use structure that compresses
35
+
36
+ Pick the form that carries the meaning in the fewest tokens:
37
+
38
+ - **Comparisons / trade-offs** -> a small table or two labeled lines, not prose.
39
+ - **A process or causal chain** -> `A -> B -> C` or a short numbered list.
40
+ - **A few independent points** -> tight bullets, one idea each.
41
+ - **A single idea** -> one or two plain sentences. Don't add structure a sentence doesn't need.
42
+
43
+ Match depth to the question. A quick "what's the flag for X" gets one line. A "why does this whole thing work this way" earns a model plus an example. Read which one they asked.
44
+
45
+ ## Stay correct
46
+
47
+ Token-efficiency never comes before being right.
48
+
49
+ - If you're not sure, say so in a few words and state your confidence ("I think X, but verify Y") - don't pad uncertainty into a long hedge, and don't state a guess as fact.
50
+ - Don't invent specifics (numbers, flags, names, APIs) to sound complete. A short answer that admits a gap beats a fluent wrong one.
51
+ - If the question is ambiguous and the answers genuinely differ, ask one sharp clarifying question instead of writing all branches. If the branches are short, just cover them.
52
+
53
+ ## The test
54
+
55
+ Before sending, check: Is the answer right? Would the reader come away with a model they can reuse on the next case? Could I cut a third of the words without losing meaning? If yes to the last one, cut them.
@@ -0,0 +1,133 @@
1
+ ---
2
+ name: understand
3
+ description: Read a whole codebase and write a set of plain-language docs that explain it - one overview/map doc plus one doc per aspect (UI, styles, API, models, data, testing, features, services, and so on). Use this when someone wants to understand a project as a whole or get onboarded to a repo - things like "help me understand this codebase", "document this repo", "explain how this project is structured", "map out the code", "onboard me to this project", or "I just joined and need to learn this code". This is for the WHOLE codebase. To explain one single feature in depth, use the feature-explainer skill instead.
4
+ ---
5
+
6
+ # Understanding
7
+
8
+ The goal is to help someone understand a codebase fast - like a new engineer joining the team next week. You do that by reading the code and writing a small set of plain, connected docs: one map that gives the big picture, and one doc per aspect (UI, API, data, and so on) that goes deeper.
9
+
10
+ Write everything for a smart person who is new to this project. No jargon dumps. Point to real files. Don't make things up - if you didn't read something, say so.
11
+
12
+ Do these steps in order: survey the repo, pick the aspects, write the map, then write each aspect doc.
13
+
14
+ ## Step 1 - Survey the repo
15
+
16
+ Get the big picture before going deep. Look at:
17
+
18
+ - The entry points (main file, app start, routes, index).
19
+ - The folder layout - what the top-level folders are for.
20
+ - Config and dependencies (package.json, requirements, env files) - this tells you the stack and the main libraries.
21
+ - The README, if there is one.
22
+
23
+ You don't need to read every file. Read the entry points and a few important files in each area so you understand how the project is put together. Note what you did and didn't read.
24
+
25
+ ## Step 2 - Pick the aspects
26
+
27
+ Don't force a fixed list. Look at what this repo actually has and pick the aspects that apply. A good default set:
28
+
29
+ 1. UI elements
30
+ 2. Styles
31
+ 3. API
32
+ 4. Models
33
+ 5. Data
34
+ 6. Testing
35
+ 7. Features
36
+ 8. Services
37
+
38
+ But adjust to the repo. Drop ones that don't exist (a backend repo has no UI or styles). Add ones that matter here but aren't listed (for example: auth, config, state management, build/deploy, data flow, third-party integrations). Tell the user the list of aspects you landed on before you write.
39
+
40
+ ## Step 3 - Write the map doc first
41
+
42
+ This is the most important doc - it ties everything together and gives the mental model. Write it before the aspect docs. Use this shape:
43
+
44
+ ```markdown
45
+ # Codebase map: <project name>
46
+
47
+ ## What this project is
48
+
49
+ One short paragraph in plain words - what it does and who it's for.
50
+
51
+ ## The big pieces
52
+
53
+ The main parts of the system and what each one is responsible for. Link to the
54
+ aspect doc for each (e.g. "see api.md").
55
+
56
+ ## How it's laid out
57
+
58
+ The folder structure and what each top-level folder is for.
59
+
60
+ ## How a typical action flows through
61
+
62
+ Follow one common action from start to finish (e.g. a user clicks X -> this
63
+ component -> this API -> this service -> this data). This is the part that makes
64
+ it all click. A simple diagram or step list is great here.
65
+
66
+ ## Stack and key dependencies
67
+
68
+ The main languages, frameworks, and libraries, and what each is used for.
69
+
70
+ ## Where to start reading
71
+
72
+ The 3-5 files a newcomer should open first, and why.
73
+
74
+ ## What this map skips
75
+
76
+ Anything you didn't read or that's out of scope, so the reader isn't misled.
77
+ ```
78
+
79
+ ## Step 4 - Write one doc per aspect
80
+
81
+ For each aspect from Step 2, write a doc using the same shape so they all feel consistent:
82
+
83
+ ```markdown
84
+ # <Aspect> (e.g. API)
85
+
86
+ ## What this covers
87
+
88
+ One or two sentences - what this aspect is and why it matters here.
89
+
90
+ ## Where it lives
91
+
92
+ The key files and folders, with real paths:
93
+
94
+ - `path/to/file` - what it does
95
+
96
+ ## How it works
97
+
98
+ The mental model in plain words. How the pieces fit together. A small diagram
99
+ or flow helps a lot.
100
+
101
+ ## The main pieces
102
+
103
+ The important files/modules/functions and what each one does. Keep it to the
104
+ ones that matter, not every file.
105
+
106
+ ## How it connects to the rest
107
+
108
+ How this aspect talks to the others (e.g. the API calls these services, which
109
+ read these models).
110
+
111
+ ## Gotchas
112
+
113
+ The non-obvious things - surprises, tricky bits, patterns you have to know.
114
+ Whatever would trip up a newcomer.
115
+
116
+ ## Where to start reading
117
+
118
+ The first file or two to open to understand this aspect.
119
+ ```
120
+
121
+ ## Where to save the docs
122
+
123
+ Put all the docs in one folder so they're a set. Reuse the project's docs folder if there is one - look for `docs/`, then use `docs/codebase/`. If there's no docs folder, create `codebase-map/`.
124
+
125
+ Name the files simply: the map is `overview.md`, and each aspect is its lowercase name (`api.md`, `ui.md`, `data.md`, ...). Tell the user the folder path and the list of files when you're done.
126
+
127
+ ## Rules to keep in mind
128
+
129
+ - Write for a newcomer. Plain words, real examples, no walls of jargon.
130
+ - Point to real file paths. Every claim should be tied to actual code, not a guess.
131
+ - Don't invent. If you didn't read part of the code, leave it out and say so in the "skips" section rather than guessing.
132
+ - Keep the docs connected. The map links to the aspect docs; the aspect docs say how they connect to each other. That's what makes the set feel cohesive instead of 8 loose files.
133
+ - Use a small diagram or step-by-step flow wherever it explains things faster than prose - especially for data flow and how an action moves through the system.