ramstack 0.1.1 → 0.2.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 (57) hide show
  1. package/README.md +1 -1
  2. package/agents/ram-agent.md +9 -0
  3. package/cli/ramstack.mjs +225 -54
  4. package/package.json +2 -2
  5. package/skills/automate-me/README.md +1 -1
  6. package/skills/automate-me/SKILL.md +2 -2
  7. package/skills/figure-it-out/SKILL.md +1 -1
  8. package/skills/{poteto-mode → ram-mode}/README.md +4 -4
  9. package/skills/{poteto-mode → ram-mode}/SKILL.md +5 -5
  10. package/skills/ram-mode/agents/openai.yaml +5 -0
  11. package/skills/{poteto-mode → ram-mode}/playbooks/autonomous-run.md +1 -1
  12. package/skills/{poteto-mode → ram-mode}/references/plan.md +4 -4
  13. package/skills/{poteto-mode → ram-mode}/scripts/bootstrap.ts +1 -1
  14. package/skills/{poteto-mode → ram-mode}/scripts/bun.lock +1 -1
  15. package/skills/{poteto-mode → ram-mode}/scripts/package.json +1 -1
  16. package/skills/setup-ramstack/SKILL.md +1 -1
  17. package/agents/poteto-agent.md +0 -9
  18. package/skills/poteto-mode/agents/openai.yaml +0 -5
  19. /package/skills/{poteto-mode → ram-mode}/playbooks/authoring-a-skill.md +0 -0
  20. /package/skills/{poteto-mode → ram-mode}/playbooks/autopilot-full.md +0 -0
  21. /package/skills/{poteto-mode → ram-mode}/playbooks/autopilot-stack.md +0 -0
  22. /package/skills/{poteto-mode → ram-mode}/playbooks/babysit.md +0 -0
  23. /package/skills/{poteto-mode → ram-mode}/playbooks/bug-fix.md +0 -0
  24. /package/skills/{poteto-mode → ram-mode}/playbooks/eval.md +0 -0
  25. /package/skills/{poteto-mode → ram-mode}/playbooks/feature.md +0 -0
  26. /package/skills/{poteto-mode → ram-mode}/playbooks/hillclimb.md +0 -0
  27. /package/skills/{poteto-mode → ram-mode}/playbooks/investigation.md +0 -0
  28. /package/skills/{poteto-mode → ram-mode}/playbooks/multi-phase-plan.md +0 -0
  29. /package/skills/{poteto-mode → ram-mode}/playbooks/opening-a-pr.md +0 -0
  30. /package/skills/{poteto-mode → ram-mode}/playbooks/orchestrate.md +0 -0
  31. /package/skills/{poteto-mode → ram-mode}/playbooks/pause-safely.md +0 -0
  32. /package/skills/{poteto-mode → ram-mode}/playbooks/perf-issue.md +0 -0
  33. /package/skills/{poteto-mode → ram-mode}/playbooks/prototype.md +0 -0
  34. /package/skills/{poteto-mode → ram-mode}/playbooks/refactoring.md +0 -0
  35. /package/skills/{poteto-mode → ram-mode}/playbooks/runtime-forensics.md +0 -0
  36. /package/skills/{poteto-mode → ram-mode}/playbooks/session-pickup.md +0 -0
  37. /package/skills/{poteto-mode → ram-mode}/playbooks/shipping.md +0 -0
  38. /package/skills/{poteto-mode → ram-mode}/playbooks/trace-forensics.md +0 -0
  39. /package/skills/{poteto-mode → ram-mode}/playbooks/visual-parity.md +0 -0
  40. /package/skills/{poteto-mode → ram-mode}/playbooks/worktree-cleanup.md +0 -0
  41. /package/skills/{poteto-mode → ram-mode}/references/bugbot-triage.md +0 -0
  42. /package/skills/{poteto-mode → ram-mode}/scripts/orch/orch.test.ts +0 -0
  43. /package/skills/{poteto-mode → ram-mode}/scripts/orch/orch.ts +0 -0
  44. /package/skills/{poteto-mode → ram-mode}/scripts/orch/store.ts +0 -0
  45. /package/skills/{poteto-mode → ram-mode}/scripts/watch-pr/cli.test.ts +0 -0
  46. /package/skills/{poteto-mode → ram-mode}/scripts/watch-pr/cli.ts +0 -0
  47. /package/skills/{poteto-mode → ram-mode}/scripts/watch-pr/fakes.test-helper.ts +0 -0
  48. /package/skills/{poteto-mode → ram-mode}/scripts/watch-pr/github.test.ts +0 -0
  49. /package/skills/{poteto-mode → ram-mode}/scripts/watch-pr/github.ts +0 -0
  50. /package/skills/{poteto-mode → ram-mode}/scripts/watch-pr/policy.test.ts +0 -0
  51. /package/skills/{poteto-mode → ram-mode}/scripts/watch-pr/policy.ts +0 -0
  52. /package/skills/{poteto-mode → ram-mode}/scripts/watch-pr/render.ts +0 -0
  53. /package/skills/{poteto-mode → ram-mode}/scripts/watch-pr/tsconfig.json +0 -0
  54. /package/skills/{poteto-mode → ram-mode}/scripts/watch-pr/types.compile.ts +0 -0
  55. /package/skills/{poteto-mode → ram-mode}/scripts/watch-pr/types.ts +0 -0
  56. /package/skills/{poteto-mode → ram-mode}/scripts/watch-pr/watch-pr +0 -0
  57. /package/skills/{poteto-mode → ram-mode}/scripts/worktree-audit.sh +0 -0
