Compare commits

...

2 Commits

Author SHA1 Message Date
Peter Steinberger
b72a3674a7 fix: quiet logs progress output (#1472) (thanks @czekaj) 2026-01-23 01:29:09 +00:00
Lucas Czekaj
8bf1af35de fix: suppress spinner in logs --follow mode
The progress spinner was being shown for each gateway RPC call during
log tailing, causing repeated spinner frames (◇ │) to appear every
polling interval.

Add a `progress` option to `callGatewayFromCli` and disable the spinner
during follow mode polling to keep output clean.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 01:22:19 +00:00
4 changed files with 31 additions and 8 deletions

View File

@ -25,6 +25,7 @@ Docs: https://docs.clawd.bot
### Fixes
- BlueBubbles: stop typing indicator on idle/no-reply. (#1439) Thanks @Nicell.
- CLI: suppress progress spinner noise for `logs --follow` and JSON output. (#1472) Thanks @czekaj.
- Auto-reply: only report a model switch when session state is available. (#1465) Thanks @robbyczgw-cla.
- Control UI: resolve local avatar URLs with basePath across injection + identity RPC. (#1457) Thanks @dlauer.
- Agents: surface concrete API error details instead of generic AI service errors.

View File

@ -23,13 +23,14 @@ export async function callGatewayFromCli(
method: string,
opts: GatewayRpcOpts,
params?: unknown,
extra?: { expectFinal?: boolean },
extra?: { expectFinal?: boolean; progress?: boolean },
) {
const showProgress = (extra?.progress ?? true) && opts.json !== true;
return await withProgress(
{
label: `Gateway ${method}`,
indeterminate: true,
enabled: opts.json !== true,
enabled: showProgress,
},
async () =>
await callGateway({

View File

@ -82,4 +82,21 @@ describe("logs cli", () => {
expect(stderrWrites.join("")).toContain("output stdout closed");
});
it("disables progress spinner in json mode", async () => {
callGatewayFromCli.mockResolvedValueOnce({
file: "/tmp/clawdbot.log",
lines: [],
});
const { registerLogsCli } = await import("./logs-cli.js");
const program = new Command();
program.exitOverride();
registerLogsCli(program);
await program.parseAsync(["logs", "--json"], { from: "user" });
const extra = callGatewayFromCli.mock.calls[0]?.[3];
expect(extra).toEqual({ progress: false });
});
});

View File

@ -41,14 +41,16 @@ function parsePositiveInt(value: string | undefined, fallback: number): number {
async function fetchLogs(
opts: LogsCliOptions,
cursor: number | undefined,
showProgress: boolean,
): Promise<LogsTailPayload> {
const limit = parsePositiveInt(opts.limit, 200);
const maxBytes = parsePositiveInt(opts.maxBytes, 250_000);
const payload = await callGatewayFromCli("logs.tail", opts, {
cursor,
limit,
maxBytes,
});
const payload = await callGatewayFromCli(
"logs.tail",
opts,
{ cursor, limit, maxBytes },
{ progress: showProgress },
);
if (!payload || typeof payload !== "object") {
throw new Error("Unexpected logs.tail response");
}
@ -194,8 +196,10 @@ export function registerLogsCli(program: Command) {
while (true) {
let payload: LogsTailPayload;
// Show progress spinner only on first fetch for non-follow, non-JSON output.
const showProgress = first && !opts.follow && !jsonMode;
try {
payload = await fetchLogs(opts, cursor);
payload = await fetchLogs(opts, cursor, showProgress);
} catch (err) {
emitGatewayError(err, opts, jsonMode ? "json" : "text", rich, emitJsonLine, errorLine);
process.exit(1);