@nonbot/cli 0.10.16 → 0.10.17
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/CHANGELOG.md +7 -0
- package/dist/commands/logs.js +1 -1
- package/dist/commands/run.js +1 -1
- package/dist/index.js +25 -11
- package/dist/lib/local-status.js +54 -0
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
What changed for the person running the CLI, newest first. Update with
|
|
4
4
|
`npm i -g @nonbot/cli@latest`.
|
|
5
5
|
|
|
6
|
+
## 0.10.17 (2026-11-11)
|
|
7
|
+
|
|
8
|
+
- Typing `nonbot` alone now shows who you're signed in as and whether the daemon is running (or "not signed in — start with: nonbot login"). The login row says "switch account" when you're already signed in.
|
|
9
|
+
- `nonbot help` and `nonbot -h` open with the gradient wordmark.
|
|
10
|
+
- Under the wordmark: "non.bot CLI v… · non.bot MCP v…" — both versions side by side (the MCP's is read from this machine, so the screen stays instant).
|
|
11
|
+
- Help and error messages say "To use" instead of "Usage", which read like a page of your account usage.
|
|
12
|
+
|
|
6
13
|
## 0.10.16 (2026-11-11)
|
|
7
14
|
|
|
8
15
|
- New: `nonbot mcp` shows the non.bot MCP in one place: its version and what's new since, every Claude app and config file it's set up in (and duplicates), a live start with its tool count by group, how much of each conversation its tool list uses, which tools your apps switch off, the token it uses (last four characters only), whether that token is valid and what it may do, and which tools Claude runs without asking. `--quick` skips the live start.
|
package/dist/commands/logs.js
CHANGED
|
@@ -73,7 +73,7 @@ export async function runLogsCommand(args = [], deps = {}) {
|
|
|
73
73
|
const opts = parseArgs(args);
|
|
74
74
|
if (opts.error) {
|
|
75
75
|
errLog(statusRow('✗', 'nonbot logs', opts.error, { stream: process.stderr }) + '\n');
|
|
76
|
-
errLog('
|
|
76
|
+
errLog(' To use: nonbot logs [--limit <n>] [--json] [--follow|-f]\n');
|
|
77
77
|
return 1;
|
|
78
78
|
}
|
|
79
79
|
const entries = await readActivityLog(opts.limit);
|
package/dist/commands/run.js
CHANGED
|
@@ -16,7 +16,7 @@ export async function runRunCommand(args = [], deps = {}) {
|
|
|
16
16
|
}
|
|
17
17
|
const id = args.find((a) => !a.startsWith('-'));
|
|
18
18
|
if (!id) {
|
|
19
|
-
errLog('
|
|
19
|
+
errLog('To use: nonbot run <activation-id> [--headless]\n');
|
|
20
20
|
return 1;
|
|
21
21
|
}
|
|
22
22
|
const auth = await loader();
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ import { runChoirCommand } from './commands/choir.js';
|
|
|
16
16
|
import { runRunMcpCommand } from './commands/run-mcp.js';
|
|
17
17
|
import { runRunPromptHookCommand } from './commands/run-prompt-hook.js';
|
|
18
18
|
import { setActiveProfile } from './lib/auth.js';
|
|
19
|
+
import { localStatus, statusLine, localMcpLabel, versionsLine } from './lib/local-status.js';
|
|
19
20
|
import { header, kvRow, ANSI, isTTY, wordmarkArt, WORDMARK_WIDTH } from './lib/output.js';
|
|
20
21
|
const COMMANDS = [
|
|
21
22
|
{
|
|
@@ -115,14 +116,26 @@ const COMMANDS = [
|
|
|
115
116
|
function printVersion() {
|
|
116
117
|
process.stdout.write(VERSION + '\n');
|
|
117
118
|
}
|
|
118
|
-
function
|
|
119
|
+
function roomForWordmark() {
|
|
120
|
+
const cols = process.stdout.columns ?? 0;
|
|
121
|
+
return cols === 0 || cols >= WORDMARK_WIDTH + 4;
|
|
122
|
+
}
|
|
123
|
+
function printHelp(opts = {}) {
|
|
119
124
|
const tty = isTTY(process.stdout);
|
|
120
125
|
const head = (t) => (tty ? ` ${ANSI.bold}${t}${ANSI.reset}` : ` ${t}`);
|
|
121
126
|
const KEY = 18;
|
|
122
127
|
const lines = [];
|
|
123
|
-
|
|
128
|
+
if (opts.wordmark !== false && roomForWordmark()) {
|
|
129
|
+
lines.push('');
|
|
130
|
+
lines.push(wordmarkArt({ indent: ' ' }));
|
|
131
|
+
lines.push('');
|
|
132
|
+
lines.push(kvRow('', versionsLine(VERSION, opts.mcpLabel ?? 'not checked'), { keyWidth: 8 }));
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
lines.push(header('nonbot', `non.bot CLI · v${VERSION}`));
|
|
136
|
+
}
|
|
124
137
|
lines.push('');
|
|
125
|
-
lines.push(kvRow('
|
|
138
|
+
lines.push(kvRow('To use', 'nonbot <command> [args]', { keyWidth: KEY }));
|
|
126
139
|
const section = (title, group) => {
|
|
127
140
|
lines.push('');
|
|
128
141
|
lines.push(head(title));
|
|
@@ -151,19 +164,20 @@ async function printQuickStart() {
|
|
|
151
164
|
const io = { stdin: process.stdin, stdout: process.stdout };
|
|
152
165
|
const interactive = menuIsInteractive(io);
|
|
153
166
|
const lines = [];
|
|
154
|
-
|
|
155
|
-
if (cols === 0 || cols >= WORDMARK_WIDTH + 4) {
|
|
167
|
+
if (roomForWordmark()) {
|
|
156
168
|
lines.push('');
|
|
157
169
|
lines.push(wordmarkArt({ indent: ' ' }));
|
|
158
170
|
lines.push('');
|
|
159
|
-
lines.push(kvRow('',
|
|
171
|
+
lines.push(kvRow('', versionsLine(VERSION, await localMcpLabel()), { keyWidth: KEY }));
|
|
160
172
|
}
|
|
161
173
|
else {
|
|
162
174
|
lines.push(header('non.bot CLI', `v${VERSION}`));
|
|
163
175
|
}
|
|
176
|
+
const status = await localStatus();
|
|
177
|
+
lines.push(statusLine(status, KEY));
|
|
164
178
|
lines.push('');
|
|
165
|
-
lines.push(kvRow('login', 'sign in', { keyWidth: KEY }));
|
|
166
|
-
lines.push(kvRow('daemon', 'listen for runs — Ctrl-C stops it', { keyWidth: KEY }));
|
|
179
|
+
lines.push(kvRow('login', status.email ? 'switch account' : 'sign in', { keyWidth: KEY }));
|
|
180
|
+
lines.push(kvRow('daemon', status.daemon ? 'running · Ctrl-C in its window stops it' : 'listen for runs — Ctrl-C stops it', { keyWidth: KEY }));
|
|
167
181
|
lines.push(kvRow('doctor', 'check that everything is set up', { keyWidth: KEY }));
|
|
168
182
|
lines.push(kvRow('logout', 'sign out and stop the daemon', { keyWidth: KEY }));
|
|
169
183
|
lines.push(kvRow('update', 'install the latest version', { keyWidth: KEY }));
|
|
@@ -178,7 +192,7 @@ async function printQuickStart() {
|
|
|
178
192
|
return;
|
|
179
193
|
const choice = await waitForMenuChoice(io, linesBelow(printed, HELP_MARK));
|
|
180
194
|
if (choice === 'help')
|
|
181
|
-
printHelp();
|
|
195
|
+
printHelp({ wordmark: false });
|
|
182
196
|
}
|
|
183
197
|
function extractProfileFlag(args) {
|
|
184
198
|
let profile;
|
|
@@ -222,13 +236,13 @@ async function main(argv) {
|
|
|
222
236
|
return 0;
|
|
223
237
|
}
|
|
224
238
|
if (first === '-h' || first === '--help' || first === 'help') {
|
|
225
|
-
printHelp();
|
|
239
|
+
printHelp({ mcpLabel: await localMcpLabel() });
|
|
226
240
|
return 0;
|
|
227
241
|
}
|
|
228
242
|
const cmd = COMMANDS.find((c) => c.name === first);
|
|
229
243
|
if (!cmd) {
|
|
230
244
|
process.stderr.write(`nonbot: unknown command "${first}"\n\n`);
|
|
231
|
-
printHelp();
|
|
245
|
+
printHelp({ mcpLabel: await localMcpLabel() });
|
|
232
246
|
return 1;
|
|
233
247
|
}
|
|
234
248
|
const result = await cmd.run(args.slice(1));
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { loadAuth } from './auth.js';
|
|
2
|
+
import { readPidFile } from './daemon-lifecycle.js';
|
|
3
|
+
import { ANSI, isTTY } from './output.js';
|
|
4
|
+
import { scanMcpConfigs } from './mcp-config.js';
|
|
5
|
+
import { installedMcpVersion } from './mcp-status.js';
|
|
6
|
+
export async function localMcpLabel(scan = () => scanMcpConfigs().nonbot, versionOf = (e) => installedMcpVersion(e)) {
|
|
7
|
+
let entries = [];
|
|
8
|
+
try {
|
|
9
|
+
entries = scan();
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
entries = [];
|
|
13
|
+
}
|
|
14
|
+
const primary = entries.find((e) => e.scope && e.scope !== 'desktop') ?? entries[0];
|
|
15
|
+
if (!primary)
|
|
16
|
+
return 'not set up';
|
|
17
|
+
if (primary.kind === 'remote')
|
|
18
|
+
return 'remote';
|
|
19
|
+
const v = await versionOf(primary).catch(() => null);
|
|
20
|
+
return v ? `v${v}` : 'set up';
|
|
21
|
+
}
|
|
22
|
+
export function versionsLine(cliVersion, mcpLabel) {
|
|
23
|
+
return `non.bot CLI v${cliVersion} · non.bot MCP ${mcpLabel}`;
|
|
24
|
+
}
|
|
25
|
+
export async function localStatus(deps = {}) {
|
|
26
|
+
let email = null;
|
|
27
|
+
try {
|
|
28
|
+
email = (await (deps.loadAuth ?? loadAuth)())?.email ?? null;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
email = null;
|
|
32
|
+
}
|
|
33
|
+
const pid = (deps.readPid ?? (() => readPidFile()))();
|
|
34
|
+
const alive = deps.isAlive ??
|
|
35
|
+
((p) => {
|
|
36
|
+
try {
|
|
37
|
+
process.kill(p, 0);
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
return { email, daemon: pid !== null && alive(pid) };
|
|
45
|
+
}
|
|
46
|
+
export function statusLine(s, keyWidth, stream = process.stdout) {
|
|
47
|
+
const tty = isTTY(stream);
|
|
48
|
+
const pad = ' '.repeat(3 + keyWidth + 1);
|
|
49
|
+
const mark = (ok) => (tty ? (ok ? `${ANSI.green}✓${ANSI.reset}` : `${ANSI.dim}○${ANSI.reset}`) : ok ? '✓' : '○');
|
|
50
|
+
const dim = (t) => (tty ? `${ANSI.dim}${t}${ANSI.reset}` : t);
|
|
51
|
+
if (!s.email)
|
|
52
|
+
return `${pad}${mark(false)} ${dim('not signed in — start with: nonbot login')}`;
|
|
53
|
+
return `${pad}${mark(true)} ${dim(`signed in as ${s.email} · daemon ${s.daemon ? 'running' : 'not running'}`)}`;
|
|
54
|
+
}
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '0.10.
|
|
1
|
+
export const VERSION = '0.10.17';
|
package/package.json
CHANGED