package/README.md CHANGED
@@ -40,7 +40,7 @@ Understand the design.
40
40
  - [About ramstack](docs/explanation/about-ramstack.md)
41
41
  - [About the pstack port](docs/explanation/about-the-pstack-port.md)
42
42
  - [About model routing](docs/explanation/about-model-routing.md)
43
- - [About poteto-mode](docs/explanation/about-poteto-mode.md)
43
+ - [About ram-mode](docs/explanation/about-ram-mode.md)
44
44
 
45
45
  ## Reference
46
46
 
@@ -0,0 +1,9 @@
1
+ ---
2
+ name: ram-agent
3
+ description: Routing target for `/ram-mode` and any request for that style. Resume an existing `ram-agent` for the conversation rather than spawning a sibling. Reads the `ram-mode` skill's `SKILL.md` in full before any work, including its inline Principles index. Substituting `general-purpose` skips that read and drifts.
4
+ is_background: true
5
+ ---
6
+
7
+ # Ram subagent
8
+
9
+ You are operating in ram-mode. Read the `ram-mode` skill's `SKILL.md` in full before doing any work, including its inline Principles index. Navigate to a leaf `principle-*` skill whenever you apply that principle.
package/cli/ramstack.mjs CHANGED
@@ -11,7 +11,6 @@ import path from 'node:path';
11
11
  import { execFileSync } from 'node:child_process';
12
12
  import { parseArgs } from 'node:util';
13
13
  import { fileURLToPath } from 'node:url';
14
- import readline from 'node:readline/promises';
15
14
 
16
15
  const REPO = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
17
16
  const CONFIG_PATH = path.join(REPO, '.ramstack', 'config.local.json');
