potetos-for-everyone 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/.agents/plugins/marketplace.json +21 -0
  2. package/.claude-plugin/marketplace.json +32 -0
  3. package/.claude-plugin/plugin.json +36 -0
  4. package/.codex-plugin/plugin.json +13 -0
  5. package/.codex-plugin/prompts/architect.md +6 -0
  6. package/.codex-plugin/prompts/arena.md +6 -0
  7. package/.codex-plugin/prompts/automate-me.md +6 -0
  8. package/.codex-plugin/prompts/blast-radius.md +6 -0
  9. package/.codex-plugin/prompts/bro.md +6 -0
  10. package/.codex-plugin/prompts/create-verification-skill.md +6 -0
  11. package/.codex-plugin/prompts/figure-it-out.md +6 -0
  12. package/.codex-plugin/prompts/how.md +6 -0
  13. package/.codex-plugin/prompts/interrogate.md +6 -0
  14. package/.codex-plugin/prompts/maintain-verification-skill.md +6 -0
  15. package/.codex-plugin/prompts/make-bot-ui.md +6 -0
  16. package/.codex-plugin/prompts/no-comments.md +6 -0
  17. package/.codex-plugin/prompts/poteto-mode.md +6 -0
  18. package/.codex-plugin/prompts/recall.md +6 -0
  19. package/.codex-plugin/prompts/reflect.md +6 -0
  20. package/.codex-plugin/prompts/setup-pstack.md +6 -0
  21. package/.codex-plugin/prompts/show-me-your-work.md +6 -0
  22. package/.codex-plugin/prompts/swarm.md +6 -0
  23. package/.codex-plugin/prompts/tdd.md +6 -0
  24. package/.codex-plugin/prompts/teach.md +6 -0
  25. package/.codex-plugin/prompts/technical-writing.md +6 -0
  26. package/.codex-plugin/prompts/typescript-best-practices.md +6 -0
  27. package/.codex-plugin/prompts/unslop.md +6 -0
  28. package/.codex-plugin/prompts/why.md +6 -0
  29. package/AGENTS.md +11 -0
  30. package/LICENSE +22 -0
  31. package/NOTICE.md +17 -0
  32. package/PORTABILITY.md +29 -0
  33. package/README.md +483 -0
  34. package/UPSTREAM.json +9 -0
  35. package/UPSTREAM_INVENTORY.json +13 -0
  36. package/VERSION +1 -0
  37. package/adapters/README.md +9 -0
  38. package/adapters/registry.json +46 -0
  39. package/agents/comment-reviewer.md +3 -0
  40. package/agents/comment-sicko.md +31 -0
  41. package/agents/poteto-agent.md +14 -0
  42. package/assets/logo.png +0 -0
  43. package/automations/benny/FOR_AGENTS.md +5 -0
  44. package/automations/benny/README.md +10 -0
  45. package/automations/benny/skills/reproduce-and-fix-issues/SKILL.md +12 -0
  46. package/automations/benny/skills/triage-issue-reports/SKILL.md +11 -0
  47. package/automations/benny/templates/configuration.example.yaml +11 -0
  48. package/automations/benny/templates/reproduce-automation-prompt.md +1 -0
  49. package/automations/benny/templates/triage-automation-prompt.md +1 -0
  50. package/bin/potetos +547 -0
  51. package/docs/.nojekyll +0 -0
  52. package/docs/guide/01-setup.md +25 -0
  53. package/docs/guide/02-poteto-mode.md +11 -0
  54. package/docs/guide/03-understand.md +5 -0
  55. package/docs/guide/04-design.md +5 -0
  56. package/docs/guide/05-build-and-clean.md +5 -0
  57. package/docs/guide/06-verify-and-ship.md +5 -0
  58. package/docs/guide/07-overnight.md +5 -0
  59. package/docs/guide/08-principles.md +5 -0
  60. package/docs/guide/09-make-it-yours.md +5 -0
  61. package/docs/guide/10-recipes-and-pitfalls.md +8 -0
  62. package/docs/guide/README.md +16 -0
  63. package/docs/index.html +422 -0
  64. package/hooks/hooks.json +17 -0
  65. package/hooks/session-start-context.md +11 -0
  66. package/npm/core.mjs +318 -0
  67. package/npm/postinstall.mjs +22 -0
  68. package/npm/potetos.mjs +145 -0
  69. package/package.json +98 -0
  70. package/runtime/README.md +21 -0
  71. package/runtime/__init__.py +1 -0
  72. package/runtime/capabilities.json +36 -0
  73. package/runtime/config.example.json +17 -0
  74. package/runtime/runner.py +240 -0
  75. package/skills/architect/SKILL.md +14 -0
  76. package/skills/arena/SKILL.md +14 -0
  77. package/skills/automate-me/SKILL.md +11 -0
  78. package/skills/blast-radius/SKILL.md +11 -0
  79. package/skills/bro/SKILL.md +7 -0
  80. package/skills/create-verification-skill/SKILL.md +11 -0
  81. package/skills/figure-it-out/SKILL.md +13 -0
  82. package/skills/how/SKILL.md +14 -0
  83. package/skills/interrogate/SKILL.md +14 -0
  84. package/skills/maintain-verification-skill/SKILL.md +11 -0
  85. package/skills/make-bot-ui/SKILL.md +11 -0
  86. package/skills/no-comments/SKILL.md +11 -0
  87. package/skills/poteto-mode/SKILL.md +93 -0
  88. package/skills/poteto-mode/playbooks/authoring-a-skill.md +7 -0
  89. package/skills/poteto-mode/playbooks/autonomous-run.md +7 -0
  90. package/skills/poteto-mode/playbooks/autopilot-full.md +7 -0
  91. package/skills/poteto-mode/playbooks/autopilot-stack.md +7 -0
  92. package/skills/poteto-mode/playbooks/babysit.md +7 -0
  93. package/skills/poteto-mode/playbooks/bug-fix.md +8 -0
  94. package/skills/poteto-mode/playbooks/eval.md +7 -0
  95. package/skills/poteto-mode/playbooks/feature.md +8 -0
  96. package/skills/poteto-mode/playbooks/hillclimb.md +8 -0
  97. package/skills/poteto-mode/playbooks/investigation.md +7 -0
  98. package/skills/poteto-mode/playbooks/multi-phase-plan.md +7 -0
  99. package/skills/poteto-mode/playbooks/opening-a-pr.md +7 -0
  100. package/skills/poteto-mode/playbooks/orchestrate.md +8 -0
  101. package/skills/poteto-mode/playbooks/pause-safely.md +7 -0
  102. package/skills/poteto-mode/playbooks/perf-issue.md +8 -0
  103. package/skills/poteto-mode/playbooks/prototype.md +7 -0
  104. package/skills/poteto-mode/playbooks/refactoring.md +7 -0
  105. package/skills/poteto-mode/playbooks/runtime-forensics.md +7 -0
  106. package/skills/poteto-mode/playbooks/session-pickup.md +7 -0
  107. package/skills/poteto-mode/playbooks/shipping.md +7 -0
  108. package/skills/poteto-mode/playbooks/trace-forensics.md +7 -0
  109. package/skills/poteto-mode/playbooks/visual-parity.md +7 -0
  110. package/skills/poteto-mode/playbooks/worktree-cleanup.md +7 -0
  111. package/skills/principle-attack-the-premise/SKILL.md +20 -0
  112. package/skills/principle-boundary-discipline/SKILL.md +20 -0
  113. package/skills/principle-build-the-lever/SKILL.md +20 -0
  114. package/skills/principle-encode-lessons-in-structure/SKILL.md +20 -0
  115. package/skills/principle-exhaust-the-design-space/SKILL.md +20 -0
  116. package/skills/principle-experience-first/SKILL.md +20 -0
  117. package/skills/principle-fix-root-causes/SKILL.md +20 -0
  118. package/skills/principle-foundational-thinking/SKILL.md +20 -0
  119. package/skills/principle-guard-the-context-window/SKILL.md +20 -0
  120. package/skills/principle-laziness-protocol/SKILL.md +20 -0
  121. package/skills/principle-make-operations-idempotent/SKILL.md +20 -0
  122. package/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md +20 -0
  123. package/skills/principle-minimize-reader-load/SKILL.md +20 -0
  124. package/skills/principle-model-the-domain/SKILL.md +20 -0
  125. package/skills/principle-never-block-on-the-human/SKILL.md +20 -0
  126. package/skills/principle-outcome-oriented-execution/SKILL.md +20 -0
  127. package/skills/principle-prove-it-works/SKILL.md +20 -0
  128. package/skills/principle-redesign-from-first-principles/SKILL.md +20 -0
  129. package/skills/principle-separate-before-serializing-shared-state/SKILL.md +20 -0
  130. package/skills/principle-sequence-verifiable-units/SKILL.md +20 -0
  131. package/skills/principle-subtract-before-you-add/SKILL.md +20 -0
  132. package/skills/principle-test-behavior-not-implementation/SKILL.md +20 -0
  133. package/skills/principle-type-system-discipline/SKILL.md +20 -0
  134. package/skills/recall/SKILL.md +13 -0
  135. package/skills/reflect/SKILL.md +11 -0
  136. package/skills/setup-pstack/SKILL.md +12 -0
  137. package/skills/show-me-your-work/SKILL.md +17 -0
  138. package/skills/swarm/SKILL.md +12 -0
  139. package/skills/tdd/SKILL.md +12 -0
  140. package/skills/teach/SKILL.md +11 -0
  141. package/skills/technical-writing/SKILL.md +12 -0
  142. package/skills/typescript-best-practices/SKILL.md +14 -0
  143. package/skills/unslop/SKILL.md +11 -0
  144. package/skills/why/SKILL.md +14 -0
package/npm/core.mjs ADDED
@@ -0,0 +1,318 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ export const PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
7
+ export const MANIFEST = ".potetos/install.json";
8
+ export const BEGIN = "<!-- potetos-for-everyone:begin -->";
9
+ export const END = "<!-- potetos-for-everyone:end -->";
10
+ export const GITIGNORE_BEGIN = "# potetos-for-everyone:begin";
11
+ export const GITIGNORE_END = "# potetos-for-everyone:end";
12
+
13
+ const BLOCK = `${BEGIN}\n## potetos-for-everyone\n\nFor non-trivial engineering work, use the Agent Skill at \`.agents/skills/poteto-mode/SKILL.md\`.\nIt routes the task to a playbook, loads supporting skills progressively, prefers simple changes,\nand requires evidence against the real artifact. Canonical skills are adapted from Lauren Tan's pstack.\nIf native skill discovery is unavailable, read that SKILL.md and its selected playbook manually.\n${END}`;
14
+ const GITIGNORE_BLOCK = `${GITIGNORE_BEGIN}\n.potetos/\n${GITIGNORE_END}`;
15
+
16
+ export function registry() {
17
+ return JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, "adapters", "registry.json"), "utf8"));
18
+ }
19
+
20
+ function die(message) {
21
+ const err = new Error(message);
22
+ err.isPotetos = true;
23
+ throw err;
24
+ }
25
+
26
+ function readText(file) {
27
+ return fs.existsSync(file) ? fs.readFileSync(file, "utf8") : "";
28
+ }
29
+
30
+ function mergeMarkedBlock(file, begin, end, block) {
31
+ const old = readText(file);
32
+ let next;
33
+ if (old.includes(begin) && old.includes(end)) {
34
+ const start = old.indexOf(begin);
35
+ const finish = old.indexOf(end, start) + end.length;
36
+ const pre = old.slice(0, start).replace(/\s+$/, "");
37
+ const post = old.slice(finish);
38
+ next = pre + (pre.trim() ? "\n\n" : "") + block + post;
39
+ } else {
40
+ next = old.replace(/\s+$/, "") + (old.trim() ? "\n\n" : "") + block + "\n";
41
+ }
42
+ fs.mkdirSync(path.dirname(file), { recursive: true });
43
+ fs.writeFileSync(file, next, "utf8");
44
+ }
45
+
46
+ function removeMarkedBlock(file, begin, end) {
47
+ if (!fs.existsSync(file)) return;
48
+ const old = fs.readFileSync(file, "utf8");
49
+ const start = old.indexOf(begin);
50
+ if (start < 0) return;
51
+ const endStart = old.indexOf(end, start);
52
+ if (endStart < 0) return;
53
+ const finish = endStart + end.length;
54
+ const pre = old.slice(0, start).replace(/\s+$/, "");
55
+ const post = old.slice(finish).replace(/^\s+/, "");
56
+ const next = (pre + (pre && post ? "\n\n" : "") + post).replace(/\s+$/, "") + "\n";
57
+ if (next.trim()) fs.writeFileSync(file, next, "utf8");
58
+ else fs.rmSync(file, { force: true });
59
+ }
60
+
61
+ function selectedAgents(selection, reg) {
62
+ if (selection === "all") {
63
+ return ["universal", ...Object.keys(reg).filter((name) => !["generic", "universal"].includes(name))];
64
+ }
65
+ if (!reg[selection]) die(`unknown agent ${JSON.stringify(selection)}; choose one of: all, ${Object.keys(reg).sort().join(", ")}`);
66
+ return [selection];
67
+ }
68
+
69
+ function skillDestination(target, agents, reg) {
70
+ const dirs = new Set(agents.map((name) => reg[name].skill_dir));
71
+ if (dirs.size !== 1) die("adapter registry uses multiple skill directories; one canonical install is required");
72
+ return path.join(target, [...dirs][0]);
73
+ }
74
+
75
+ function instructionFiles(agents, reg) {
76
+ return [...new Set(["AGENTS.md", ...agents.map((name) => reg[name].instruction_file)])];
77
+ }
78
+
79
+ function copyDir(src, dst) {
80
+ fs.cpSync(src, dst, { recursive: true, force: false, errorOnExist: true });
81
+ }
82
+
83
+ const TEXT_HASH_EXTENSIONS = new Set([".md", ".mdc", ".txt", ".json", ".yml", ".yaml", ".js", ".mjs", ".py", ".sh", ".ps1"]);
84
+
85
+ function hashBytes(file) {
86
+ const data = fs.readFileSync(file);
87
+ if (!TEXT_HASH_EXTENSIONS.has(path.extname(file).toLowerCase())) return data;
88
+ return Buffer.from(data.toString("utf8").replace(/\r\n?/g, "\n"), "utf8");
89
+ }
90
+
91
+ function hashTree(root) {
92
+ const hash = crypto.createHash("sha512");
93
+ const walk = (dir, prefix = "") => {
94
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
95
+ const full = path.join(dir, entry.name);
96
+ const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
97
+ if (entry.isDirectory()) walk(full, rel);
98
+ else if (entry.isFile()) {
99
+ hash.update(rel);
100
+ hash.update("\0");
101
+ hash.update(hashBytes(full));
102
+ hash.update("\0");
103
+ }
104
+ }
105
+ };
106
+ walk(root);
107
+ return hash.digest("hex");
108
+ }
109
+
110
+ function removePath(file) {
111
+ fs.rmSync(file, { recursive: true, force: true });
112
+ }
113
+
114
+ function pruneEmptyParents(start, stop) {
115
+ const stopAbs = path.resolve(stop);
116
+ let current = path.resolve(start);
117
+ while (current !== stopAbs && current.startsWith(stopAbs + path.sep)) {
118
+ if (!fs.existsSync(current)) {
119
+ current = path.dirname(current);
120
+ continue;
121
+ }
122
+ if (fs.readdirSync(current).length) break;
123
+ fs.rmdirSync(current);
124
+ current = path.dirname(current);
125
+ }
126
+ }
127
+
128
+ function loadManifest(target) {
129
+ const file = path.join(target, MANIFEST);
130
+ if (!fs.existsSync(file)) die(`no install manifest at ${file}`);
131
+ try {
132
+ return [file, JSON.parse(fs.readFileSync(file, "utf8"))];
133
+ } catch (err) {
134
+ die(`cannot read install manifest: ${err.message}`);
135
+ }
136
+ }
137
+
138
+ export function modifiedManagedPaths(target, meta) {
139
+ const skillDir = path.join(target, meta.skill_dir || ".agents/skills");
140
+ if (!fs.existsSync(skillDir)) return [`${meta.skill_dir || ".agents/skills"} (missing)`];
141
+ const checksums = meta.checksums || {};
142
+ if (meta.mode === "copy" && Object.keys(checksums).length) {
143
+ const modified = [];
144
+ for (const rel of meta.installed || []) {
145
+ const item = path.join(target, rel);
146
+ if (!fs.existsSync(item)) modified.push(`${rel} (missing)`);
147
+ else if (checksums[rel] && hashTree(item) !== checksums[rel]) modified.push(rel);
148
+ }
149
+ return modified;
150
+ }
151
+ if (meta.mode === "copy" && meta.tree_checksum) {
152
+ return hashTree(skillDir) === meta.tree_checksum ? [] : [`${meta.skill_dir || ".agents/skills"} (content changed)`];
153
+ }
154
+ const modified = [];
155
+ for (const rel of meta.installed || []) {
156
+ const item = path.join(target, rel);
157
+ if (!fs.existsSync(item)) modified.push(`${rel} (missing)`);
158
+ }
159
+ return modified;
160
+ }
161
+
162
+ export function install({ target = process.cwd(), agent = "all", force = false, manageGitignore = true } = {}) {
163
+ target = path.resolve(target);
164
+ if (!fs.existsSync(target)) die(`target does not exist: ${target}`);
165
+ const reg = registry();
166
+ const agents = selectedAgents(agent, reg);
167
+ const skillsDst = skillDestination(target, agents, reg);
168
+ fs.mkdirSync(skillsDst, { recursive: true });
169
+ const installed = [];
170
+ const srcRoot = path.join(PACKAGE_ROOT, "skills");
171
+ const sources = fs.readdirSync(srcRoot).sort().filter((name) => {
172
+ const src = path.join(srcRoot, name);
173
+ return fs.statSync(src).isDirectory() && fs.existsSync(path.join(src, "SKILL.md"));
174
+ });
175
+ const identicalExisting = new Set();
176
+ if (!force) {
177
+ const collisions = [];
178
+ for (const name of sources) {
179
+ const src = path.join(srcRoot, name);
180
+ const dst = path.join(skillsDst, name);
181
+ if (!fs.existsSync(dst)) continue;
182
+ let identical = false;
183
+ try {
184
+ identical = fs.statSync(dst).isDirectory() && hashTree(dst) === hashTree(src);
185
+ } catch {
186
+ identical = false;
187
+ }
188
+ if (identical) identicalExisting.add(name);
189
+ else collisions.push(name);
190
+ }
191
+ if (collisions.length) {
192
+ const preview = collisions.slice(0, 5).map((name) => path.join(skillsDst, name)).join(", ");
193
+ const more = collisions.length > 5 ? ` (+${collisions.length - 5} more)` : "";
194
+ die(`skill destinations already exist with different content: ${preview}${more}; use --force to replace them`);
195
+ }
196
+ }
197
+ for (const name of sources) {
198
+ const src = path.join(srcRoot, name);
199
+ const dst = path.join(skillsDst, name);
200
+ if (!identicalExisting.has(name)) {
201
+ if (fs.existsSync(dst)) removePath(dst);
202
+ copyDir(src, dst);
203
+ }
204
+ installed.push(path.relative(target, dst).split(path.sep).join("/"));
205
+ }
206
+ const instructions = instructionFiles(agents, reg);
207
+ for (const rel of instructions) mergeMarkedBlock(path.join(target, rel), BEGIN, END, BLOCK);
208
+ if (manageGitignore) mergeMarkedBlock(path.join(target, ".gitignore"), GITIGNORE_BEGIN, GITIGNORE_END, GITIGNORE_BLOCK);
209
+ const meta = {
210
+ source: PACKAGE_ROOT,
211
+ package: "potetos-for-everyone",
212
+ package_version: packageVersion(),
213
+ installer: "node",
214
+ agent_selection: agent,
215
+ agents,
216
+ mode: "copy",
217
+ skill_dir: path.relative(target, skillsDst).split(path.sep).join("/"),
218
+ instruction_files: instructions,
219
+ gitignore_managed: manageGitignore,
220
+ installed,
221
+ checksums: Object.fromEntries(installed.map((rel) => [rel, hashTree(path.join(target, rel))])),
222
+ tree_checksum: hashTree(skillsDst)
223
+ };
224
+ const manifest = path.join(target, MANIFEST);
225
+ fs.mkdirSync(path.dirname(manifest), { recursive: true });
226
+ fs.writeFileSync(manifest, JSON.stringify(meta, null, 2) + "\n", "utf8");
227
+ return { target, installed: installed.length, agent, agents, skills: meta.skill_dir };
228
+ }
229
+
230
+ export function update({ target = process.cwd(), force = false } = {}) {
231
+ target = path.resolve(target);
232
+ const [, meta] = loadManifest(target);
233
+ const modified = modifiedManagedPaths(target, meta);
234
+ if (modified.length && !force) {
235
+ const sample = modified.slice(0, 5).join(", ");
236
+ const more = modified.length > 5 ? ` (+${modified.length - 5} more)` : "";
237
+ die(`managed skills were edited or removed: ${sample}${more}; rerun with --force to replace them`);
238
+ }
239
+ for (const rel of meta.installed || []) removePath(path.join(target, rel));
240
+ return install({
241
+ target,
242
+ agent: meta.agent_selection || "universal",
243
+ force: false,
244
+ manageGitignore: meta.gitignore_managed !== false
245
+ });
246
+ }
247
+
248
+ export function autoInstall({ target = process.cwd(), agent = "all" } = {}) {
249
+ const manifest = path.join(path.resolve(target), MANIFEST);
250
+ if (!fs.existsSync(manifest)) return { action: "installed", result: install({ target, agent }) };
251
+ return { action: "updated", result: update({ target }) };
252
+ }
253
+
254
+ export function uninstall({ target = process.cwd() } = {}) {
255
+ target = path.resolve(target);
256
+ const [manifest, meta] = loadManifest(target);
257
+ for (const rel of meta.installed || []) removePath(path.join(target, rel));
258
+ const skillDir = path.join(target, meta.skill_dir || ".agents/skills");
259
+ pruneEmptyParents(skillDir, target);
260
+ for (const rel of meta.instruction_files || ["AGENTS.md"]) {
261
+ const file = path.join(target, rel);
262
+ removeMarkedBlock(file, BEGIN, END);
263
+ if (!fs.existsSync(file)) pruneEmptyParents(path.dirname(file), target);
264
+ }
265
+ if (meta.gitignore_managed) removeMarkedBlock(path.join(target, ".gitignore"), GITIGNORE_BEGIN, GITIGNORE_END);
266
+ fs.rmSync(manifest, { force: true });
267
+ pruneEmptyParents(path.dirname(manifest), target);
268
+ return { target };
269
+ }
270
+
271
+ export function status({ target = process.cwd() } = {}) {
272
+ target = path.resolve(target);
273
+ const manifest = path.join(target, MANIFEST);
274
+ if (!fs.existsSync(manifest)) return { installed: false, target, clean: false };
275
+ const [, meta] = loadManifest(target);
276
+ const modified = modifiedManagedPaths(target, meta);
277
+ return {
278
+ installed: true,
279
+ target,
280
+ clean: modified.length === 0,
281
+ modified,
282
+ count: (meta.installed || []).length,
283
+ agent: meta.agent_selection || "unknown",
284
+ mode: meta.mode || "unknown",
285
+ packageVersion: meta.package_version || null
286
+ };
287
+ }
288
+
289
+ export function listSkills() {
290
+ const srcRoot = path.join(PACKAGE_ROOT, "skills");
291
+ return fs.readdirSync(srcRoot).filter((name) => fs.existsSync(path.join(srcRoot, name, "SKILL.md"))).sort();
292
+ }
293
+
294
+ export function doctor({ target = process.cwd() } = {}) {
295
+ const reg = registry();
296
+ const state = status({ target });
297
+ return {
298
+ packageRoot: PACKAGE_ROOT,
299
+ packageVersion: packageVersion(),
300
+ target: path.resolve(target),
301
+ canonicalSkills: listSkills().length,
302
+ install: state,
303
+ adapters: Object.fromEntries(Object.entries(reg).map(([name, spec]) => [name, {
304
+ skillDir: spec.skill_dir,
305
+ instructionFile: spec.instruction_file,
306
+ present: fs.existsSync(path.join(path.resolve(target), spec.instruction_file))
307
+ }]))
308
+ };
309
+ }
310
+
311
+ export function packageVersion() {
312
+ return JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, "package.json"), "utf8")).version;
313
+ }
314
+
315
+ export function isPackageDevelopmentInstall(initCwd) {
316
+ if (!initCwd) return false;
317
+ return path.resolve(initCwd) === PACKAGE_ROOT;
318
+ }
@@ -0,0 +1,22 @@
1
+ import process from "node:process";
2
+ import { autoInstall, isPackageDevelopmentInstall } from "./core.mjs";
3
+
4
+ const skip = process.env.POTETOS_SKIP_AUTO_INSTALL === "1" || process.env.POTETOS_SKIP_AUTO_INSTALL === "true";
5
+ const globalInstall = process.env.npm_config_global === "true" || process.env.npm_config_global === "1";
6
+ const execInstall = process.env.npm_command === "exec";
7
+ const target = process.env.INIT_CWD || process.env.PWD || process.cwd();
8
+
9
+ if (skip || globalInstall || execInstall || !target || isPackageDevelopmentInstall(target)) {
10
+ if (globalInstall) console.log("potetos: global CLI installed; run `potetos install` inside a project.");
11
+ process.exit(0);
12
+ }
13
+
14
+ try {
15
+ const { action, result } = autoInstall({ target, agent: process.env.POTETOS_AGENT || "all" });
16
+ console.log(`potetos: ${action} ${result.installed} skills in ${result.target}`);
17
+ console.log("potetos: ready - ask your agent to use poteto-mode");
18
+ } catch (err) {
19
+ console.error(`potetos: automatic project setup failed safely: ${err?.message || err}`);
20
+ console.error("potetos: no differing managed files were overwritten. Resolve the conflict or reinstall with POTETOS_SKIP_AUTO_INSTALL=1 and run the CLI manually.");
21
+ process.exitCode = 1;
22
+ }
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env node
2
+ import childProcess from "node:child_process";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import process from "node:process";
6
+ import { PACKAGE_ROOT, doctor, install, listSkills, status, uninstall, update } from "./core.mjs";
7
+
8
+ function fail(message, code = 2) {
9
+ console.error(`potetos: ${message}`);
10
+ process.exit(code);
11
+ }
12
+
13
+ function parse(argv) {
14
+ const out = { _: [] };
15
+ for (let i = 0; i < argv.length; i++) {
16
+ const arg = argv[i];
17
+ if (!arg.startsWith("--")) { out._.push(arg); continue; }
18
+ const key = arg.slice(2);
19
+ if (["force", "no-gitignore", "copy", "link", "help", "version"].includes(key)) out[key] = true;
20
+ else {
21
+ if (i + 1 >= argv.length) fail(`missing value for --${key}`);
22
+ out[key] = argv[++i];
23
+ }
24
+ }
25
+ return out;
26
+ }
27
+
28
+ function help() {
29
+ console.log(`potetos-for-everyone
30
+
31
+ Usage:
32
+ npx potetos # auto-installs or updates in current repo
33
+ potetos install [--target .] [--agent all] [--force]
34
+ potetos update [--target .] [--force]
35
+ potetos status [--target .]
36
+ potetos uninstall [--target .]
37
+ potetos list
38
+ potetos doctor [--target .]
39
+ potetos delegate ... # forwards to bundled Python runner
40
+ potetos panel ... # forwards to bundled Python runner
41
+
42
+ Package manager zero-config install:
43
+ npm install --save-dev potetos-for-everyone
44
+ pnpm add -D potetos-for-everyone
45
+ bun add -d potetos-for-everyone
46
+ yarn add -D potetos-for-everyone
47
+
48
+ Local npm installs auto-install/update the skills. Set POTETOS_SKIP_AUTO_INSTALL=1 to disable that lifecycle behavior.`);
49
+ }
50
+
51
+ function printInstall(result, verb = "installed") {
52
+ console.log(`${verb} ${result.installed} skills in ${result.target}`);
53
+ console.log(`compatibility: ${result.agent} (${result.agents.join(", ")})`);
54
+ console.log(`mode: copy`);
55
+ console.log(`skills: ${result.skills}`);
56
+ console.log("ready: ask your agent to use poteto-mode");
57
+ }
58
+
59
+ function forwardPython(command, rest) {
60
+ const script = path.join(PACKAGE_ROOT, "bin", "potetos");
61
+ const candidates = process.platform === "win32" ? [["py", ["-3"]], ["python", []], ["python3", []]] : [["python3", []], ["python", []]];
62
+ for (const [exe, prefix] of candidates) {
63
+ const probe = childProcess.spawnSync(exe, [...prefix, "--version"], { stdio: "ignore" });
64
+ if (!probe.error && probe.status === 0) {
65
+ const run = childProcess.spawnSync(exe, [...prefix, script, command, ...rest], { stdio: "inherit" });
66
+ process.exit(run.status ?? 1);
67
+ }
68
+ }
69
+ fail(`${command} needs Python 3.10+ for the external-agent runner. Core install/update/status/uninstall commands do not require Python.`);
70
+ }
71
+
72
+ const argv = process.argv.slice(2);
73
+
74
+ if (argv.includes("--help") || argv.includes("-h") || argv[0] === "help") {
75
+ help();
76
+ process.exit(0);
77
+ }
78
+
79
+ if (argv.includes("--version") || argv.includes("-v") || argv[0] === "version") {
80
+ const { packageVersion } = await import("./core.mjs");
81
+ console.log(packageVersion());
82
+ process.exit(0);
83
+ }
84
+
85
+ let command = argv[0];
86
+ if (!command || command.startsWith("--")) {
87
+ command = "auto";
88
+ } else {
89
+ command = argv.shift();
90
+ }
91
+
92
+ if (["delegate", "panel"].includes(command)) forwardPython(command, argv);
93
+
94
+ const args = parse(argv);
95
+ const target = args.target || ".";
96
+ if (args.link) fail("the npm CLI installs self-contained copies only; use a source checkout with the Python CLI for development symlinks");
97
+ try {
98
+ switch (command) {
99
+ case "auto": {
100
+ const manifestPath = path.join(path.resolve(target), ".potetos", "install.json");
101
+ if (fs.existsSync(manifestPath)) {
102
+ printInstall(update({ target, force: !!args.force }), "updated");
103
+ } else {
104
+ printInstall(install({ target, agent: args.agent || "all", force: !!args.force, manageGitignore: !args["no-gitignore"] }));
105
+ }
106
+ break;
107
+ }
108
+ case "install":
109
+ printInstall(install({ target, agent: args.agent || "all", force: !!args.force, manageGitignore: !args["no-gitignore"] }));
110
+ break;
111
+ case "update":
112
+ printInstall(update({ target, force: !!args.force }), "updated");
113
+ break;
114
+ case "uninstall": {
115
+ const result = uninstall({ target });
116
+ console.log(`uninstalled potetos-for-everyone from ${result.target}`);
117
+ break;
118
+ }
119
+ case "status": {
120
+ const state = status({ target });
121
+ if (!state.installed) fail(`not installed in ${state.target}`, 1);
122
+ console.log(`installed: ${state.count} skills`);
123
+ console.log(`compatibility: ${state.agent}`);
124
+ console.log(`mode: ${state.mode}`);
125
+ if (state.packageVersion) console.log(`package: ${state.packageVersion}`);
126
+ if (!state.clean) {
127
+ console.log(`state: modified (${state.modified.length} managed paths differ)`);
128
+ for (const rel of state.modified.slice(0, 10)) console.log(` ${rel}`);
129
+ process.exit(1);
130
+ }
131
+ console.log("state: clean");
132
+ break;
133
+ }
134
+ case "list":
135
+ for (const name of listSkills()) console.log(name);
136
+ break;
137
+ case "doctor":
138
+ console.log(JSON.stringify(doctor({ target }), null, 2));
139
+ break;
140
+ default:
141
+ fail(`unknown command ${JSON.stringify(command)}; run potetos --help`);
142
+ }
143
+ } catch (err) {
144
+ fail(err?.message || String(err));
145
+ }
package/package.json ADDED
@@ -0,0 +1,98 @@
1
+ {
2
+ "name": "potetos-for-everyone",
3
+ "version": "0.1.0",
4
+ "description": "Universal pstack and Poteto Mode engineering workflow for Claude Code, Cursor, Codex, Gemini, and all AI coding agents. Drop-in pstack-claude alternative with native plugin support.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "potetos": "npm/potetos.mjs",
9
+ "potetos-for-everyone": "npm/potetos.mjs"
10
+ },
11
+ "files": [
12
+ "npm/",
13
+ "bin/",
14
+ "runtime/",
15
+ "adapters/",
16
+ "skills/",
17
+ "agents/",
18
+ "automations/",
19
+ "docs/",
20
+ "assets/",
21
+ "hooks/",
22
+ ".claude-plugin/",
23
+ ".codex-plugin/",
24
+ ".agents/",
25
+ "AGENTS.md",
26
+ "PORTABILITY.md",
27
+ "NOTICE.md",
28
+ "UPSTREAM.json",
29
+ "UPSTREAM_INVENTORY.json",
30
+ "VERSION",
31
+ "LICENSE",
32
+ "README.md"
33
+ ],
34
+ "scripts": {
35
+ "test": "node --test tests/npm.test.mjs",
36
+ "postinstall": "node npm/postinstall.mjs",
37
+ "test:npm": "node --test tests/npm.test.mjs",
38
+ "check:pack": "node scripts/check_npm_package.mjs",
39
+ "prepack": "node scripts/check_npm_package.mjs"
40
+ },
41
+ "engines": {
42
+ "node": ">=18"
43
+ },
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "git+https://github.com/TheOnlyFusionCube/potetos-for-everyone.git"
47
+ },
48
+ "homepage": "https://github.com/TheOnlyFusionCube/potetos-for-everyone#readme",
49
+ "bugs": {
50
+ "url": "https://github.com/TheOnlyFusionCube/potetos-for-everyone/issues"
51
+ },
52
+ "keywords": [
53
+ "pstack",
54
+ "pstack-claude",
55
+ "pstack-for-claude",
56
+ "poteto-mode",
57
+ "lauren-tan",
58
+ "claude-code",
59
+ "claude-code-plugin",
60
+ "claude-plugin",
61
+ "claude-skills",
62
+ "claude",
63
+ "anthropic",
64
+ "codex",
65
+ "codex-plugin",
66
+ "cursor",
67
+ "cursor-rules",
68
+ "gemini",
69
+ "gemini-cli",
70
+ "windsurf",
71
+ "cline",
72
+ "roo-code",
73
+ "continue-dev",
74
+ "copilot",
75
+ "github-copilot",
76
+ "agent-skills",
77
+ "ai-agents",
78
+ "coding-agents",
79
+ "developer-tools",
80
+ "tdd",
81
+ "test-driven-development",
82
+ "multi-agent",
83
+ "subagents",
84
+ "pi-package",
85
+ "pi-pstack",
86
+ "open-pstack",
87
+ "skills-cli",
88
+ "pstack-without-cursor",
89
+ "worktrees"
90
+ ],
91
+ "pi": {
92
+ "skills": ["./skills"],
93
+ "prompts": [".codex-plugin/prompts"]
94
+ },
95
+ "publishConfig": {
96
+ "access": "public"
97
+ }
98
+ }
@@ -0,0 +1,21 @@
1
+ # Portable runner protocol
2
+
3
+ Hosts with native subagents should use them. When native delegation is missing, `potetos-for-everyone` can run arbitrary user-configured AI agent CLIs without knowing their vendor syntax.
4
+
5
+ Create `.potetos/config.json` from `config.example.json`. Each runner supplies an argv array. Supported placeholders are `{prompt}`, `{prompt_file}`, `{workspace}`, and `{output_file}`. Set `stdin: true` when the CLI accepts the prompt on stdin. Prefer `env_passthrough` for credential variable names; do not commit secret values into `environment`.
6
+
7
+ Run one worker:
8
+
9
+ ```bash
10
+ ./bin/potetos delegate --workspace . --runner default --prompt-file task.md
11
+ ```
12
+
13
+ Run an independent panel:
14
+
15
+ ```bash
16
+ ./bin/potetos panel --workspace . --runners default,reviewer --prompt-file review.md
17
+ ```
18
+
19
+ Add `--isolate` for code-writing workers. It refuses a dirty base (except `.potetos/` runtime state), creates a separate Git worktree and `potetos/<run-id>/<runner>` branch per worker, and leaves that worktree intact for review. Outputs and metadata are stored under `.potetos/runs/` by default.
20
+
21
+ The runner never invokes a shell implicitly: `command` is an argv array executed directly. Any program named there is explicitly user-configured and runs with the permissions of the current process.
@@ -0,0 +1 @@
1
+ """Portable runtime helpers for potetos-for-everyone."""
@@ -0,0 +1,36 @@
1
+ {
2
+ "schema_version": 1,
3
+ "capabilities": {
4
+ "files.read": {
5
+ "required": true
6
+ },
7
+ "files.write": {
8
+ "required": false,
9
+ "fallback": "return patch/draft"
10
+ },
11
+ "run": {
12
+ "required": false,
13
+ "fallback": "report verification gap"
14
+ },
15
+ "vcs": {
16
+ "required": false,
17
+ "fallback": "workspace evidence only"
18
+ },
19
+ "delegate": {
20
+ "required": false,
21
+ "fallback": "sequential labeled passes"
22
+ },
23
+ "search": {
24
+ "required": false,
25
+ "fallback": "available local evidence only"
26
+ },
27
+ "observe": {
28
+ "required": false,
29
+ "fallback": "proxy evidence, explicitly labeled"
30
+ },
31
+ "track": {
32
+ "required": false,
33
+ "fallback": "Markdown/TSV log when writable"
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "max_parallel": 4,
3
+ "runners": {
4
+ "default": {
5
+ "command": ["your-agent-cli", "--prompt-file", "{prompt_file}"],
6
+ "stdin": false,
7
+ "timeout_seconds": 1800,
8
+ "env_passthrough": []
9
+ },
10
+ "reviewer": {
11
+ "command": ["another-agent-cli", "--prompt", "{prompt}"],
12
+ "stdin": false,
13
+ "timeout_seconds": 1800,
14
+ "env_passthrough": []
15
+ }
16
+ }
17
+ }