little-coder 1.4.0 → 1.4.1
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/extensions/branding/index.ts +17 -4
- package/CHANGELOG.md +14 -0
- package/bin/little-coder.mjs +53 -2
- package/package.json +1 -1
|
@@ -61,10 +61,13 @@ function setTitleForCwd(setTitle: (t: string) => void, cwd: string): void {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
export default function (pi: ExtensionAPI) {
|
|
64
|
-
// session_start fires on initial load AND on every session switch
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
//
|
|
64
|
+
// session_start fires on initial load AND on every session switch.
|
|
65
|
+
// Pi's updateTerminalTitle() runs in init() *after* session_start, so our
|
|
66
|
+
// setTitle here gets clobbered back to "π - <cwd>". We reassert the title
|
|
67
|
+
// on turn_start and turn_end too — pi calls updateTerminalTitle at the same
|
|
68
|
+
// points (interactive-mode.js:1179, 1346, 3971), so re-setting on every
|
|
69
|
+
// turn keeps our "little-coder - <cwd>" winning for the duration of a
|
|
70
|
+
// session.
|
|
68
71
|
pi.on("session_start", async (_event, ctx) => {
|
|
69
72
|
if (!ctx.hasUI) return;
|
|
70
73
|
|
|
@@ -77,4 +80,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
77
80
|
|
|
78
81
|
setTitleForCwd(ctx.ui.setTitle.bind(ctx.ui), ctx.cwd);
|
|
79
82
|
});
|
|
83
|
+
|
|
84
|
+
pi.on("turn_start", async (_event, ctx) => {
|
|
85
|
+
if (!ctx.hasUI) return;
|
|
86
|
+
setTitleForCwd(ctx.ui.setTitle.bind(ctx.ui), ctx.cwd);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
pi.on("turn_end", async (_event, ctx) => {
|
|
90
|
+
if (!ctx.hasUI) return;
|
|
91
|
+
setTitleForCwd(ctx.ui.setTitle.bind(ctx.ui), ctx.cwd);
|
|
92
|
+
});
|
|
80
93
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to little-coder are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and little-coder's public interface (CLI, providers, tools, skills) follows semver starting at `v0.0.1` post-rename.
|
|
4
4
|
|
|
5
|
+
## [v1.4.1] — 2026-05-16
|
|
6
|
+
|
|
7
|
+
Wire fix for the v1.4.0 startup rebrand. The `[Extensions]` block was still showing for users running from outside the repo root.
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- **`quietStartup` is now actually applied for end users.** v1.4.0 set `"quietStartup": true` in our shipped `.pi/settings.json`, but pi reads global settings from `~/.pi/agent/settings.json` (or the dir pointed to by `PI_CODING_AGENT_DIR`) — not from the npm package's internal `.pi/`. So users running little-coder from anywhere outside the repo root still saw pi's full extension/skill/prompt inventory on startup. The launcher (`bin/little-coder.mjs`) now non-destructively merges `quietStartup: true` into the user's actual global pi settings on every launch, preserving any other keys. To see the inventory anyway: `little-coder --verbose`.
|
|
11
|
+
- **Terminal title now reasserts on `turn_start` / `turn_end`.** Pi's `updateTerminalTitle()` fires multiple times during a session (init, provider count update, session-name change) and was clobbering our `setTitle("little-coder - <cwd>")` back to `π - <cwd>`. The branding extension now re-applies the title on every turn boundary, so after the first prompt the title stays correct.
|
|
12
|
+
|
|
13
|
+
### Notes for upgraders
|
|
14
|
+
- Existing keys in your `~/.pi/agent/settings.json` are preserved. The launcher only writes `quietStartup` if it isn't already `true`. If you'd previously set `"quietStartup": false` deliberately, you'll see the launcher overwrite it back to `true` — set `--verbose` per-invocation to see the inventory without disabling the global default.
|
|
15
|
+
- No CLI flag, skill-pack, or API changes.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
5
19
|
## [v1.4.0] — 2026-05-16
|
|
6
20
|
|
|
7
21
|
Startup UI rebrand. The TUI's opening frame now reads as **little-coder**, not as pi. Pi remains the substrate; the chrome above it just stops pretending it's the product.
|
package/bin/little-coder.mjs
CHANGED
|
@@ -4,7 +4,15 @@
|
|
|
4
4
|
// custom extension wired in — works from any working directory.
|
|
5
5
|
|
|
6
6
|
import { spawn } from "node:child_process";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
existsSync,
|
|
9
|
+
mkdirSync,
|
|
10
|
+
readdirSync,
|
|
11
|
+
readFileSync,
|
|
12
|
+
statSync,
|
|
13
|
+
writeFileSync,
|
|
14
|
+
} from "node:fs";
|
|
15
|
+
import { homedir } from "node:os";
|
|
8
16
|
import { dirname, join, resolve } from "node:path";
|
|
9
17
|
import { fileURLToPath } from "node:url";
|
|
10
18
|
import { checkForUpdate } from "./update-check.mjs";
|
|
@@ -98,7 +106,50 @@ if (process.env.PI_SKIP_VERSION_CHECK === undefined) {
|
|
|
98
106
|
process.env.PI_SKIP_VERSION_CHECK = "1";
|
|
99
107
|
}
|
|
100
108
|
|
|
101
|
-
// ---- 8.
|
|
109
|
+
// ---- 8. Force pi's global quietStartup so the loaded-resources block stays hidden ----
|
|
110
|
+
// Pi's interactive mode dumps an [Extensions] / [Skills] / [Prompts] block on
|
|
111
|
+
// every launch unless `quietStartup: true` is set in its global settings
|
|
112
|
+
// (~/.pi/agent/settings.json). Our shipped .pi/settings.json doesn't reach pi
|
|
113
|
+
// because pi reads from <cwd>/.pi/settings.json (project) or <agentDir>/settings.json
|
|
114
|
+
// (global), neither of which is our npm-installed package dir. So the launcher
|
|
115
|
+
// non-destructively merges quietStartup: true into the user's actual global
|
|
116
|
+
// settings file. Existing keys are preserved. To see the full inventory, run
|
|
117
|
+
// `little-coder --verbose` — pi's verbose flag overrides quietStartup.
|
|
118
|
+
try {
|
|
119
|
+
const agentDirEnv = process.env.PI_CODING_AGENT_DIR;
|
|
120
|
+
let agentDir;
|
|
121
|
+
if (agentDirEnv && agentDirEnv.trim().length > 0) {
|
|
122
|
+
agentDir = agentDirEnv === "~"
|
|
123
|
+
? homedir()
|
|
124
|
+
: agentDirEnv.startsWith("~/")
|
|
125
|
+
? homedir() + agentDirEnv.slice(1)
|
|
126
|
+
: agentDirEnv;
|
|
127
|
+
} else {
|
|
128
|
+
agentDir = join(homedir(), ".pi", "agent");
|
|
129
|
+
}
|
|
130
|
+
mkdirSync(agentDir, { recursive: true });
|
|
131
|
+
const globalSettingsPath = join(agentDir, "settings.json");
|
|
132
|
+
let globalSettings = {};
|
|
133
|
+
if (existsSync(globalSettingsPath)) {
|
|
134
|
+
try {
|
|
135
|
+
const parsed = JSON.parse(readFileSync(globalSettingsPath, "utf-8"));
|
|
136
|
+
if (parsed && typeof parsed === "object") globalSettings = parsed;
|
|
137
|
+
} catch {
|
|
138
|
+
// Corrupted JSON — start fresh rather than throw. Pi would have rejected it too.
|
|
139
|
+
globalSettings = {};
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (globalSettings.quietStartup !== true) {
|
|
143
|
+
globalSettings.quietStartup = true;
|
|
144
|
+
writeFileSync(globalSettingsPath, JSON.stringify(globalSettings, null, 2));
|
|
145
|
+
}
|
|
146
|
+
} catch {
|
|
147
|
+
// Best-effort. If we can't write the settings (read-only HOME, etc.) pi
|
|
148
|
+
// falls back to its built-in defaults — the [Extensions] block will show
|
|
149
|
+
// but everything else still works.
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// ---- 9. Spawn pi in the user's cwd ----
|
|
102
153
|
const [spawnCmd, spawnArgs] = isWindows
|
|
103
154
|
? ["cmd.exe", ["/c", piBin, ...piArgs]]
|
|
104
155
|
: [piBin, piArgs];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "little-coder",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "A pi-based coding agent optimized for small local language models. Reproduces the whitepaper's scaffold-model-fit adaptations as pi extensions.",
|
|
5
5
|
"homepage": "https://github.com/itayinbarr/little-coder",
|
|
6
6
|
"repository": {
|