takomi 2.1.27 → 2.1.28
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/.pi/README.md +10 -0
- package/.pi/extensions/takomi-context-manager/diagnostics.ts +1 -1
- package/.pi/extensions/takomi-context-manager/extension-conflicts.ts +14 -3
- package/.pi/extensions/takomi-runtime/context-panel.ts +583 -282
- package/.pi/extensions/takomi-runtime/index.ts +38 -1
- package/.pi/extensions/takomi-runtime/takomi-stats.js +44 -16
- package/README.md +34 -4
- package/package.json +4 -2
- package/src/cli.js +326 -33
- package/src/harness.js +132 -16
- package/src/pi-harness.js +27 -6
- package/src/pi-optional-features.js +195 -0
- package/src/postinstall.js +27 -0
- package/src/skills-catalog.js +245 -0
- package/src/skills-installer.js +244 -101
- package/src/skills-selection-tui.js +200 -0
- package/src/store.js +418 -240
- package/src/takomi-stats.js +44 -16
|
@@ -84,6 +84,9 @@ const STATE_ENTRY = "takomi-runtime-state";
|
|
|
84
84
|
|
|
85
85
|
let activeProfile: TakomiProfile = DEFAULT_TAKOMI_PROFILE;
|
|
86
86
|
let activeSubagentLabel: string | undefined;
|
|
87
|
+
let activeSubagentAgent: string | undefined;
|
|
88
|
+
let activeSubagentTask: string | undefined;
|
|
89
|
+
let activeSubagentStatus: string | undefined;
|
|
87
90
|
|
|
88
91
|
const ThinkingSchema = Type.Union([
|
|
89
92
|
Type.Literal("off"),
|
|
@@ -665,18 +668,27 @@ export default function takomiRuntime(pi: ExtensionAPI) {
|
|
|
665
668
|
launchMode: state.launchMode,
|
|
666
669
|
planMode: state.planMode,
|
|
667
670
|
activeSubagent: activeSubagentLabel,
|
|
671
|
+
activeSubagentAgent,
|
|
672
|
+
activeSubagentTask,
|
|
673
|
+
activeSubagentStatus,
|
|
668
674
|
});
|
|
669
675
|
}
|
|
670
676
|
|
|
671
677
|
async function applySubagentRuntimeEvent(event: TakomiSubagentRuntimeEvent, ctx: ExtensionContext): Promise<void> {
|
|
672
678
|
if (event.type === "start") {
|
|
673
679
|
activeSubagentLabel = `${event.state.agent}: ${event.state.taskLabel}`;
|
|
680
|
+
activeSubagentAgent = event.state.agent;
|
|
681
|
+
activeSubagentTask = event.state.taskLabel;
|
|
682
|
+
activeSubagentStatus = event.state.status ?? "running";
|
|
674
683
|
syncContextPanelState();
|
|
675
684
|
} else if ((event.type === "update" || event.type === "complete" || event.type === "block") && event.patch) {
|
|
676
685
|
const model = event.patch.model ? ` @ ${event.patch.model}` : "";
|
|
677
686
|
const thinking = event.patch.thinking ? ` (${event.patch.thinking})` : "";
|
|
678
687
|
const label = event.patch.summary?.split(/\r?\n/).find(Boolean);
|
|
679
688
|
if (label) activeSubagentLabel = `${label}${model}${thinking}`;
|
|
689
|
+
if (event.patch.agent) activeSubagentAgent = event.patch.agent;
|
|
690
|
+
if (event.patch.taskLabel) activeSubagentTask = event.patch.taskLabel;
|
|
691
|
+
activeSubagentStatus = event.type === "complete" ? "completed" : event.type === "block" ? "blocked" : event.patch.status ?? activeSubagentStatus;
|
|
680
692
|
syncContextPanelState();
|
|
681
693
|
}
|
|
682
694
|
switch (event.type) {
|
|
@@ -761,6 +773,9 @@ export default function takomiRuntime(pi: ExtensionAPI) {
|
|
|
761
773
|
await updateState(ctx, () => {
|
|
762
774
|
state = cloneState(DEFAULT_STATE);
|
|
763
775
|
activeSubagentLabel = undefined;
|
|
776
|
+
activeSubagentAgent = undefined;
|
|
777
|
+
activeSubagentTask = undefined;
|
|
778
|
+
activeSubagentStatus = undefined;
|
|
764
779
|
}, "Takomi runtime state reset");
|
|
765
780
|
subagentController.reset(ctx);
|
|
766
781
|
contextPanel.resetSession();
|
|
@@ -1202,6 +1217,24 @@ ${stateJson}`
|
|
|
1202
1217
|
}
|
|
1203
1218
|
|
|
1204
1219
|
const routingPolicy = await resolveTakomiRoutingPolicy(runtimeCwd);
|
|
1220
|
+
const optionalFeatureContext = (() => {
|
|
1221
|
+
try {
|
|
1222
|
+
const tools = typeof (pi as { getAllTools?: () => Array<{ name?: string }> }).getAllTools === "function"
|
|
1223
|
+
? (pi as { getAllTools: () => Array<{ name?: string }> }).getAllTools()
|
|
1224
|
+
: [];
|
|
1225
|
+
const toolNames = new Set(tools.map((tool) => tool.name).filter(Boolean));
|
|
1226
|
+
const guidance: string[] = [];
|
|
1227
|
+
if (toolNames.has("ask_user_question")) {
|
|
1228
|
+
guidance.push("Takomi Interview is available: when Genesis, Design, or ambiguous planning would otherwise require guessing, use ask_user_question to ask concise structured questions before proceeding.");
|
|
1229
|
+
}
|
|
1230
|
+
if (toolNames.has("todo")) {
|
|
1231
|
+
guidance.push("Takomi Todo is available as an optional live overlay. You may use todo for short-lived execution visibility, but takomi_board remains the durable lifecycle/task source of truth.");
|
|
1232
|
+
}
|
|
1233
|
+
return guidance.join("\n");
|
|
1234
|
+
} catch {
|
|
1235
|
+
return "";
|
|
1236
|
+
}
|
|
1237
|
+
})();
|
|
1205
1238
|
const modelPreflightContext = (() => {
|
|
1206
1239
|
try {
|
|
1207
1240
|
const available = typeof (ctx as { modelRegistry?: { getAvailable?: () => Array<{ provider?: string; id?: string; name?: string }> } }).modelRegistry?.getAvailable === "function"
|
|
@@ -1223,6 +1256,7 @@ ${stateJson}`
|
|
|
1223
1256
|
routingPolicy.text
|
|
1224
1257
|
? `${routingPolicy.source === "bundled" ? "Bundled" : "Project"} Takomi model routing policy is active. Apply it when choosing parent/subagent models and escalation levels:\n\n${routingPolicy.text}`
|
|
1225
1258
|
: "No Takomi routing policy file was found. Users can install one with `/takomi routing <policy>` or by saying `Update Takomi routing logic: \"\"\"...\"\"\"`.",
|
|
1259
|
+
optionalFeatureContext,
|
|
1226
1260
|
modelPreflightContext,
|
|
1227
1261
|
`Execution mode: ${route.executionMode}. Session recommendation: ${route.sessionRecommendation}.`,
|
|
1228
1262
|
`Takomi execution gate: ${effectiveState.launchMode === "manual" ? "review" : "auto"}. In review gate mode, show the delegation plan before launching and return to the user after each task with results, verification guidance, and the recommended next step.`,
|
|
@@ -1257,8 +1291,10 @@ ${stateJson}`
|
|
|
1257
1291
|
runtimeCtx = ctx;
|
|
1258
1292
|
activeProfile = await loadTakomiProfile(ctx.cwd);
|
|
1259
1293
|
activeSubagentLabel = undefined;
|
|
1294
|
+
activeSubagentAgent = undefined;
|
|
1295
|
+
activeSubagentTask = undefined;
|
|
1296
|
+
activeSubagentStatus = undefined;
|
|
1260
1297
|
subagentController.reset(ctx);
|
|
1261
|
-
contextPanel.resetSession();
|
|
1262
1298
|
const entries = ctx.sessionManager.getEntries();
|
|
1263
1299
|
for (let i = entries.length - 1; i >= 0; i--) {
|
|
1264
1300
|
const entry = entries[i] as { type: string; customType?: string; data?: TakomiState };
|
|
@@ -1278,6 +1314,7 @@ ${stateJson}`
|
|
|
1278
1314
|
}
|
|
1279
1315
|
|
|
1280
1316
|
syncContextPanelState();
|
|
1317
|
+
contextPanel.rebuildFromSession(ctx);
|
|
1281
1318
|
await refreshUi(ctx, state);
|
|
1282
1319
|
contextPanel.show(ctx);
|
|
1283
1320
|
flushPendingSubagentEvents();
|
|
@@ -40,6 +40,28 @@ function cost(model, input, cache, output, additiveCache = true) { const p = PRI
|
|
|
40
40
|
function fmtTokens(n) { if (n >= 1e9) return `${(n/1e9).toFixed(2)}B`; if (n >= 1e6) return `${(n/1e6).toFixed(1)}M`; if (n >= 1e3) return `${(n/1e3).toFixed(1)}K`; return String(Math.round(n || 0)); }
|
|
41
41
|
function fmtMoney(n) { return `$${(n || 0).toFixed(n > 100 ? 0 : 2)}`; }
|
|
42
42
|
function ms(n) { if (!n) return '-'; const s = Math.round(n/1000); if (s < 60) return `${s}s`; const m = Math.floor(s/60); if (m < 60) return `${m}m ${s%60}s`; const h = Math.floor(m/60); return `${h}h ${m%60}m`; }
|
|
43
|
+
const ACTIVE_GAP_THRESHOLD_MS = 15 * 60 * 1000;
|
|
44
|
+
function timestampMs(value) {
|
|
45
|
+
if (typeof value === 'number') return Number.isFinite(value) ? value : null;
|
|
46
|
+
if (typeof value === 'string' && value) {
|
|
47
|
+
const parsed = Date.parse(value);
|
|
48
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
function addTimestamp(target, value) {
|
|
53
|
+
const parsed = timestampMs(value);
|
|
54
|
+
if (parsed !== null) target.push(parsed);
|
|
55
|
+
}
|
|
56
|
+
function activeDuration(timestamps, maxGapMs = ACTIVE_GAP_THRESHOLD_MS) {
|
|
57
|
+
const sorted = [...new Set((timestamps || []).filter(Number.isFinite))].sort((a, b) => a - b);
|
|
58
|
+
let total = 0;
|
|
59
|
+
for (let i = 1; i < sorted.length; i += 1) {
|
|
60
|
+
const delta = sorted[i] - sorted[i - 1];
|
|
61
|
+
if (delta > 0 && delta <= maxGapMs) total += delta;
|
|
62
|
+
}
|
|
63
|
+
return total;
|
|
64
|
+
}
|
|
43
65
|
function parseSince(value) {
|
|
44
66
|
if (!value) return null;
|
|
45
67
|
const raw = String(value).trim().toLowerCase();
|
|
@@ -88,14 +110,20 @@ async function files(root, suffix = '.jsonl') {
|
|
|
88
110
|
await walk(root); return out;
|
|
89
111
|
}
|
|
90
112
|
|
|
113
|
+
function pushTask(taskRows, task) {
|
|
114
|
+
if (!task?.end || task.end === task.start) return;
|
|
115
|
+
task.activeMs = activeDuration(task.activityTimestamps || []);
|
|
116
|
+
taskRows.push(task);
|
|
117
|
+
}
|
|
118
|
+
|
|
91
119
|
async function scanPiSessions(root, source, events, sessionRows = [], taskRows = []) {
|
|
92
120
|
for (const file of await files(root)) {
|
|
93
121
|
let provider = 'unknown', model = 'unknown', session = path.basename(file, '.jsonl'), cwd = '', currentTask = null;
|
|
94
|
-
const row = { key: session, session, source, file, project: projectKey(file), cwd, start: '', end: '', turns: 0, messages: 0, toolCalls: 0, subagentCalls: 0, roles: new Map(), stages: new Map(), workflows: new Map(), activeMs: 0 };
|
|
122
|
+
const row = { key: session, session, source, file, project: projectKey(file), cwd, start: '', end: '', turns: 0, messages: 0, toolCalls: 0, subagentCalls: 0, roles: new Map(), stages: new Map(), workflows: new Map(), activeMs: 0, activityTimestamps: [] };
|
|
95
123
|
const text = await fs.readFile(file, 'utf8').catch(() => '');
|
|
96
124
|
for (const line of text.split(/\r?\n/)) {
|
|
97
125
|
const obj = safeJson(line); if (!obj) continue;
|
|
98
|
-
if (obj.timestamp) { row.start ||= obj.timestamp; row.end = obj.timestamp; }
|
|
126
|
+
if (obj.timestamp) { row.start ||= obj.timestamp; row.end = obj.timestamp; addTimestamp(row.activityTimestamps, obj.timestamp); }
|
|
99
127
|
if (obj.type === 'session') { session = obj.id || session; cwd = obj.cwd || cwd; row.key = session; row.session = session; row.cwd = cwd; }
|
|
100
128
|
if (obj.type === 'model_change') { provider = obj.provider || provider; model = obj.modelId || model; }
|
|
101
129
|
if (obj.type === 'custom' && obj.customType === 'takomi-runtime-state' && obj.data) {
|
|
@@ -112,12 +140,14 @@ async function scanPiSessions(root, source, events, sessionRows = [], taskRows =
|
|
|
112
140
|
row.messages += 1;
|
|
113
141
|
const ts = obj.timestamp || msg.timestamp || '';
|
|
114
142
|
if (msg.role === 'user') {
|
|
115
|
-
|
|
143
|
+
pushTask(taskRows, currentTask);
|
|
116
144
|
row.turns += 1;
|
|
117
145
|
const textPart = (msg.content || []).find(p => p?.type === 'text')?.text || '';
|
|
118
|
-
currentTask = { source, file, session, project: projectKey(file), cwd, start: ts, end: ts, provider, model, turns: 1, toolCalls: 0, title: String(textPart).replace(/\s+/g, ' ').trim() };
|
|
146
|
+
currentTask = { source, file, session, project: projectKey(file), cwd, start: ts, end: ts, provider, model, turns: 1, toolCalls: 0, title: String(textPart).replace(/\s+/g, ' ').trim(), activityTimestamps: [] };
|
|
147
|
+
addTimestamp(currentTask.activityTimestamps, ts);
|
|
119
148
|
} else if (currentTask && ts) {
|
|
120
149
|
currentTask.end = ts;
|
|
150
|
+
addTimestamp(currentTask.activityTimestamps, ts);
|
|
121
151
|
}
|
|
122
152
|
for (const part of msg.content || []) {
|
|
123
153
|
if (!part || part.type !== 'toolCall') continue;
|
|
@@ -135,8 +165,8 @@ async function scanPiSessions(root, source, events, sessionRows = [], taskRows =
|
|
|
135
165
|
const u = msg && msg.usage;
|
|
136
166
|
if (u) events.push({ source, file, timestamp: obj.timestamp, day: dayOf(obj.timestamp), session, provider, model, project: projectKey(file), kind: 'usage', input: +u.input||0, cache: +u.cacheRead||0, output: +u.output||0, total: +u.totalTokens||0, cost: cost(model, +u.input||0, +u.cacheRead||0, +u.output||0, true) });
|
|
137
167
|
}
|
|
138
|
-
|
|
139
|
-
row.activeMs =
|
|
168
|
+
pushTask(taskRows, currentTask);
|
|
169
|
+
row.activeMs = activeDuration(row.activityTimestamps);
|
|
140
170
|
if (row.messages || row.toolCalls || row.turns) sessionRows.push(row);
|
|
141
171
|
}
|
|
142
172
|
}
|
|
@@ -336,9 +366,7 @@ function sessionDuration(row) {
|
|
|
336
366
|
return row?.activeMs || 0;
|
|
337
367
|
}
|
|
338
368
|
function taskDuration(row) {
|
|
339
|
-
|
|
340
|
-
const end = Date.parse(row?.end || '');
|
|
341
|
-
return Number.isFinite(start) && Number.isFinite(end) && end >= start ? end - start : 0;
|
|
369
|
+
return row?.activeMs ?? activeDuration(row?.activityTimestamps || []);
|
|
342
370
|
}
|
|
343
371
|
function taskLabel(row, width = 34) {
|
|
344
372
|
const label = row?.title || row?.project || row?.session || 'unknown';
|
|
@@ -379,7 +407,7 @@ function renderFocusedView(stats, opts = {}) {
|
|
|
379
407
|
` ${pc.cyan(ms(sessionDuration(r)))} ${pc.dim(r.turns + ' turns')} ${pc.dim(r.toolCalls + ' tools')}`,
|
|
380
408
|
` ${pc.dim(r.file || '')}`,
|
|
381
409
|
].join('\n'), limit);
|
|
382
|
-
if (view === 'tasks-full' || view === 'task-full') return renderFullList('Longest
|
|
410
|
+
if (view === 'tasks-full' || view === 'task-full') return renderFullList('Longest Active Turns — Full Prompts', stats.topTasks || [], (r, i) => [
|
|
383
411
|
` ${pc.dim(String(i + 1).padStart(2, '0') + '.')} ${pc.cyan(ms(taskDuration(r)))} ${pc.magenta(r.toolCalls + ' tools')} ${pc.dim(dayOf(r.start))}`,
|
|
384
412
|
` ${pc.white(indentWrap(r.title || r.project || r.session || 'unknown'))}`,
|
|
385
413
|
` ${pc.dim(r.project || '')}`,
|
|
@@ -426,7 +454,7 @@ function renderFocusedView(stats, opts = {}) {
|
|
|
426
454
|
{ width: 8, align: 'right', get: r => pc.cyan(String(r.toolCalls)) },
|
|
427
455
|
{ width: 8, align: 'left', get: () => pc.dim('tools') },
|
|
428
456
|
]],
|
|
429
|
-
tasks: ['Longest
|
|
457
|
+
tasks: ['Longest Active Turns', stats.topTasks || [], [
|
|
430
458
|
{ width: 6, align: 'left', get: r => pc.dim(dayOf(r.start).slice(5)) },
|
|
431
459
|
{ width: 9, align: 'right', get: r => pc.cyan(ms(taskDuration(r))) },
|
|
432
460
|
{ width: 11, align: 'right', get: r => pc.magenta(`${r.toolCalls} tools`) },
|
|
@@ -518,9 +546,9 @@ export function renderTakomiStats(stats, opts = {}) {
|
|
|
518
546
|
// ── Duration Cards ────────────────────────────────────────────────────
|
|
519
547
|
lines.push('');
|
|
520
548
|
const cards3 = [
|
|
521
|
-
statCard(longestSession ? ms(sessionDuration(longestSession)) : '-', 'Active Session', pc.cyan),
|
|
549
|
+
statCard(longestSession ? ms(sessionDuration(longestSession)) : '-', 'Top Active Session', pc.cyan),
|
|
522
550
|
statCard(longestSession ? String(longestSession.turns) : '-', 'Turns in Session', pc.cyan),
|
|
523
|
-
statCard(longestTask ? ms(taskDuration(longestTask)) : '-', 'Longest
|
|
551
|
+
statCard(longestTask ? ms(taskDuration(longestTask)) : '-', 'Longest Active Turn', pc.magenta),
|
|
524
552
|
statCard(longestTask ? String(longestTask.toolCalls) : '-', 'Tools in Task', pc.magenta),
|
|
525
553
|
statCard(stats.mostSubagentsSession ? String(stats.mostSubagentsSession.subagentCalls) : '0', 'Max Subagents', pc.blue),
|
|
526
554
|
];
|
|
@@ -530,7 +558,7 @@ export function renderTakomiStats(stats, opts = {}) {
|
|
|
530
558
|
|
|
531
559
|
// ── Info line ─────────────────────────────────────────────────────────
|
|
532
560
|
lines.push('');
|
|
533
|
-
const infoText = `Peak: ${peak?.key || '-'} · ${streaks.quietDays} quiet days · ${stats.totals.events.toLocaleString()} events${stats.since ? ` · since ${stats.since}` : ''}`;
|
|
561
|
+
const infoText = `Peak: ${peak?.key || '-'} · ${streaks.quietDays} quiet days · ${stats.totals.events.toLocaleString()} events · active gaps ≤15m${stats.since ? ` · since ${stats.since}` : ''}`;
|
|
534
562
|
lines.push(center(pc.dim(infoText), W));
|
|
535
563
|
|
|
536
564
|
lines.push('');
|
|
@@ -586,10 +614,10 @@ export function renderTakomiStats(stats, opts = {}) {
|
|
|
586
614
|
]));
|
|
587
615
|
}
|
|
588
616
|
|
|
589
|
-
// ── Longest
|
|
617
|
+
// ── Longest Active Turns ───────────────────────────────────────────────
|
|
590
618
|
if (stats.topTasks?.length) {
|
|
591
619
|
lines.push('');
|
|
592
|
-
lines.push(renderTable('Longest
|
|
620
|
+
lines.push(renderTable('Longest Active Turns', stats.topTasks.slice(0, 5), [
|
|
593
621
|
{ width: 6, align: 'left', get: r => pc.dim(dayOf(r.start).slice(5)) },
|
|
594
622
|
{ width: 9, align: 'right', get: r => pc.cyan(ms(taskDuration(r))) },
|
|
595
623
|
{ width: 11, align: 'right', get: r => pc.magenta(`${r.toolCalls} tools`) },
|
package/README.md
CHANGED
|
@@ -29,6 +29,11 @@ Optional global skills:
|
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
31
|
takomi setup skills
|
|
32
|
+
# First install defaults to Core Skills.
|
|
33
|
+
# Repeat installs default to Leave As Is so existing selections are not pruned accidentally.
|
|
34
|
+
# Custom opens a color-coded category TUI with expandable skill rows when a TTY is available.
|
|
35
|
+
# Optional Pi feature packs can also be managed later:
|
|
36
|
+
takomi setup pi-features
|
|
32
37
|
```
|
|
33
38
|
|
|
34
39
|
Useful management commands:
|
|
@@ -43,6 +48,8 @@ takomi setup project
|
|
|
43
48
|
|
|
44
49
|
Legacy commands like `takomi install pi`, `takomi sync pi`, `takomi upgrade`, and `takomi init` still work, but the simpler mental model is: **setup once, refresh when stale, run `takomi` to use it.**
|
|
45
50
|
|
|
51
|
+
During `takomi setup pi` or `takomi setup pi-features`, Takomi offers optional Pi feature packs with recommended/manual/select-all/skip choices. Current defaults install **Takomi Interview** (`npm:@juicesharp/rpiv-ask-user-question`) so models can ask structured clarification questions. **Takomi Todo** (`npm:@juicesharp/rpiv-todo`), **Takomi Browser QA** (`npm:pi-chrome`), and **Takomi Doc Preview** (`npm:pi-markdown-preview`) remain opt-in. `takomi refresh` runs Pi's package updater so installed optional, custom, old, and new Pi packages are reconciled together.
|
|
52
|
+
|
|
46
53
|
### Context Manager
|
|
47
54
|
|
|
48
55
|
Takomi now ships a Pi-native `takomi-context-manager` extension. It reduces prompt bloat with progressive context loading:
|
|
@@ -69,7 +76,8 @@ npx takomi install
|
|
|
69
76
|
What happens next:
|
|
70
77
|
- 🔍 **Auto-detects** every AI harness on your machine
|
|
71
78
|
- 📦 **Creates your command center** at `~/.takomi/`
|
|
72
|
-
-
|
|
79
|
+
- 🧰 **Lets you choose Core, Present Custom, Custom, All, or Leave As Is for skills**
|
|
80
|
+
- 📡 **Syncs your selected toolkit** to every IDE automatically
|
|
73
81
|
- 🔄 **Keeps KiloCode in sync** across CLI and VS Code
|
|
74
82
|
|
|
75
83
|
### Option B: Per-Project Setup
|
|
@@ -118,7 +126,9 @@ Original Takomi-authored skills in this bundle include `21st-dev-components`, `t
|
|
|
118
126
|
|
|
119
127
|
Think of skills as specialized team members you can summon on demand. From security audits to AI video generation — there's a skill for that.
|
|
120
128
|
|
|
121
|
-
|
|
129
|
+
Takomi's own installer no longer installs every bundled skill by default. `takomi setup skills` uses **Core Skills** for first-time installs, **Leave As Is** for repeat installs, and ownership-safe cleanup when you explicitly deselect Takomi-managed skills. Manual/user-added skills are preserved. Custom selection opens a color-coded category browser with expandable rows on capable terminals, and falls back to simple prompts elsewhere. The global store/harness sync path uses the same ownership model so deselected Takomi-managed skills and workflows can be pruned from `~/.takomi/` and synced harness folders without touching manual or imported resources.
|
|
130
|
+
|
|
131
|
+
The published bundle currently ships **72 top-level skills**, including the original `21st-dev-components` workflow for guided 21st.dev integration. The `pr-comment-fix` skill is sourced from https://gist.github.com/GSonofNun/35c67304c35dac7d6b43308b5371f671.
|
|
122
132
|
|
|
123
133
|
### Interactive Search & Install
|
|
124
134
|
```bash
|
|
@@ -130,7 +140,22 @@ npx -y skills add https://github.com/JStaRFilms/VibeCode-Protocol-Suite
|
|
|
130
140
|
```
|
|
131
141
|
|
|
132
142
|
### Core Essentials (Start Here)
|
|
133
|
-
The
|
|
143
|
+
The recommended Takomi installer defaults are:
|
|
144
|
+
|
|
145
|
+
```txt
|
|
146
|
+
takomi
|
|
147
|
+
sync-docs
|
|
148
|
+
code-review
|
|
149
|
+
security-audit
|
|
150
|
+
optimize-agent-context
|
|
151
|
+
agent-recovery
|
|
152
|
+
avoid-feature-creep
|
|
153
|
+
ai-sdk
|
|
154
|
+
git-commit-generation
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
For the external `skills` CLI, install only the router skill if you want the smallest possible footprint:
|
|
158
|
+
|
|
134
159
|
```bash
|
|
135
160
|
npx -y skills add https://github.com/JStaRFilms/VibeCode-Protocol-Suite --skill takomi
|
|
136
161
|
```
|
|
@@ -466,8 +491,9 @@ This is a living system. If you discover improvements:
|
|
|
466
491
|
|
|
467
492
|
## 🙏 Acknowledgements
|
|
468
493
|
|
|
469
|
-
Externally sourced skills
|
|
494
|
+
Externally sourced skills and optional Pi packages retain credit to their upstream creators. Takomi-original skills, workflows, and Takomi runtime/orchestration extensions in this repository, including `21st-dev-components`, remain authored and maintained by J StaR Films Studios.
|
|
470
495
|
|
|
496
|
+
- **Pi Coding Agent**: Built for [Pi](https://github.com/earendil-works/pi) / `@earendil-works/pi-coding-agent` by **Mario Zechner** and Earendil Works — the MIT-licensed coding-agent runtime and extension API that powers the Pi-native Takomi harness.
|
|
471
497
|
- **Anthropic Skills**: From [anthropics/skills](https://github.com/anthropics/skills) — a massive collection including **Office Suite** (PDF/DOCX/PPTX/XLSX), **Frontend Design**, **Webapp Testing**, **Algorithmic Art**, **Monorepo Management**, and **Skill Creator**.
|
|
472
498
|
- **Inference.sh Skills**: From [inference.sh/skills](https://github.com/inference-sh/skills) — complete media & automation suite including **Marketing Videos**, **Voice Cloning**, **Social Content**, **Twitter Automation**, **Product Photography**, and **Prompt Engineering**.
|
|
473
499
|
- **Marketing Skills**: From [coreyhaines31/marketingskills](https://github.com/coreyhaines31/marketingskills) — the complete marketer's toolkit: **Copywriting**, **Pricing Strategy**, **Social Strategy**, **Programmatic SEO**, and **Marketing Ideas**.
|
|
@@ -483,6 +509,10 @@ Externally sourced skills in this bundle retain credit to their upstream creator
|
|
|
483
509
|
- **Google Stitch Skills**: From [google-labs-code/stitch-skills](https://github.com/google-labs-code/stitch-skills) — Design-to-code suite including **design-md**, **enhance-prompt**, **stitch-loop**, **react-components**, and **shadcn-ui**.
|
|
484
510
|
- **Jules**: From [sanjay3290/ai-skills](https://github.com/sanjay3290/ai-skills) — delegate coding tasks to Google Jules AI agent.
|
|
485
511
|
- **Subagent Execution**: Built on **[`pi-subagents`](https://github.com/nicobailon/pi-subagents)** by **Nico Bailon** — providing the underlying Pi extension for delegated subagent runs (result rendering, live progress, single/parallel/chain execution, session/artifact handling, and related subagent tooling), upon which Takomi adds its own lifecycle orchestration, model-routing policy, and workflow metadata.
|
|
512
|
+
- **Takomi Interview / Todo Optional Packs**: Optional setup integrates **[`@juicesharp/rpiv-ask-user-question`](https://github.com/juicesharp/rpiv-mono/tree/main/packages/rpiv-ask-user-question)** and **[`@juicesharp/rpiv-todo`](https://github.com/juicesharp/rpiv-mono/tree/main/packages/rpiv-todo)** by **juicesharp** — MIT-licensed Pi extensions for structured user questions and live todo overlays.
|
|
513
|
+
- **Takomi Browser QA Optional Pack**: Optional setup can install **[`pi-chrome`](https://github.com/tianrendong/pi-chrome)** by **tianrendong** — an MIT-licensed Pi extension for explicitly authorized Chrome/browser automation.
|
|
514
|
+
- **Takomi Doc Preview Optional Pack**: Optional setup can install **[`pi-markdown-preview`](https://github.com/omaclaren/pi-markdown-preview)** by **omaclaren** — an MIT-licensed Pi extension for terminal/browser/PDF markdown and LaTeX previews.
|
|
515
|
+
- **Context Mode Research / Optional Power User Tooling**: **[`context-mode`](https://github.com/mksglu/context-mode)** by **Mert Koseoğlu** is credited as an external context-window and session-continuity project. It is not bundled as a Takomi default; users can install/evaluate it separately under its own license.
|
|
486
516
|
- **Git Commit Generation**: From the **[`kilocode`](https://github.com/Kilo-Org/kilocode)** repository by **Kilo-Org** (specifically, [git-commit-generation.md](https://github.com/Kilo-Org/kilocode/blob/main/packages/kilo-docs/pages/code-with-ai/features/git-commit-generation.md)) — enabling automated, high-quality conventional git commit messages based on staged changes.
|
|
487
517
|
|
|
488
518
|
## 📄 License
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "takomi",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.28",
|
|
4
4
|
"description": "🎯 Stop wrestling with AI. Start building with purpose. The artisan's toolkit for agent workflows, Codex skills, and original Takomi capabilities like 21st.dev integration.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
".pi/takomi/policies"
|
|
23
23
|
],
|
|
24
24
|
"scripts": {
|
|
25
|
-
"
|
|
25
|
+
"postinstall": "node src/postinstall.js",
|
|
26
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
27
|
+
"test:skills": "node scripts/test-skill-selection.js"
|
|
26
28
|
},
|
|
27
29
|
"repository": {
|
|
28
30
|
"type": "git",
|