Skip to content

feat(cli): add --no-log flag and keep stdout clean under --json#1234

Open
John-David Dalton (jdalton) wants to merge 3 commits intomainfrom
fix/no-log-flag-automation
Open

feat(cli): add --no-log flag and keep stdout clean under --json#1234
John-David Dalton (jdalton) wants to merge 3 commits intomainfrom
fix/no-log-flag-automation

Conversation

@jdalton
Copy link
Copy Markdown
Contributor

@jdalton John-David Dalton (jdalton) commented Apr 18, 2026

The ask

ASK-115: `socket fix --json | jq` (and any automation combining `--json` with `--dry-run`) was getting non-JSON text on stdout because the dry-run preview routed through `logger.log` (stdout). Human-readable output leaking into a machine-readable stream broke scripts.

Changes

New flag

`--no-log` (boolean, on `commonFlags`) — suppresses non-essential informational output so stdout is clean for automation. Errors still print to stderr. Visible in `--help`.

New module

`utils/output/no-log.mts` — tiny module exposing `setNoLogMode`, `isNoLogMode`, and `shouldQuietStdout(flags)`.

Wiring

`meowOrExit` now:

  1. Resets no-log mode at the start of every invocation so state doesn't leak across unit tests that run multiple commands in sequence.
  2. Engages no-log mode when any of `--no-log`, `--json`, or `--markdown` is parsed. The last two imply clean stdout because the primary payload belongs on stdout alone.

Dry-run routing

`utils/dry-run/output.mts` now routes through a private `out()` helper that uses `logger.error` (stderr) when no-log mode is engaged, otherwise `logger.log` (stdout). Every `outputDryRun*` formatter flows through this single helper, so all six dry-run shapes (preview, fetch, execute, upload, delete, write) inherit the fix.

Before / after

```sh

Before

$ socket fix --json --dry-run | jq .

→ [DryRun]: Analyze... (human text in stdout breaks the jq pipe)

After

$ socket fix --json --dry-run 2>/tmp/err 1>/tmp/out

stdout: 0 bytes (pipe-safe)

stderr: 658 bytes (preview visible to humans)

Human default unchanged

$ socket fix --dry-run

still prints to stdout

```

Tests

  • New `utils/output/no-log.test.mts` — 7 tests covering toggle, `shouldQuietStdout` under each flag, and unrelated-flag isolation.
  • New `stream routing` describe block in `utils/dry-run/output.test.mts` — asserts stdout routing by default and stderr routing when no-log mode is engaged.
  • Updated two command tests that combine `--json` with dry-run to assert `mockLogger.error` instead of `mockLogger.log`: `cmd-scan-view` `--json --stream` and `cmd-organization-quota` `--dry-run --json`.

All 340 test files / 5113 tests green.

Test plan

  • `pnpm run type` clean
  • `pnpm --filter @socketsecurity/cli run test:unit` — 340 files / 5113 tests
  • `pnpm run build:cli` succeeds
  • Manual end-to-end: verified `--json` stdout is empty, `--dry-run` alone still prints to stdout
  • CI green

Note

Medium Risk
Changes CLI output stream behavior by introducing a module-level no-log toggle and implicitly enabling it for --json/--markdown, which could affect scripts/tests that assumed dry-run text on stdout. Scope is limited to logging/routing and is covered by updated and new unit tests.

Overview
Adds a new --no-log common flag and a shared utils/output/no-log.mts toggle to support automation-friendly runs where stdout must remain payload-only.

Wires the toggle into CLI argument parsing (meowWithSubcommands/meowOrExit), resetting state per invocation to avoid test leakage and enabling no-log mode for --no-log and implicitly for --json/--markdown.

Updates dry-run output helpers to route through stderr when no-log mode is active (leaving default interactive output on stdout), and adjusts/adds unit tests to assert the new stdout/stderr behavior.

Reviewed by Cursor Bugbot for commit ed83f91. Configure here.

Fixes ASK-115. Previously `socket fix --json | jq` (and any
automation combining `--json` with `--dry-run`) got non-JSON text
on stdout because the dry-run preview routed through `logger.log`
(stdout). Human-readable output leaking into a machine-readable
stream broke scripts.

## Changes

* New `--no-log` boolean in `commonFlags`. Suppresses non-essential
  informational output so stdout is clean for automation. Errors
  still print to stderr. Visible in `--help`.

* New `utils/output/no-log.mts` module with `setNoLogMode(on)`,
  `isNoLogMode()`, and a `shouldQuietStdout(flags)` helper that
  derives the right answer from `--no-log` / `--json` / `--markdown`.

* `meowOrExit` now:
  - Resets no-log mode at the start of every invocation so state
    doesn't leak across unit tests that run multiple commands in
    sequence.
  - Engages no-log mode when any of `--no-log`, `--json`, or
    `--markdown` is parsed. `--json` and `--markdown` imply clean
    stdout because the primary payload belongs on stdout alone.

* `utils/dry-run/output.mts` now routes through a private `out()`
  helper that uses `logger.error` (stderr) when no-log mode is
  engaged, otherwise `logger.log` (stdout). Every `outputDryRun*`
  formatter flows through this single helper, so all dry-run shapes
  (preview, fetch, execute, upload, delete, write) get the fix.

## Verification

Against a fresh build:

    $ socket fix --json --dry-run 2>/tmp/err 1>/tmp/out
    # stdout: 0 bytes (pipe-safe)
    # stderr: 658 bytes (preview visible to humans)

    $ socket fix --dry-run 2>/tmp/err 1>/tmp/out
    # stdout: 658 bytes (human default unchanged)

## Tests

* New `utils/output/no-log.test.mts` — 7 tests covering toggle,
  `shouldQuietStdout` under each flag, and unrelated-flag isolation.

* `utils/dry-run/output.test.mts` — new `stream routing` describe
  block asserting stdout routing by default and stderr routing
  when no-log mode is engaged.

* Two command tests that combine `--json` with dry-run updated to
  assert `mockLogger.error` instead of `mockLogger.log`:
  `cmd-scan-view` `--json --stream` and `cmd-organization-quota`
  `--dry-run --json`.

All other 5100+ tests unchanged. Full suite green.
Comment thread packages/cli/src/utils/output/no-log.mts Outdated
Addresses Cursor bugbot feedback on PR #1234. The helper was exported
but never imported in any production source — only in its own test
file. Production uses isNoLogMode() directly, and the flag-checking
logic already lives inline in meowOrExit.

Delete the helper and its dedicated tests.
@jdalton
Copy link
Copy Markdown
Contributor Author

Cursor (@cursor) review

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit e04fa30. Configure here.

@jdalton
Copy link
Copy Markdown
Contributor Author

Cursor (@cursor) review

Comment thread packages/cli/src/utils/cli/with-subcommands.mts
@jdalton
Copy link
Copy Markdown
Contributor Author

Cursor (@cursor) review

@jdalton
Copy link
Copy Markdown
Contributor Author

Cursor (@cursor) review

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit ed83f91. Configure here.

@jdalton
Copy link
Copy Markdown
Contributor Author

Cursor (@cursor) review

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit ed83f91. Configure here.

@jdalton
Copy link
Copy Markdown
Contributor Author

Cursor (@cursor) review

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit ed83f91. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant