@b0tts/template-dev-installer 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.mjs +129 -0
- package/files/.agents/skills/_explain-it-v1-disabled/SKILL.md +86 -0
- package/files/.agents/skills/close/SKILL.md +112 -0
- package/files/.agents/skills/closev2/REFERENCE.md +194 -0
- package/files/.agents/skills/closev2/SKILL.md +84 -0
- package/files/.agents/skills/create-nav-guide/SKILL.md +39 -0
- package/files/.agents/skills/docs-mcp/SKILL.md +91 -0
- package/files/.agents/skills/explain-it-v2/REFERENCE.md +213 -0
- package/files/.agents/skills/explain-it-v2/SKILL.md +133 -0
- package/files/.agents/skills/grill-me/SKILL.md +10 -0
- package/files/.agents/skills/grill-with-docs/ADR-FORMAT.md +47 -0
- package/files/.agents/skills/grill-with-docs/CONTEXT-FORMAT.md +63 -0
- package/files/.agents/skills/grill-with-docs/SKILL.md +88 -0
- package/files/.agents/skills/handoff/SKILL.md +34 -0
- package/files/.agents/skills/improve-codebase-architecture/DEEPENING.md +37 -0
- package/files/.agents/skills/improve-codebase-architecture/HTML-REPORT.md +123 -0
- package/files/.agents/skills/improve-codebase-architecture/INTERFACE-DESIGN.md +44 -0
- package/files/.agents/skills/improve-codebase-architecture/LANGUAGE.md +53 -0
- package/files/.agents/skills/improve-codebase-architecture/SKILL.md +81 -0
- package/files/.agents/skills/karpathy-guidelines/SKILL.md +0 -0
- package/files/.agents/skills/regenerate-minecraft-world/SKILL.md +46 -0
- package/files/.agents/skills/to-prd/SKILL.md +76 -0
- package/files/.agents/skills/tutorial/SKILL.md +43 -0
- package/files/.agents/skills/write-a-skill/SKILL.md +117 -0
- package/files/.agents/skills/zoom-out/SKILL.md +7 -0
- package/files/AGENTS.md +40 -0
- package/files/README.md +245 -0
- package/files/opencode/opencode.json +178 -0
- package/files/opencode/plugins/Notifications.js +66 -0
- package/files/opencode/settings.json +1 -0
- package/files/pi/extensions/context-tiers.ts +250 -0
- package/files/pi/mcp.json +12 -0
- package/files/pi/settings.json +13 -0
- package/package.json +23 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Tiers — 3-line custom footer with tiered context + cost colours.
|
|
3
|
+
*
|
|
4
|
+
* Layout:
|
|
5
|
+
* Line 1: /full/path/to/project
|
|
6
|
+
* Line 2: ↑tokens ↓tokens 62,000/200,000 (31%)
|
|
7
|
+
* Line 3: model-id (branch) $0.023 ext-status…
|
|
8
|
+
*
|
|
9
|
+
* Context numbers (line 2): 16 tiers — dim-gray → animated rainbow.
|
|
10
|
+
* Cost number (line 3): 18 tiers — dim-gray → copper→bronze→
|
|
11
|
+
* green→silver→teal→blue→purple→ruby→orange→gold→diamond◆→
|
|
12
|
+
* bright-gold✦→rainbow★.
|
|
13
|
+
*
|
|
14
|
+
* All non-tier text uses uniform ANSI-256 grays in the same colour
|
|
15
|
+
* space as the tier colours so everything sits on one visual plane.
|
|
16
|
+
*
|
|
17
|
+
* Unknown / post-compaction context → `???` (reverse video), no %.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import type { AssistantMessage } from "@earendil-works/pi-ai";
|
|
21
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
22
|
+
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
23
|
+
|
|
24
|
+
// ── Number formatting ────────────────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
function fmt(n: number): string {
|
|
27
|
+
return String(Math.floor(n)).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ── ANSI escape helpers ──────────────────────────────────────────────────────
|
|
31
|
+
|
|
32
|
+
const BOLD = "\x1b[1m";
|
|
33
|
+
const UNDERLINE = "\x1b[4m";
|
|
34
|
+
const REVERSE = "\x1b[7m";
|
|
35
|
+
const REV_OFF = "\x1b[27m";
|
|
36
|
+
const RESET = "\x1b[0m";
|
|
37
|
+
|
|
38
|
+
function fg(n: number): string { return `\x1b[38;5;${n}m`; }
|
|
39
|
+
|
|
40
|
+
/** Uniform ANSI-256 gray helpers — same colour-space as the tier colours */
|
|
41
|
+
const GRAY = {
|
|
42
|
+
path: fg(245), // medium — project directory
|
|
43
|
+
labels: fg(245), // medium — ↑ ↓ $ symbols
|
|
44
|
+
stats: fg(247), // lighter — input/output/cost numbers
|
|
45
|
+
pct: fg(245), // medium — (31%)
|
|
46
|
+
model: fg(242), // dim — model id, branch, ext statuses
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// ── Tier definitions (16 tiers, absolute tokens) ─────────────────────────────
|
|
50
|
+
|
|
51
|
+
interface Tier {
|
|
52
|
+
max: number;
|
|
53
|
+
color: number;
|
|
54
|
+
bold?: boolean;
|
|
55
|
+
underline?: boolean;
|
|
56
|
+
sparkle?: boolean;
|
|
57
|
+
diamond?: boolean; // always-on ◆ (no flicker)
|
|
58
|
+
rainbow?: boolean;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const TIERS: Tier[] = [
|
|
62
|
+
{ max: 1_000, color: 242 }, // 1: dim gray
|
|
63
|
+
{ max: 3_000, color: 252 }, // 2: white
|
|
64
|
+
{ max: 7_000, color: 249 }, // 3: light gray
|
|
65
|
+
{ max: 15_000, color: 108 }, // 4: light green
|
|
66
|
+
{ max: 30_000, color: 41 }, // 5: green
|
|
67
|
+
{ max: 50_000, color: 43 }, // 6: teal
|
|
68
|
+
{ max: 75_000, color: 51 }, // 7: cyan
|
|
69
|
+
{ max: 100_000, color: 33 }, // 8: blue
|
|
70
|
+
{ max: 200_000, color: 39 }, // 9: bright blue
|
|
71
|
+
{ max: 500_000, color: 201 }, // 10: magenta
|
|
72
|
+
{ max: 1_000_000, color: 93 }, // 11: purple
|
|
73
|
+
{ max: 10_000_000, color: 208 }, // 12: orange
|
|
74
|
+
{ max: 100_000_000, color: 202, bold: true }, // 13: amber bold
|
|
75
|
+
{ max: 500_000_000, color: 220, bold: true, underline: true }, // 14: gold b+u
|
|
76
|
+
{ max: 999_999_999, color: 226, bold: true, underline: true, // 15: bright gold ✦
|
|
77
|
+
sparkle: true },
|
|
78
|
+
{ max: Infinity, rainbow: true, bold: true }, // 16: rainbow ★
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
const RAINBOW = [196, 208, 220, 226, 46, 51, 39, 33, 93, 201];
|
|
82
|
+
|
|
83
|
+
// ── Cost tier definitions (18 tiers, $0 → $1 000 000) ────────────────────────
|
|
84
|
+
|
|
85
|
+
const COST_TIERS: Tier[] = [
|
|
86
|
+
{ max: 0.01, color: 242 }, // 1: dim gray
|
|
87
|
+
{ max: 0.05, color: 248 }, // 2: light gray
|
|
88
|
+
{ max: 0.10, color: 252 }, // 3: white
|
|
89
|
+
{ max: 0.25, color: 137 }, // 4: copper
|
|
90
|
+
{ max: 0.50, color: 179 }, // 5: bronze
|
|
91
|
+
{ max: 1.00, color: 143 }, // 6: sage green
|
|
92
|
+
{ max: 2, color: 71 }, // 7: deep green
|
|
93
|
+
{ max: 5, color: 35 }, // 8: bright green
|
|
94
|
+
{ max: 10, color: 247 }, // 9: silver
|
|
95
|
+
{ max: 25, color: 43 }, // 10: teal
|
|
96
|
+
{ max: 50, color: 39 }, // 11: blue
|
|
97
|
+
{ max: 100, color: 134 }, // 12: purple
|
|
98
|
+
{ max: 500, color: 196 }, // 13: ruby red
|
|
99
|
+
{ max: 1_000, color: 202, bold: true }, // 14: deep orange bold
|
|
100
|
+
{ max: 10_000, color: 220, bold: true, underline: true }, // 15: gold b+u
|
|
101
|
+
{ max: 100_000, color: 255, bold: true, underline: true, // 16: diamond white ◆
|
|
102
|
+
diamond: true },
|
|
103
|
+
{ max: 999_999, color: 226, bold: true, underline: true, // 17: bright gold ✦
|
|
104
|
+
sparkle: true },
|
|
105
|
+
{ max: Infinity, rainbow: true, bold: true }, // 18: rainbow ★
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
// ── Context tier helpers ─────────────────────────────────────────────────────
|
|
109
|
+
|
|
110
|
+
function getCtxTier(n: number): Tier {
|
|
111
|
+
for (const t of TIERS) if (n <= t.max) return t;
|
|
112
|
+
return TIERS[TIERS.length - 1]!;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function styledCtx(n: number, tier: Tier, frame: number): string {
|
|
116
|
+
return applyTierStyle(fmt(n), tier, frame);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ── Cost tier helpers ────────────────────────────────────────────────────────
|
|
120
|
+
|
|
121
|
+
function getCostTier(n: number): Tier {
|
|
122
|
+
for (const t of COST_TIERS) if (n <= t.max) return t;
|
|
123
|
+
return COST_TIERS[COST_TIERS.length - 1]!;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function styledCost(n: number, tier: Tier, frame: number): string {
|
|
127
|
+
return applyTierStyle(`$${n.toFixed(3)}`, tier, frame);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ── Shared style application ─────────────────────────────────────────────────
|
|
131
|
+
|
|
132
|
+
function applyTierStyle(text: string, tier: Tier, frame: number): string {
|
|
133
|
+
let color: number;
|
|
134
|
+
let prefix = "";
|
|
135
|
+
let suffix = "";
|
|
136
|
+
|
|
137
|
+
if (tier.rainbow) {
|
|
138
|
+
color = RAINBOW[frame % RAINBOW.length]!;
|
|
139
|
+
suffix = " ★";
|
|
140
|
+
} else if (tier.sparkle && Math.random() > 0.5) {
|
|
141
|
+
color = tier.color;
|
|
142
|
+
prefix = "✦ ";
|
|
143
|
+
} else if (tier.diamond) {
|
|
144
|
+
color = tier.color;
|
|
145
|
+
prefix = "◆ ";
|
|
146
|
+
} else {
|
|
147
|
+
color = tier.color;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
let style = fg(color);
|
|
151
|
+
if (tier.bold) style += BOLD;
|
|
152
|
+
if (tier.underline) style += UNDERLINE;
|
|
153
|
+
|
|
154
|
+
return `${style}${prefix}${text}${suffix}${RESET}`;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ── Extension entry ──────────────────────────────────────────────────────────
|
|
158
|
+
|
|
159
|
+
export default function (pi: ExtensionAPI) {
|
|
160
|
+
pi.on("session_start", (_event, ctx) => {
|
|
161
|
+
let frame = 0;
|
|
162
|
+
let animTimer: ReturnType<typeof setInterval> | null = null;
|
|
163
|
+
|
|
164
|
+
ctx.ui.setFooter((tui, _theme, footerData) => {
|
|
165
|
+
if (!animTimer) {
|
|
166
|
+
animTimer = setInterval(() => { frame++; tui.requestRender(); }, 800);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const unsub = footerData.onBranchChange(() => tui.requestRender());
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
dispose: () => {
|
|
173
|
+
unsub();
|
|
174
|
+
if (animTimer) { clearInterval(animTimer); animTimer = null; }
|
|
175
|
+
},
|
|
176
|
+
invalidate: () => {},
|
|
177
|
+
|
|
178
|
+
render(width: number): string[] {
|
|
179
|
+
// ── Line 1: project directory ─────────────────────────────────
|
|
180
|
+
const dirLine = `${GRAY.path}${process.cwd()}${RESET}`;
|
|
181
|
+
|
|
182
|
+
// ── Line 2: token stats + context usage ───────────────────────
|
|
183
|
+
let input = 0, output = 0, cost = 0;
|
|
184
|
+
for (const e of ctx.sessionManager.getBranch()) {
|
|
185
|
+
if (e.type === "message" && e.message.role === "assistant") {
|
|
186
|
+
const msg = e.message as AssistantMessage;
|
|
187
|
+
input += msg.usage.input;
|
|
188
|
+
output += msg.usage.output;
|
|
189
|
+
cost += msg.usage.cost.total;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const statsStr =
|
|
194
|
+
`${GRAY.labels}↑${GRAY.stats}${fmt(input)}` +
|
|
195
|
+
`${GRAY.labels} ↓${GRAY.stats}${fmt(output)}${RESET}`;
|
|
196
|
+
|
|
197
|
+
const cu = ctx.getContextUsage();
|
|
198
|
+
let ctxStr = "";
|
|
199
|
+
|
|
200
|
+
if (cu) {
|
|
201
|
+
const usedOk = cu.tokens != null;
|
|
202
|
+
const maxOk = cu.contextWindow > 0;
|
|
203
|
+
|
|
204
|
+
const usedStr = usedOk
|
|
205
|
+
? styledCtx(cu.tokens!, getCtxTier(cu.tokens!), frame)
|
|
206
|
+
: `${REVERSE}???${REV_OFF}`;
|
|
207
|
+
|
|
208
|
+
const maxStr = maxOk
|
|
209
|
+
? styledCtx(cu.contextWindow, getCtxTier(cu.contextWindow), frame)
|
|
210
|
+
: `${REVERSE}???${REV_OFF}`;
|
|
211
|
+
|
|
212
|
+
const slash = usedOk && maxOk ? "/" : " / ";
|
|
213
|
+
|
|
214
|
+
// Percentage: only show when both numbers are valid
|
|
215
|
+
const pctStr = (usedOk && maxOk && cu.percent != null)
|
|
216
|
+
? ` ${GRAY.pct}(${cu.percent.toFixed(2)}%)${RESET}`
|
|
217
|
+
: "";
|
|
218
|
+
|
|
219
|
+
ctxStr = `${usedStr}${GRAY.stats}${slash}${maxStr}${pctStr}`;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const line2parts = [statsStr, ctxStr].filter(Boolean);
|
|
223
|
+
const line2 = line2parts.join(" ");
|
|
224
|
+
|
|
225
|
+
// ── Line 3: model + branch + cost + extension statuses ────────
|
|
226
|
+
const branch = footerData.getGitBranch();
|
|
227
|
+
const modelText = `${ctx.model?.id || "no-model"}${branch ? ` (${branch})` : ""}`;
|
|
228
|
+
|
|
229
|
+
const costSty = styledCost(cost, getCostTier(cost), frame);
|
|
230
|
+
const costText = `${costSty}`;
|
|
231
|
+
|
|
232
|
+
const statuses = footerData.getExtensionStatuses();
|
|
233
|
+
let statusText = "";
|
|
234
|
+
if (statuses.size > 0) {
|
|
235
|
+
statusText = " " + [...statuses.values()].join(" ");
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const line3 = `${GRAY.model}${modelText} ${costText}${statusText}${RESET}`;
|
|
239
|
+
|
|
240
|
+
// ── Render ────────────────────────────────────────────────────
|
|
241
|
+
return [
|
|
242
|
+
truncateToWidth(dirLine, width),
|
|
243
|
+
truncateToWidth(line2, width),
|
|
244
|
+
truncateToWidth(line3, width),
|
|
245
|
+
];
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lastChangelogVersion": "0.79.6",
|
|
3
|
+
"theme": "dark",
|
|
4
|
+
"defaultProvider": "deepseek",
|
|
5
|
+
"defaultModel": "deepseek-v4-pro",
|
|
6
|
+
"defaultThinkingLevel": "high",
|
|
7
|
+
"packages": [
|
|
8
|
+
"npm:pi-web-access",
|
|
9
|
+
"npm:pi-subagents",
|
|
10
|
+
"npm:pi-mcp-extension"
|
|
11
|
+
],
|
|
12
|
+
"hideThinkingBlock": false
|
|
13
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@b0tts/template-dev-installer",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Interactive installer for the DevelopmentTemplate — pick Skills, OpenCode, Pi, or install everything at once.",
|
|
6
|
+
"bin": {
|
|
7
|
+
"template-dev-installer": "./cli.mjs"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"cli.mjs",
|
|
11
|
+
"files/"
|
|
12
|
+
],
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@inquirer/prompts": "^5.0.0"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"template",
|
|
18
|
+
"installer",
|
|
19
|
+
"dev-setup",
|
|
20
|
+
"scaffold"
|
|
21
|
+
],
|
|
22
|
+
"license": "MIT"
|
|
23
|
+
}
|