cxstatusline 0.4.0 → 0.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/README.md +10 -56
- package/dist/cxstatusline.js +51 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -101,66 +101,20 @@ cxstatusline
|
|
|
101
101
|
The bare command opens the configuration TUI in an interactive terminal. Choose widgets, colors
|
|
102
102
|
and themes, preview, then save explicitly or press Ctrl+S. Settings live at
|
|
103
103
|
`~/.config/cxstatusline/settings.json` (or your XDG config location).
|
|
104
|
-
Claude-only widgets without a Codex data source are not included; see the widget inventory in the
|
|
105
|
-
project notes for the full list and reasons.
|
|
106
104
|
|
|
107
105
|
For scripts, `cxstatusline render` reads a versioned JSON payload on stdin and prints ANSI rows;
|
|
108
106
|
it never opens the TUI.
|
|
109
107
|
|
|
110
|
-
##
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
### Custom Command execution and caching
|
|
121
|
-
|
|
122
|
-
Custom Command runs `commandPath` through your shell (`/bin/sh -c`) with Codex's environment, in
|
|
123
|
-
the session's working directory. It receives the Codex status payload as JSON on stdin plus `terminal_width`.
|
|
124
|
-
Only the first non-empty line is shown; stderr is discarded. Set `preserveColors` (key `p`) to keep
|
|
125
|
-
the command's own colour codes; other escape sequences and control characters are always removed. Configured
|
|
126
|
-
background colours apply in both render modes and survive resets within the command output. `maxWidth`
|
|
127
|
-
(key `w`) truncates with an ellipsis. The TUI preview never runs commands. Imported presets list their
|
|
128
|
-
commands before you confirm.
|
|
129
|
-
|
|
130
|
-
#### Synchronous execution (default)
|
|
131
|
-
|
|
132
|
-
When `refreshMs` is unset (or `0`), commands run synchronously on **every footer redraw** (up to five
|
|
133
|
-
times a second while Codex streams).
|
|
134
|
-
|
|
135
|
-
Codex kills the whole statusline renderer after one second and keeps the previous frame, so
|
|
136
|
-
cxstatusline caps each synchronous command at **300 ms by default, 600 ms maximum** (`timeout`, editor key
|
|
137
|
-
`t`), and all commands on a render share a 600 ms budget. Over budget shows `[Budget]`; a slow
|
|
138
|
-
command shows `[Timeout]`, a failing one `[Exit: N]` or `[Cmd not found]`. Commands terminated by
|
|
139
|
-
external signals before the deadline report `[Signal: <name>]` rather than `[Timeout]`. Keep synchronous
|
|
140
|
-
commands cheap and local: `git status -s | wc -l` and `date +%H:%M` are good fits; network calls are not.
|
|
141
|
-
|
|
142
|
-
#### Background caching (`refreshMs`)
|
|
143
|
-
|
|
144
|
-
For commands that take longer or should not run on every redraw, configure `refreshMs` (key `f`).
|
|
145
|
-
|
|
146
|
-
- **Background refresh:** When `refreshMs` is set, rendering reads the latest result from disk and never
|
|
147
|
-
blocks the statusline or consumes renderer timeout budget. When an entry is due for an update,
|
|
148
|
-
cxstatusline spawns a detached background process to refresh it; the refresh outlives the render.
|
|
149
|
-
- **Cold start:** On the very first render before the initial background run completes, the widget shows
|
|
150
|
-
`[Loading]`.
|
|
151
|
-
- **Failures and timeouts:** A failing background command caches its exit code or error token; if a
|
|
152
|
-
background refresh stays outstanding or fails beyond 60 seconds, the widget settles on `[Error]` and
|
|
153
|
-
keeps showing `[Error]` across subsequent renders until a refresh succeeds.
|
|
154
|
-
- **Cache location:** Cached documents live under `~/.cache/cxstatusline/commands/` (or
|
|
155
|
-
`$XDG_CACHE_HOME/cxstatusline/commands/`). Deleting this cache directory at any time is completely
|
|
156
|
-
safe; entries are re-created automatically.
|
|
157
|
-
- **Eviction:** Cache entries and temporary files expire and are automatically evicted after 7 days.
|
|
158
|
-
- **Session sharing constraint:** The cache key is derived from `(command, cwd)`, so every Codex
|
|
159
|
-
session running in the same working directory shares one cache entry and one payload (the payload
|
|
160
|
-
written by whichever session triggered the refresh). `refreshMs` is intended for commands whose
|
|
161
|
-
output does not depend on specific session payload details.
|
|
162
|
-
- **Pipeline processes:** As with synchronous mode, `shell: true` terminates `/bin/sh` on timeout,
|
|
163
|
-
so child processes spawned inside a shell pipeline can outlive the cap. Avoid long-running pipelines.
|
|
108
|
+
## Widgets
|
|
109
|
+
|
|
110
|
+
34 widgets: model and thinking effort, Git branch and changes, context and token counts, token speed,
|
|
111
|
+
weekly usage and reset, session clock and name, working directory, terminal width, memory, plus three
|
|
112
|
+
custom widgets that show your own text, symbol, or the output of a shell command.
|
|
113
|
+
|
|
114
|
+
Type IDs match ccstatusline's, so a ccstatusline preset imports without translation.
|
|
115
|
+
|
|
116
|
+
👉 The full catalog, and how Custom Command handles timeouts, colours and background caching, are in
|
|
117
|
+
the **[Usage guide](docs/usage.md)**.
|
|
164
118
|
|
|
165
119
|
## Update
|
|
166
120
|
|
package/dist/cxstatusline.js
CHANGED
|
@@ -55203,6 +55203,47 @@ class GitBranchWidget {
|
|
|
55203
55203
|
return true;
|
|
55204
55204
|
}
|
|
55205
55205
|
}
|
|
55206
|
+
// src/utils/git.ts
|
|
55207
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
55208
|
+
function parseDiffShortStat(stat) {
|
|
55209
|
+
const insertMatch = /(\d+)\s+insertions?/.exec(stat);
|
|
55210
|
+
const deleteMatch = /(\d+)\s+deletions?/.exec(stat);
|
|
55211
|
+
return {
|
|
55212
|
+
additions: insertMatch?.[1] ? parseInt(insertMatch[1], 10) : 0,
|
|
55213
|
+
deletions: deleteMatch?.[1] ? parseInt(deleteMatch[1], 10) : 0
|
|
55214
|
+
};
|
|
55215
|
+
}
|
|
55216
|
+
var defaultGitRunner = (args, cwd2) => {
|
|
55217
|
+
const result2 = spawnSync2("git", args, {
|
|
55218
|
+
cwd: cwd2,
|
|
55219
|
+
encoding: "utf8",
|
|
55220
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
55221
|
+
timeout: 300,
|
|
55222
|
+
env: { ...process.env, GIT_OPTIONAL_LOCKS: "0" },
|
|
55223
|
+
windowsHide: true
|
|
55224
|
+
});
|
|
55225
|
+
if (result2.error || result2.status !== 0) {
|
|
55226
|
+
throw result2.error ?? new Error(`git exited with status ${result2.status}`);
|
|
55227
|
+
}
|
|
55228
|
+
return result2.stdout ?? "";
|
|
55229
|
+
};
|
|
55230
|
+
function getGitDiffChanges(cwd2, runner = defaultGitRunner) {
|
|
55231
|
+
if (!cwd2)
|
|
55232
|
+
return null;
|
|
55233
|
+
try {
|
|
55234
|
+
const unstaged = runner(["diff", "--no-ext-diff", "--shortstat"], cwd2);
|
|
55235
|
+
const staged = runner(["diff", "--cached", "--no-ext-diff", "--shortstat"], cwd2);
|
|
55236
|
+
const unstagedCounts = parseDiffShortStat(unstaged);
|
|
55237
|
+
const stagedCounts = parseDiffShortStat(staged);
|
|
55238
|
+
return {
|
|
55239
|
+
additions: unstagedCounts.additions + stagedCounts.additions,
|
|
55240
|
+
deletions: unstagedCounts.deletions + stagedCounts.deletions
|
|
55241
|
+
};
|
|
55242
|
+
} catch {
|
|
55243
|
+
return null;
|
|
55244
|
+
}
|
|
55245
|
+
}
|
|
55246
|
+
|
|
55206
55247
|
// src/widgets/GitChanges.ts
|
|
55207
55248
|
class GitChangesWidget {
|
|
55208
55249
|
getDefaultColor() {
|
|
@@ -55226,7 +55267,10 @@ class GitChangesWidget {
|
|
|
55226
55267
|
render(item, context, _settings) {
|
|
55227
55268
|
if (context.isPreview)
|
|
55228
55269
|
return "(+42,-10)";
|
|
55229
|
-
const
|
|
55270
|
+
const cwd2 = context.data.session?.cwd ?? context.data.session?.project_root;
|
|
55271
|
+
const shouldCheckLive = Boolean(context.commandCacheDir || context.liveGit || !context.data.git?.changes);
|
|
55272
|
+
const liveChanges = shouldCheckLive ? getGitDiffChanges(cwd2) : null;
|
|
55273
|
+
const changes2 = liveChanges ?? context.data.git?.changes;
|
|
55230
55274
|
if (!changes2)
|
|
55231
55275
|
return isHideStateEnabled(item, NO_GIT_HIDEABLE_STATE) ? null : "(no git)";
|
|
55232
55276
|
return "(+" + changes2.additions + ",-" + changes2.deletions + ")";
|
|
@@ -58152,19 +58196,19 @@ function runRefreshCommand(cacheKey2, deps) {
|
|
|
58152
58196
|
return 0;
|
|
58153
58197
|
}
|
|
58154
58198
|
// src/version-info.ts
|
|
58155
|
-
var VERSION = "0.4.
|
|
58156
|
-
var SOURCE_COMMIT = /^[0-9a-f]{40}$/.test("
|
|
58199
|
+
var VERSION = "0.4.1";
|
|
58200
|
+
var SOURCE_COMMIT = /^[0-9a-f]{40}$/.test("d5cfa7430d7fdb52a032c51c289131d04f714dd4") ? "d5cfa7430d7fdb52a032c51c289131d04f714dd4" : null;
|
|
58157
58201
|
var SOURCE_DIRTY = false;
|
|
58158
58202
|
|
|
58159
58203
|
// src/context.ts
|
|
58160
58204
|
import { existsSync as existsSync3, realpathSync } from "node:fs";
|
|
58161
|
-
import { spawnSync as
|
|
58205
|
+
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
58162
58206
|
import { dirname as dirname5, join as join7 } from "node:path";
|
|
58163
58207
|
|
|
58164
58208
|
// src/patch/preflight.ts
|
|
58165
58209
|
import { accessSync, constants as constants2, existsSync as existsSync2, statfsSync } from "node:fs";
|
|
58166
58210
|
import { dirname as dirname4, join as join6 } from "node:path";
|
|
58167
|
-
import { spawnSync as
|
|
58211
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
58168
58212
|
var MIN_FREE_BYTES = 20 * 1024 ** 3;
|
|
58169
58213
|
var MIN_STAGING_FREE_BYTES = 2 * 1024 ** 3;
|
|
58170
58214
|
var REQUIRED_TOOLCHAIN = "1.95.0";
|
|
@@ -58246,7 +58290,7 @@ function realDeps() {
|
|
|
58246
58290
|
return {
|
|
58247
58291
|
which: whichReal,
|
|
58248
58292
|
run: (cmd, args, opts) => {
|
|
58249
|
-
const r =
|
|
58293
|
+
const r = spawnSync3(cmd, args, { encoding: "utf8", cwd: opts?.cwd });
|
|
58250
58294
|
return { status: r.status, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
|
|
58251
58295
|
},
|
|
58252
58296
|
freeBytes: (path) => {
|
|
@@ -58268,7 +58312,7 @@ function realContext(env3, io) {
|
|
|
58268
58312
|
const sccache = deps.which("sccache");
|
|
58269
58313
|
const run = (cmd, args, opts) => {
|
|
58270
58314
|
const baseEnv = opts?.env ? { ...process.env, ...opts.env } : process.env;
|
|
58271
|
-
const r =
|
|
58315
|
+
const r = spawnSync4(cmd, args, {
|
|
58272
58316
|
encoding: "utf8",
|
|
58273
58317
|
cwd: opts?.cwd,
|
|
58274
58318
|
stdio: opts?.interactive ? "inherit" : "pipe",
|