feat: add standalone zcode-quota CLI with watch mode#13
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a standalone CLI tool, zcode-quota, allowing users to query their GLM Coding Plan usage directly from the terminal. It supports both one-shot and live watch modes, strips markdown fences for clean terminal rendering, and includes comprehensive unit tests. The feedback highlights two issues in the CLI implementation: an off-by-one error in the watch mode countdown loop that results in a shorter sleep duration than requested, and a SIGINT handler that prematurely exits the process, bypassing the finally block cleanup in runWatch.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| for (let remaining = intervalSec - 1; remaining > 0; remaining--) { | ||
| await sleep(1000, controller.signal).catch(() => undefined); | ||
| if (controller.signal.aborted) break; | ||
| process.stdout.write(`\r${ANSI.clearLine}${renderFooter(updatedAt, remaining)}`); | ||
| } |
There was a problem hiding this comment.
There is an off-by-one error in the countdown loop. If intervalSec is 10, the loop runs for remaining values from 9 down to 1 (9 iterations), sleeping for 1 second each. This results in a total sleep of 9 seconds instead of the requested 10 seconds. To fix this, the loop should run for intervalSec iterations (from intervalSec - 1 down to 0 inclusive), while conditionally skipping the footer write when remaining is 0 to avoid showing a '0s' countdown right before the redraw.
for (let remaining = intervalSec - 1; remaining >= 0; remaining--) {
await sleep(1000, controller.signal).catch(() => undefined);
if (controller.signal.aborted) break;
if (remaining > 0) {
process.stdout.write(`\r${ANSI.clearLine}${renderFooter(updatedAt, remaining)}`);
}
}| const onInt = (): void => { | ||
| controller.abort(); | ||
| restore(); | ||
| process.exit(0); | ||
| }; |
There was a problem hiding this comment.
Calling process.exit(0) inside the SIGINT handler terminates the process synchronously, which completely bypasses the finally block at the end of runWatch. This makes the finally block (and the process.off cleanup) dead code. By simply calling controller.abort(), the active sleep promise will reject, the loops will terminate naturally, and the finally block will execute to restore the cursor and clean up the event listener.
const onInt = (): void => {
controller.abort();
};
Summary
zcode-quotaCLI (new bin) that queries GLM Coding Plan usage from the terminal — no ACP server or editor needed. Reuses the existingqueryQuota()/formatQuotaPlain()(only reads~/.zcode/v2/config.json).zcode-quotazcode-quota -w(clear-and-redraw liketop, with a per-second refresh countdown in the footer; default 30s, min 10s to match the cache TTL)zcode-quota -hfor help; zero new dependencies (hand-rolled argv parser + ANSI escapes)formatQuotaPlain()to strip the```textfence for raw terminal output (the fenced card stays for the in-editor/quotaslash command).docs/ARCHITECTURE.md, explaining what data the bridge touches, where it goes, and why each access is needed (notably: thetasks-index.sqlitewrite syncs sessions into the ZCode app history/search).zcode-org/zcode-acp-server→william0wang/zcode-acp) across README badges, package.json, and CONTRIBUTING.md — the old address pointed to a non-existent repo.Test plan
pnpm typecheckcleanpnpm test— 152 tests pass (incl. 14 new CLI tests forparseArgs/resolveIntervalMs, 2 newformatQuotaPlaintests)pnpm buildsucceeds;dist/bin/quota.jsgeneratednode dist/bin/quota.js— one-shot prints the card against the live APInode dist/bin/quota.js -w -i 10— watch mode stays alive (fixed: the sleep timer wasunref()-ed, which let Node exit after the first frame), countdown ticks per second, Ctrl-C exits cleanlynode dist/bin/quota.js -w -i 3— clamps below-floor interval to 10s with a stderr warningNotes
formatQuotaPlain); the in-editor/quotacard keeps its```textfence unchanged.