@@ -76,9 +75,10 @@ function fail(message) {
76
75
 
77
76
  // ── Wizard ───────────────────────────────────────────────────────────────
78
77
  // An interactive run on a terminal gets the wizard treatment: a banner, one
79
- // stage per step, a confirm gate before anything changes, and a closing
80
- // summary. A run with --yes, or without a terminal, keeps the plain tag
81
- // output and never prompts.
78
+ // stage per step, arrow-key selectors (multi-select for hosts), a confirm
79
+ // gate before anything changes, and a closing summary. Project scope uses
80
+ // the current directory. A run with --yes, or without a terminal, keeps the
81
+ // plain tag output and never prompts.
82
82
 
83
83
  const COLOR =
84
84
  Boolean(process.stdout.isTTY) && process.env.NO_COLOR === undefined && process.env.TERM !== 'dumb';
@@ -88,11 +88,188 @@ const C = COLOR
88
88
 
89
89
  let stageTotal = 0;
90
90
  let stageIndex = 0;
91
- let rl = null;
91
+ let wizardIo = false;
92
+
93
+ function restoreTty() {
94
+ if (process.stdin.isTTY && typeof process.stdin.setRawMode === 'function') {
95
+ try {
96
+ process.stdin.setRawMode(false);
97
+ } catch {
98
+ // stdin may already be closed on the way out
99
+ }
100
+ }
101
+ if (process.stdout.isTTY) process.stdout.write('\x1b[?25h');
102
+ }
103
+
104
+ function startWizardIo() {
105
+ process.stdin.setRawMode(true);
106
+ process.stdin.resume();
107
+ process.stdin.setEncoding('utf8');
108
+ wizardIo = true;
109
+ }
110
+
111
+ function stopWizardIo() {
112
+ if (!wizardIo) return;
113
+ wizardIo = false;
114
+ restoreTty();
115
+ process.stdin.pause();
116
+ }
117
+
118
+ process.on('exit', restoreTty);
119
+
120
+ function decodeChunk(data) {
121
+ return typeof data === 'string' ? data : String(data);
122
+ }
123
+
124
+ function readChunk() {
125
+ return new Promise((resolve) => {
126
+ if (process.stdin.readableEnded) {
127
+ resolve('\x04');
128
+ return;
129
+ }
130
+ const onData = (data) => {
131
+ process.stdin.off('end', onEnd);
132
+ resolve(decodeChunk(data));
133
+ };
134
+ const onEnd = () => {
135
+ process.stdin.off('data', onData);
136
+ resolve('\x04');
137
+ };
138
+ process.stdin.once('data', onData);
139
+ process.stdin.once('end', onEnd);
140
+ });
141
+ }
142
+
143
+ function readChunkTimeout(ms) {
144
+ return new Promise((resolve) => {
145
+ const timer = setTimeout(() => {
146
+ process.stdin.off('data', onData);
147
+ resolve(null);
148
+ }, ms);
149
+ const onData = (data) => {
150
+ clearTimeout(timer);
151
+ resolve(decodeChunk(data));
152
+ };
153
+ process.stdin.once('data', onData);
154
+ });
155
+ }
156
+
157
+ async function readKey() {
158
+ let chunk = await readChunk();
159
+ if (chunk === '\x1b' || chunk === '\x1b[' || chunk === '\x1bO') {
160
+ const rest = await readChunkTimeout(30);
161
+ if (rest) chunk += rest;
162
+ }
163
+ if (chunk === '\x1b[A' || chunk === '\x1bOA' || chunk === 'k') return 'up';
164
+ if (chunk === '\x1b[B' || chunk === '\x1bOB' || chunk === 'j') return 'down';
165
+ if (chunk === '\r' || chunk === '\n') return 'enter';
166
+ if (chunk === ' ') return 'space';
167
+ if (chunk === '\x03' || chunk === '\x04' || chunk === '\x1b' || chunk === 'q') return 'cancel';
168
+ return 'other';
169
+ }
170
+
171
+ function cancelWizard() {
172
+ restoreTty();
173
+ fail('\nerror: cancelled.');
174
+ }
175
+
176
+ async function pause(message) {
177
+ process.stdout.write(` ${C.dim}${message}${C.reset}`);
178
+ for (;;) {
179
+ const key = await readKey();
180
+ if (key === 'enter') break;
181
+ if (key === 'cancel') cancelWizard();
182
+ }
183
+ process.stdout.write('\n');
184
+ }
92
185
 
93
- function getRl() {
94
- rl ??= readline.createInterface({ input: process.stdin, output: process.stdout });
95
- return rl;
186
+ async function select({ message, options, multiple = false, initial, emptyError }) {
187
+ const known = new Set(options.map((opt) => opt.value));
188
+ const chosen = new Set();
189
+ if (multiple) {
190
+ for (const value of initial ?? []) {
191
+ if (known.has(value)) chosen.add(value);
192
+ }
193
+ } else {
194
+ const start = known.has(initial) ? initial : options[0]?.value;
195
+ if (start !== undefined) chosen.add(start);
196
+ }
197
+
198
+ let index = Math.max(
199
+ 0,
200
+ options.findIndex((opt) => chosen.has(opt.value)),
201
+ );
202
+ let error = '';
203
+ let rendered = 0;
204
+ process.stdout.write('\x1b[?25l');
205
+
206
+ const paint = () => {
207
+ const help = multiple
208
+ ? '↑/↓ move · space toggle · enter confirm'
209
+ : '↑/↓ move · enter choose';
210
+ const rows = [` ${message}`, ` ${C.dim}${help}${C.reset}`, ''];
211
+ const labelWidth = options.some((opt) => opt.hint)
212
+ ? Math.max(...options.map((opt) => opt.label.length))
213
+ : 0;
214
+ for (const [i, opt] of options.entries()) {
215
+ const on = chosen.has(opt.value);
216
+ const pointer = i === index ? `${C.blue}❯${C.reset}` : ' ';
217
+ const mark = on ? `${C.green}●${C.reset}` : '○';
218
+ const label = opt.label.padEnd(labelWidth);
219
+ const hint = opt.hint ? ` ${C.dim}${opt.hint}${C.reset}` : '';
220
+ rows.push(` ${pointer} ${multiple ? `${mark} ` : ''}${label}${hint}`);
221
+ }
222
+ if (error) rows.push('', ` ${C.yellow}${error}${C.reset}`);
223
+ const text = rows.join('\n');
224
+ if (rendered > 0) process.stdout.write(`\x1b[${rendered}A\r\x1b[J`);
225
+ process.stdout.write(`${text}\n`);
226
+ rendered = text.split('\n').length;
227
+ };
228
+
229
+ const collapse = (summary) => {
230
+ process.stdout.write(`\x1b[${rendered}A\r\x1b[J`);
231
+ process.stdout.write(` ${message} ${C.green}${summary}${C.reset}\n`);
232
+ process.stdout.write('\x1b[?25h');
233
+ };
234
+
235
+ console.log('');
236
+ paint();
237
+ for (;;) {
238
+ const key = await readKey();
239
+ if (key === 'cancel') cancelWizard();
240
+ if (key === 'up') {
241
+ index = (index + options.length - 1) % options.length;
242
+ paint();
243
+ continue;
244
+ }
245
+ if (key === 'down') {
246
+ index = (index + 1) % options.length;
247
+ paint();
248
+ continue;
249
+ }
250
+ if (key === 'space' && multiple) {
251
+ const value = options[index].value;
252
+ if (chosen.has(value)) chosen.delete(value);
253
+ else chosen.add(value);
254
+ error = '';
255
+ paint();
256
+ continue;
257
+ }
258
+ if (key === 'enter') {
259
+ if (!multiple) {
260
+ collapse(options[index].label);
261
+ return options[index].value;
262
+ }
263
+ if (chosen.size === 0) {
264
+ error = emptyError ?? 'select at least one option';
265
+ paint();
266
+ continue;
267
+ }
268
+ const values = options.filter((opt) => chosen.has(opt.value)).map((opt) => opt.value);
269
+ collapse(values.join(', '));
270
+ return values;
271
+ }
272
+ }
96
273
  }
97
274
 
98
275
  async function banner(title) {
@@ -101,7 +278,7 @@ async function banner(title) {
101
278
  console.log(`${C.dim} ${stageTotal} stages${C.reset}\n`);
102
279
  console.log(`${C.dim} The installer shows each step before it runs. Stop any time with${C.reset}`);
103
280
  console.log(`${C.dim} Ctrl-C and re-run later. Saved choices become the defaults.${C.reset}\n`);
104
- await getRl().question(` ${C.dim}Ready to start? [Enter]${C.reset} `);
281
+ await pause('Ready to start? [Enter]');
105
282
  }
106
283
 
107
284
  function stage(name) {
@@ -115,10 +292,15 @@ function note(message) {
115
292
  }
116
293
 
117
294
  async function confirm(question) {
118
- const answer = (await getRl().question(` ${C.yellow}? ${question} [y/N]${C.reset} `))
119
- .trim()
120
- .toLowerCase();
121
- return answer === 'y' || answer === 'yes';
295
+ const answer = await select({
296
+ message: question,
297
+ options: [
298
+ { value: 'no', label: 'No' },
299
+ { value: 'yes', label: 'Yes' },
300
+ ],
301
+ initial: 'no',
302
+ });
303
+ return answer === 'yes';
122
304
  }
123
305
 
124
306
  function finish(headline, notes = []) {
@@ -317,40 +499,33 @@ function gitPull() {
317
499
 
318
500
  async function promptHosts(defaults) {
319
501
  const detected = detectHosts();
320
- console.log('');
321
- console.log(' Detected hosts:');
322
- for (const name of HOST_NAMES) {
323
- const hit = detected.includes(name);
324
- const where = hit ? path.join(os.homedir(), HOSTS[name].marker) : `no ~/${HOSTS[name].marker}`;
325
- console.log(` ${hit ? 'found' : ' - '} ${name.padEnd(11)} ${where}`);
326
- }
327
- console.log('');
328
- const answer = (
329
- await getRl().question(` Install for ${defaults.join(', ')}? [Y/n/list] `)
330
- ).trim().toLowerCase();
331
- if (answer === '' || answer === 'y' || answer === 'yes') return defaults;
332
- const list =
333
- answer === 'n' || answer === 'no' || answer === 'list'
334
- ? await getRl().question(` Hosts (comma-separated: ${HOST_NAMES.join(', ')}): `)
335
- : answer;
336
- const hosts = parseHosts(list);
337
- if (hosts.length === 0) fail('error: no hosts selected.');
338
- return hosts;
502
+ const initial = defaults.filter((name) => HOST_NAMES.includes(name));
503
+ return select({
504
+ message: 'Hosts',
505
+ multiple: true,
506
+ emptyError: 'select at least one host',
507
+ initial: initial.length ? initial : detectedOrAll(),
508
+ options: HOST_NAMES.map((name) => {
509
+ const hit = detected.includes(name);
510
+ const marker = HOSTS[name].marker;
511
+ return {
512
+ value: name,
513
+ label: name,
514
+ hint: hit ? `found ~/${marker}` : `no ~/${marker}`,
515
+ };
516
+ }),
517
+ });
339
518
  }
340
519
 
341
520
  async function promptScope(defaultScope) {
342
- const answer = (
343
- await getRl().question(` Scope: global (all projects) or project (one directory)? [${defaultScope}] `)
344
- ).trim().toLowerCase();
345
- if (answer === '') return defaultScope;
346
- if (answer === 'g') return 'global';
347
- if (answer === 'p') return 'project';
348
- return parseScope(answer);
349
- }
350
-
351
- async function promptProjectDir(defaultDir) {
352
- const answer = (await getRl().question(` Project directory? [${defaultDir}] `)).trim();
353
- return answer ? path.resolve(answer) : defaultDir;
521
+ return select({
522
+ message: 'Scope',
523
+ initial: defaultScope === 'project' ? 'project' : 'global',
524
+ options: [
525
+ { value: 'global', label: 'global', hint: 'home directory, all projects' },
526
+ { value: 'project', label: 'project', hint: `this directory, ${process.cwd()}` },
527
+ ],
528
+ });
354
529
  }
355
530
 
356
531
  function showPlan(hosts, scope, base, clone) {
@@ -409,9 +584,10 @@ async function main() {
409
584
  const saved = readConfig(clone);
410
585
  let hosts = values.hosts ? parseHosts(values.hosts) : null;
411
586
  let scope = values.scope ? parseScope(values.scope) : null;
412
- const wizard = !values.yes && process.stdout.isTTY;
587
+ const wizard = !values.yes && process.stdout.isTTY && process.stdin.isTTY;
413
588
 
414
589
  try {
590
+ if (wizard) startWizardIo();
415
591
  if (command === 'install') {
416
592
  if (wizard) {
417
593
  stageTotal = 2 + (hosts ? 0 : 1) + (scope ? 0 : 1);
@@ -420,15 +596,11 @@ async function main() {
420
596
  stage('Hosts');
421
597
  hosts = await promptHosts(saved?.hosts ?? detectedOrAll());
422
598
  }
423
- let projectDir = values['project-dir'] ?? saved?.projectDir;
424
599
  if (!scope) {
425
600
  stage('Scope');
426
601
  scope = await promptScope(saved?.scope ?? 'global');
427
- if (scope === 'project' && !values['project-dir']) {
428
- projectDir = await promptProjectDir(saved?.projectDir ?? process.cwd());
429
- }
430
602
  }
431
- const base = resolveBase(scope, projectDir);
603
+ const base = resolveBase(scope, values['project-dir']);
432
604
  stage('Review');
433
605
  showPlan(hosts, scope, base, clone);
434
606
  if (values.force) note('--force is on: a conflicting real file moves to <name>.bak first.');
@@ -448,7 +620,7 @@ async function main() {
448
620
  }
449
621
  hosts ??= detectedOrAll();
450
622
  scope ??= 'global';
451
- const base = resolveBase(scope, values['project-dir'] ?? saved?.projectDir);
623
+ const base = resolveBase(scope, values['project-dir']);
452
624
  if (!clone) syncStore();
453
625
  const counts = runLink(hosts, base, values.force, src);
454
626
  if (clone) configureGitHooks();
@@ -528,11 +700,10 @@ async function main() {
528
700
  runUnlink(hosts, base, src);
529
701
  say('done', `links removed for ${hosts.join(', ')} (${scope})`);
530
702
  } catch (error) {
531
- // Ctrl+D at a prompt rejects with AbortError; Ctrl+C never reaches here.
532
- if (error?.code === 'ABORT_ERR') fail('\nerror: cancelled.');
703
+ restoreTty();
533
704
  throw error;
534
705
  } finally {
535
- rl?.close();
706
+ stopWizardIo();
536
707
  }
537
708
  }
538
709
 
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "ramstack",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Agent skills for Claude Code, Codex, and pi",
5
- "author": "Justin Ramos <justinramos@outlook.com>",
5
+ "author": "Justin Ramos",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",
@@ -14,7 +14,7 @@ A `<handle>-mode/SKILL.md` skill file that encodes your response preferences, de
14
14
 
15
15
  ## How it works
16
16
 
17
- The skill mines recent agent transcripts in parallel slices for recurring patterns, asks you structured questions to fill gaps the mining missed, clusters findings into sections, drafts the skill (using the host's skill-authoring skill when available), and iterates on prose with the `unslop` skill. Patterns need 2+ independent sightings before they get codified. The `poteto-mode` skill serves as the reference shape.
17
+ The skill mines recent agent transcripts in parallel slices for recurring patterns, asks you structured questions to fill gaps the mining missed, clusters findings into sections, drafts the skill (using the host's skill-authoring skill when available), and iterates on prose with the `unslop` skill. Patterns need 2+ independent sightings before they get codified. The `ram-mode` skill serves as the reference shape.
18
18
 
19
19
  ## Related
20
20
 
@@ -60,7 +60,7 @@ Group the combined signals into sections. Common ones (use only what applies):
60
60
  - **Process**: git worktrees, commits, PRs, review/merge tooling.
61
61
  - **Skills**: skill-authoring habits, fix-the-skill-first, proposing new skills.
62
62
 
63
- The **poteto-mode** skill shows the shape. Read it for granularity. Don't copy its content; the user's rules are not the same as poteto-mode's.
63
+ The **ram-mode** skill shows the shape. Read it for granularity. Don't copy its content; the user's rules are not the same as ram-mode's.
64
64
 
65
65
  ### 4. Draft the skill
66
66
 
@@ -104,6 +104,6 @@ Run a description-optimization loop only if the skill's trigger accuracy turns o
104
104
 
105
105
  ## Reference files
106
106
 
107
- - The **poteto-mode** skill: example of the output shape.
107
+ - The **ram-mode** skill: example of the output shape.
108
108
  - The **unslop** skill: prose discipline for every line.
109
109
  - The host's skill-authoring skill (when installed): skill authoring process and writing guidelines.
@@ -12,7 +12,7 @@ Don't reinvent a playbook you already have. A focused single-unit task that matc
12
12
 
13
13
  ## Start
14
14
 
15
- Open a todolist whose first item is to read the Principles section of the **poteto-mode** skill. Then add the phases below as todos.
15
+ Open a todolist whose first item is to read the Principles section of the **ram-mode** skill. Then add the phases below as todos.
16
16
 
17
17
  ## Phase A: Frame
18
18
 
@@ -1,10 +1,10 @@
1
- # Poteto mode
1
+ # Ram mode
2
2
 
3
3
  Opt-in rigor wrapper. Matches a task to a playbook, cites engineering principles, routes bulk work to subagents, and keeps the parent agent in the lead.
4
4
 
5
5
  ## When to use
6
6
 
7
- - `/poteto-mode` or "poteto"
7
+ - `/ram-mode` or "ram-mode"
8
8
  - Any task that needs structured rigor: features, bug fixes, investigations, refactoring, shipping
9
9
 
10
10
  ## What it produces
@@ -13,7 +13,7 @@ A todolist driven by the matched playbook's steps, principle citations tied to r
13
13
 
14
14
  ## How it works
15
15
 
16
- The mode matches the task to one of 23 bundled playbooks (feature, bug fix, investigation, refactoring, and others). The playbook's steps become the todolist verbatim. Principles from the index are read as leaf skills and cited only when they change a real choice. Code-writing steps go to `poteto-agent` subagents. Review panels use the configured models. The parent reviews every diff and writes its own summary.
16
+ The mode matches the task to one of 23 bundled playbooks (feature, bug fix, investigation, refactoring, and others). The playbook's steps become the todolist verbatim. Principles from the index are read as leaf skills and cited only when they change a real choice. Code-writing steps go to `ram-agent` subagents. Review panels use the configured models. The parent reviews every diff and writes its own summary.
17
17
 
18
18
  The mode is opt-in. `disable-model-invocation: true` prevents the host from applying it to prompts that just look similar.
19
19
 
@@ -22,5 +22,5 @@ The mode is opt-in. `disable-model-invocation: true` prevents the host from appl
22
22
  - [SKILL.md](SKILL.md)
23
23
  - [playbooks/](playbooks/) (23 playbook files)
24
24
  - [references/](references/) (bugbot triage, plan template)
25
- - [About poteto-mode](../../docs/explanation/about-poteto-mode.md)
25
+ - [About ram-mode](../../docs/explanation/about-ram-mode.md)
26
26
  - [Playbooks reference](../../docs/reference/playbooks.md)
@@ -1,14 +1,14 @@
1
1
  ---
2
- name: poteto-mode
3
- description: poteto's agent style for concise, detailed responses, deliberate subagents, unslopped prose, simple code, and verified work. Use for poteto, /poteto-mode, or requests to work in this style.
2
+ name: ram-mode
3
+ description: Ram-mode agent style for concise, detailed responses, deliberate subagents, unslopped prose, simple code, and verified work. Use for ram-mode, /ram-mode, or requests to work in this style.
4
4
  disable-model-invocation: true
5
5
  mode: true
6
6
  icon: crown
7
7
  color: yellow
8
- reminder: New task? Playbook match or rigor needed -> apply /poteto-mode. Casual turn or user opts out -> don't.
8
+ reminder: New task? Playbook match or rigor needed -> apply /ram-mode. Casual turn or user opts out -> don't.
9
9
  ---
10
10
 
11
- # Poteto mode
11
+ # Ram mode
12
12
 
13
13
  ## Non-negotiables
14
14
 
@@ -86,7 +86,7 @@ Read the leaf skill in full for any principle you apply. Each entry names when i
86
86
 
87
87
  ## Subagents
88
88
 
89
- **Use `subagent_type: "poteto-agent"` for any subagent you spawn inside a playbook step** (code-writing delegates, ad-hoc helpers). `/poteto-mode` and `poteto-agent` route through the same wrapper. Routed workflow skills (`how`, `why`, `interrogate`, `reflect`, `swarm`) set their own `subagent_type` for diverse-model review; respect what the skill prescribes, don't override to `poteto-agent`.
89
+ **Use `subagent_type: "ram-agent"` for any subagent you spawn inside a playbook step** (code-writing delegates, ad-hoc helpers). `/ram-mode` and `ram-agent` route through the same wrapper. Routed workflow skills (`how`, `why`, `interrogate`, `reflect`, `swarm`) set their own `subagent_type` for diverse-model review; respect what the skill prescribes, don't override to `ram-agent`.
90
90
 
91
91
  **Defaults for every subagent call.** Run in the background when the host supports it, file pointers not inlined context, explicit model per role (configurable via `/setup-ramstack`; defaults `sonnet` for code, `fable` for prose and judgment). Code delegates tier by difficulty. The hardest changes (cross-cutting design, gnarly concurrency, subtle algorithms) go to your strongest judgment model (`fable`) when the task needs judgment or the intent is vague, and to your strongest instruction-following model (`opus`) when the work is a precisely specified sequence of steps to execute to the letter; trivial mechanical edits go to your fast code model. Per-role lines in your host's section of the `/setup-ramstack` config (`~/.agents/ramstack-models.md`) override these defaults and the model choices in the routed skills (`how`, `why`, `arena`, `swarm`, `architect`, `interrogate`, `reflect`); a role with no line keeps its default, and a role line of `inherit-parent` or `auto` runs that role on the parent chat model (omit the subagent `model` param).
92
92
 
@@ -0,0 +1,5 @@
1
+ interface:
2
+ display_name: "Ram Mode"
3
+ short_description: "Rigorous ram-mode working style"
4
+ policy:
5
+ allow_implicit_invocation: false
@@ -6,7 +6,7 @@
6
6
  2. Pick the wake mechanism using the host's `/loop` command when it has one (a built-in, not a ramstack skill). An event to watch (CI, a merge, a ref advancing) gets a watcher subagent that wakes you on the event, with a long time-based heartbeat as fallback. No event gets a fixed-interval heartbeat sized to when the result is worth re-checking.
7
7
  3. Each iteration makes the smallest change the evidence justifies, verifies it against the predicate, commits if it advanced, discards changes that didn't help. Belt-and-suspenders that "might help" gets reverted, not left to ride.
8
8
  Sequence the work via the **sequence-verifiable-units** principle skill, verifying each unit before the next instead of batching checks at the end.
9
- 4. Mid-run discoveries are yours. Address broken skills, related bugs, flaky verifiers, review noise, tooling failures, orphaned follow-ups, and fixable drift yourself via poteto-mode. Put out-of-band fixes in their own PR. Do not park reversible work for the human or use `AskUserQuestion`. Surface only irreversible actions, genuine product or preference calls no experiment can settle, or a real dead end. Keep the predicate as the main drive, and return to it after each side fix.
9
+ 4. Mid-run discoveries are yours. Address broken skills, related bugs, flaky verifiers, review noise, tooling failures, orphaned follow-ups, and fixable drift yourself via ram-mode. Put out-of-band fixes in their own PR. Do not park reversible work for the human or use `AskUserQuestion`. Surface only irreversible actions, genuine product or preference calls no experiment can settle, or a real dead end. Keep the predicate as the main drive, and return to it after each side fix.
10
10
  5. Checkpoint every iteration via the **show-me-your-work** skill, a row for what changed and whether the predicate moved. A run with no trail can't be audited or resumed.
11
11
  6. Stop when the predicate is met. A plateau is not a stop, so keep going and pivot your approach to push past it. Surface a genuine dead end rather than spinning, and never relax the predicate to declare victory.
12
12
 
@@ -1,6 +1,6 @@
1
1
  # Plan
2
2
 
3
- Produce a phased implementation plan grounded in the **Principles** section of the `poteto-mode` skill. The plan is the deliverable. Do not implement.
3
+ Produce a phased implementation plan grounded in the **Principles** section of the `ram-mode` skill. The plan is the deliverable. Do not implement.
4
4
 
5
5
  Open a todolist with one item per step below.
6
6
 
@@ -12,7 +12,7 @@ Plan when the change spans three or more files, introduces architecture, has com
12
12
 
13
13
  ## 1. Re-read principles
14
14
 
15
- Read the **Principles** section of the `poteto-mode` skill end to end, and the leaf `principle-*` skills it indexes. The principles govern every plan decision; cross-link them.
15
+ Read the **Principles** section of the `ram-mode` skill end to end, and the leaf `principle-*` skills it indexes. The principles govern every plan decision; cross-link them.
16
16
 
17
17
  ## 2. Scope and constraints
18
18
 
@@ -24,7 +24,7 @@ Resolve what is in scope vs explicitly out, technical or platform constraints, p
24
24
 
25
25
  Delegate codebase exploration (the **guard-the-context-window** principle skill).
26
26
 
27
- - Prefer `subagent_type: "poteto-agent"`. `general-purpose` is the fallback. Never use the built-in `plan` subagent_type; it ignores this skill.
27
+ - Prefer `subagent_type: "ram-agent"`. `general-purpose` is the fallback. Never use the built-in `plan` subagent_type; it ignores this skill.
28
28
  - Pass `model:` explicitly per the configured roles (defaults `sonnet` for code, `fable` for judgment).
29
29
 
30
30
  Each explorer returns file pointers, conventions, dependencies, test infrastructure, and entry points. No inlined dumps.
@@ -92,7 +92,7 @@ For bug fixes, the loop is reproduce on the surface, fix, verify on the same sur
92
92
 
93
93
  ## 6. Implementation guidance
94
94
 
95
- In the overview, name which poteto-mode non-negotiables the implementer must apply, by name:
95
+ In the overview, name which ram-mode non-negotiables the implementer must apply, by name:
96
96
 
97
97
  - the **how** skill over each unfamiliar subsystem before changing it.
98
98
  - the **interrogate** skill for adversarial review on contested designs before shipping.
@@ -11,7 +11,7 @@ const commanderPackagePath = join(
11
11
  );
12
12
  const installKeyPath = join(
13
13
  nodeModulesDirectory,
14
- ".poteto-mode-tools-install-key"
14
+ ".ram-mode-tools-install-key"
15
15
  );
16
16
 
17
17
  function currentInstallKey(): string {
@@ -3,7 +3,7 @@
3
3
  "configVersion": 1,
4
4
  "workspaces": {
5
5
  "": {
6
- "name": "@cursor-skill/poteto-mode-tools",
6
+ "name": "@ramstack/ram-mode-tools",
7
7
  "dependencies": {
8
8
  "commander": "14.0.0",
9
9
  },
@@ -1,5 +1,5 @@
1
1
  {
2
- "name": "@ramstack/poteto-mode-tools",
2
+ "name": "@ramstack/ram-mode-tools",
3
3
  "private": true,
4
4
  "type": "module",
5
5
  "scripts": {
@@ -37,7 +37,7 @@ Every real slug written must be in the detected set; `inherit-parent` and `auto`
37
37
 
38
38
  ### 5. Write the config
39
39
 
40
- Rewrite this host's `## <host>` section of `~/.agents/ramstack-models.md` with one line per role, using the same labels poteto-mode uses. Preserve every other host's section byte for byte; create the file with the header comment below if it doesn't exist. Re-runs stay idempotent by replacing the whole section.
40
+ Rewrite this host's `## <host>` section of `~/.agents/ramstack-models.md` with one line per role, using the same labels ram-mode uses. Preserve every other host's section byte for byte; create the file with the header comment below if it doesn't exist. Re-runs stay idempotent by replacing the whole section.
41
41
 
42
42
  Shape, with the Claude Code defaults filled in (another host substitutes its own detected slugs under its own heading, keeping the same roles):
43
43
 
@@ -1,9 +0,0 @@
1
- ---
2
- name: poteto-agent
3
- description: Routing target for `/poteto-mode` and any request for poteto's style. Resume an existing `poteto-agent` for the conversation rather than spawning a sibling. Reads the `poteto-mode` skill's `SKILL.md` in full before any work, including its inline Principles index. Substituting `general-purpose` skips that read and drifts.
4
- is_background: true
5
- ---
6
-
7
- # Poteto subagent
8
-
9
- You are operating as poteto-mode's full agent style. Read the `poteto-mode` skill's `SKILL.md` in full before doing any work, including its inline Principles index. Navigate to a leaf `principle-*` skill whenever you apply that principle.
@@ -1,5 +0,0 @@
1
- interface:
2
- display_name: "Poteto Mode"
3
- short_description: "poteto's rigorous agent working style"
4
- policy:
5
- allow_implicit_invocation: false