@tommy-ca/lazypi 0.6.5 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/bin/lazypi.mjs +26 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ LazyPi will:
|
|
|
13
13
|
1. Install `pi` for you if it isn't installed yet.
|
|
14
14
|
2. Ask if you want to install all the packages or choose which to install.
|
|
15
15
|
|
|
16
|
-
That setup is the harness core — isolated sub-agents, a structured ask gate, skill visibility, $ skill mention, a long-objective gate, side chat, context budgeting, code simplification review, web research, and
|
|
16
|
+
That setup is the harness core — isolated sub-agents, a structured ask gate, skill visibility, $ skill mention, a long-objective gate, side chat, context budgeting, code simplification review, web research, FFF search, a workflow engine for sub-agent fan-out, and ponytail discipline review. Optional extras (skill arguments, memory, MCP, interactive shell overlays, research loops, themes) install on demand with `pi install`.
|
|
17
17
|
|
|
18
18
|
That's it. Once done - run `pi` and experience a feature rich coding agent experience.
|
|
19
19
|
|
|
@@ -54,6 +54,12 @@ There is nothing to "uninstall" for LazyPi itself — `npx` doesn't leave it aro
|
|
|
54
54
|
|
|
55
55
|
Run the built-in health check with `npx @tommy-ca/lazypi doctor`.
|
|
56
56
|
|
|
57
|
+
**Stale `bunx` after a release?** bun caches resolved package versions, so a
|
|
58
|
+
bare `bunx @tommy-ca/lazypi` can keep serving the previous release until the
|
|
59
|
+
cache is cleared. Run `bun pm cache rm`, pin `@tommy-ca/lazypi@latest`, and
|
|
60
|
+
check `npx @tommy-ca/lazypi --version` to see which release is actually
|
|
61
|
+
running.
|
|
62
|
+
|
|
57
63
|
## Site / docs
|
|
58
64
|
|
|
59
65
|
The site at [lazypi.org](https://lazypi.org) lives in `docs/` and is a Jekyll site compiled by GitHub Pages automatically on push to `master`.
|
package/bin/lazypi.mjs
CHANGED
|
@@ -44,6 +44,8 @@ export const PACKAGES = [
|
|
|
44
44
|
{ id: "simplify", category: "core", source: "npm:pi-simplify", essential: true, description: "Code simplify review", hint: "Reviews recently changed code for clarity, consistency, and maintainability." },
|
|
45
45
|
{ id: "web-access", category: "core", source: "npm:pi-web-access", essential: true, description: "Web search and page fetch", hint: "Built-in web search and URL fetching." },
|
|
46
46
|
{ id: "fff", category: "core", source: "npm:@ff-labs/pi-fff", essential: true, description: "FFF fuzzy search", hint: "Additive fffind / ffgrep / fff-multi-grep beside the built-in tools; /fff-health checks the index." },
|
|
47
|
+
{ id: "dynamic-workflows", category: "core", source: "npm:@quintinshaw/pi-dynamic-workflows", essential: true, description: "Workflow engine", hint: "Fan work out across subagents: /workflows TUI, deep-research, resume, token accounting." },
|
|
48
|
+
{ id: "ponytail", category: "core", source: "npm:@dietrichgebert/ponytail", essential: true, description: "Lazy senior dev mode", hint: "Enforces minimal, stdlib-first code; /ponytail review, audit, and a debt ledger." },
|
|
47
49
|
];
|
|
48
50
|
|
|
49
51
|
// ---------------------------------------------------------------------------
|
|
@@ -96,6 +98,7 @@ function parseArgs(args) {
|
|
|
96
98
|
yes: false,
|
|
97
99
|
help: false,
|
|
98
100
|
badArg: false,
|
|
101
|
+
version: false,
|
|
99
102
|
only: null,
|
|
100
103
|
except: null,
|
|
101
104
|
targets: [],
|
|
@@ -111,6 +114,7 @@ function parseArgs(args) {
|
|
|
111
114
|
const arg = args[i];
|
|
112
115
|
if (arg === "-l" || arg === "--local") flags.local = true;
|
|
113
116
|
else if (arg === "-y" || arg === "--yes") flags.yes = true;
|
|
117
|
+
else if (arg === "-V" || arg === "--version") flags.version = true;
|
|
114
118
|
else if (arg === "-h" || arg === "--help") flags.help = true;
|
|
115
119
|
else if (arg === "--only") flags.only = parseList(args[++i]);
|
|
116
120
|
else if (arg.startsWith("--only=")) flags.only = parseList(arg.slice("--only=".length));
|
|
@@ -185,6 +189,7 @@ ${bold("Install options:")}
|
|
|
185
189
|
-l, --local Install into the current project (.pi/settings.json)
|
|
186
190
|
-y, --yes Skip the picker and any confirmation prompt
|
|
187
191
|
-h, --help Show this help
|
|
192
|
+
-V, --version Show the installed version
|
|
188
193
|
|
|
189
194
|
${bold("Default behaviour:")}
|
|
190
195
|
- Every catalog package is installed (lazy on purpose).
|
|
@@ -193,7 +198,7 @@ ${bold("Default behaviour:")}
|
|
|
193
198
|
- With --yes, --only, or --except the picker is skipped.
|
|
194
199
|
|
|
195
200
|
${bold("Categories:")}
|
|
196
|
-
core the harness control plane: sub-agents, ask gate, skill visibility, $ mention, goal, side chat, context budget, simplify, web research, fff search
|
|
201
|
+
core the harness control plane: sub-agents, workflows, ask gate, skill visibility, $ mention, goal, side chat, context budget, simplify, web research, fff search, ponytail discipline
|
|
197
202
|
Non-catalog extras (pi install npm:<source>): skill-args, memory, mcp,
|
|
198
203
|
interactive-shell, ralph-wiggum, curated-themes (65 dark themes)
|
|
199
204
|
|
|
@@ -210,6 +215,7 @@ ${bold("Examples:")}
|
|
|
210
215
|
// ---------------------------------------------------------------------------
|
|
211
216
|
// Pi / settings plumbing
|
|
212
217
|
// ---------------------------------------------------------------------------
|
|
218
|
+
const VERSION = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
213
219
|
// On Windows, package-manager CLIs and global Node bins are usually `.cmd`
|
|
214
220
|
// shims. Node's child_process docs note that those need to be launched via a
|
|
215
221
|
// shell, so we route spawned commands through the platform shell there while
|
|
@@ -326,8 +332,15 @@ function legacySourcesForPackage(pkg) {
|
|
|
326
332
|
return Array.isArray(pkg.legacySources) ? pkg.legacySources : [];
|
|
327
333
|
}
|
|
328
334
|
|
|
335
|
+
// An installed source matches a catalog source when equal or when it is the
|
|
336
|
+
// same source with a version/pin suffix (npm:pkg vs npm:pkg@x.y.z,
|
|
337
|
+
// git:... vs git:...@sha).
|
|
338
|
+
export function sourcesMatch(catalogSource, installedSource) {
|
|
339
|
+
return catalogSource === installedSource || installedSource.startsWith(`${catalogSource}@`);
|
|
340
|
+
}
|
|
341
|
+
|
|
329
342
|
function isLegacySourceForPackage(pkg, source) {
|
|
330
|
-
return legacySourcesForPackage(pkg).
|
|
343
|
+
return legacySourcesForPackage(pkg).some((legacy) => sourcesMatch(legacy, source));
|
|
331
344
|
}
|
|
332
345
|
|
|
333
346
|
function findLegacyInstalledSources(pkg, installedPiSources) {
|
|
@@ -348,10 +361,11 @@ function removeLegacy(pkg, installedPiSources, local, interactive) {
|
|
|
348
361
|
|
|
349
362
|
function packageInstallStatus(pkg, installedPiSources) {
|
|
350
363
|
const legacySources = findLegacyInstalledSources(pkg, installedPiSources);
|
|
364
|
+
const installed = [...installedPiSources].some((src) => sourcesMatch(pkg.source, src));
|
|
351
365
|
return {
|
|
352
|
-
installed
|
|
366
|
+
installed,
|
|
353
367
|
legacy: legacySources.length > 0,
|
|
354
|
-
present:
|
|
368
|
+
present: installed || legacySources.length > 0,
|
|
355
369
|
};
|
|
356
370
|
}
|
|
357
371
|
|
|
@@ -690,11 +704,12 @@ function cmdStatus(flags) {
|
|
|
690
704
|
return 1;
|
|
691
705
|
}
|
|
692
706
|
|
|
693
|
-
const piCatalogSources = new Set(PACKAGES.flatMap((p) => [p.source, ...legacySourcesForPackage(p)]));
|
|
694
707
|
const installed = PACKAGES.filter((pkg) => packageInstallStatus(pkg, sources).installed);
|
|
695
708
|
const legacy = PACKAGES.filter((pkg) => packageInstallStatus(pkg, sources).legacy);
|
|
696
709
|
const missing = PACKAGES.filter((pkg) => !packageInstallStatus(pkg, sources).present);
|
|
697
|
-
const others = [...sources].filter(
|
|
710
|
+
const others = [...sources].filter(
|
|
711
|
+
(src) => !PACKAGES.some((pkg) => sourcesMatch(pkg.source, src) || isLegacySourceForPackage(pkg, src)),
|
|
712
|
+
);
|
|
698
713
|
|
|
699
714
|
printHeader(`Installed from LazyPi catalog (${installed.length}/${PACKAGES.length}):`);
|
|
700
715
|
if (installed.length === 0) console.log(dim(" none"));
|
|
@@ -849,7 +864,7 @@ async function cmdRemove(flags, targets) {
|
|
|
849
864
|
|
|
850
865
|
const sourcesToRemove = pkg
|
|
851
866
|
? [
|
|
852
|
-
...
|
|
867
|
+
...[...installedSources].filter((src) => sourcesMatch(pkg.source, src)),
|
|
853
868
|
...findLegacyInstalledSources(pkg, installedSources),
|
|
854
869
|
]
|
|
855
870
|
: [source];
|
|
@@ -872,6 +887,10 @@ async function cmdRemove(flags, targets) {
|
|
|
872
887
|
// ---------------------------------------------------------------------------
|
|
873
888
|
async function main() {
|
|
874
889
|
const flags = parseArgs(argv.slice(2));
|
|
890
|
+
if (flags.version) {
|
|
891
|
+
console.log(`@tommy-ca/lazypi ${VERSION}`);
|
|
892
|
+
return 0;
|
|
893
|
+
}
|
|
875
894
|
if (flags.help) {
|
|
876
895
|
printHelp();
|
|
877
896
|
return flags.badArg ? 2 : 0;
|