Skip to content

[codex] Fix banner contrast across terminals#60

Open
tomcasaburi wants to merge 2 commits into
masterfrom
codex/fix-banner-contrast
Open

[codex] Fix banner contrast across terminals#60
tomcasaburi wants to merge 2 commits into
masterfrom
codex/fix-banner-contrast

Conversation

@tomcasaburi
Copy link
Copy Markdown
Member

@tomcasaburi tomcasaburi commented May 26, 2026

Summary

  • Render the Bitsocial banner with only a broadly supported ANSI blue accent and leave the wordmark/ring on the terminal default foreground.
  • Force the daemon startup banner color for Docker/systemd-style non-TTY logs while still respecting NO_COLOR.
  • Register daemon shutdown cleanup before Kubo/RPC startup so SIGTERM cannot hit the readiness-before-cleanup window found during verification.

Refs #58.
Refs #59.

Validation

  • npm run build && npm run build:test
  • npm run test:cli -- test/cli/daemon.test.ts -t "daemon's own cleanup kills kubo after SIGTERM"
  • npm run test:cli (29 files, 215 passed, 1 skipped)

Note

Low Risk
Changes are limited to terminal styling, banner API surface, and daemon startup ordering for safer SIGTERM cleanup; no auth or data-path logic changes.

Overview
Improves CLI banner readability by dropping fixed RGB silver/blue in favor of a standard bright blue accent (\x1b[94m) and the terminal’s default foreground for the wordmark and rings, so the art works on light and dark themes. Banner rendering is refactored into renderBanner with injectable env/TTY/forceColor options and stricter FORCE_COLOR handling; the daemon calls printBanner({ forceColor: true }) so Docker/systemd logs still get color while NO_COLOR stays honored.

Daemon startup order moves Kubo bring-up and RPC connection to after asyncExitHook and the emergency exit handler are registered, closing a window where SIGTERM during early readiness could run before cleanup was wired.

Adds test/cli/ascii-banner.test.ts covering plain output, color codes, non-TTY behavior, forced color, and FORCE_COLOR edge cases.

Reviewed by Cursor Bugbot for commit 0c1f6b3. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features

    • ASCII banner rendering is now configurable with color control options
    • Supports NO_COLOR and FORCE_COLOR environment variables to manage banner colors
    • Daemon startup now displays ASCII banner with optimized color support
  • Tests

    • Added test suite for ASCII banner rendering with color mode variants

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 26, 2026

📝 Walkthrough

Walkthrough

The PR refactors ASCII banner rendering to use configurable ANSI escape codes (blue and terminal-default foreground), exports a new renderBanner(options) API with environment-aware color support (NO_COLOR, FORCE_COLOR), updates daemon startup to force colored output, relocates daemon initialization calls, and adds comprehensive test coverage.

Changes

Banner Rendering and Daemon Integration

Layer / File(s) Summary
Banner rendering API and color support
src/cli/ascii-banner.ts
Color mapping documentation and ANSI constants updated from hex references to blue (\x1b[94m) and terminal-default foreground (\x1b[39m). Paint logic simplified to toggle only between blue-active and default. Introduced RenderBannerOptions interface with environment detection supporting NO_COLOR, FORCE_COLOR, forceColor, and stdoutIsTTY overrides. Exported renderBanner(options) function and updated printBanner(options) signature.
Daemon startup with banner and initialization reordering
src/cli/commands/daemon.ts
Daemon now forces colored banner output via printBanner({ forceColor: true }). Removed early conditional invocation of keepKuboUp() and createOrConnectRpc() from initial startup path and re-added them later immediately before the keepKuboUpInterval begins.
Banner rendering test suite
test/cli/ascii-banner.test.ts
Added Vitest tests validating renderBanner behavior: NO_COLOR environment variable removes all ANSI codes, TTY output includes blue foreground code and default foreground code without 24-bit RGB sequences, non-TTY output stays plain unless forceColor or FORCE_COLOR=1 is set, and FORCE_COLOR=0 disables color even on TTY.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related issues

  • Fix banner contrast across terminals #58: The changes directly address banner rendering, color/default-foreground behavior, and testability via the new renderBanner() API with environment-aware color handling.

Possibly related PRs

  • bitsocialnet/bitsocial-cli#20: Both PRs modify the same src/cli/ascii-banner.ts banner renderer and daemon startup path in src/cli/commands/daemon.ts (banner invocation and color behavior).

Poem

🐰 A banner painted blue so bright,
With terminal defaults, colors right!
Now NO_COLOR hops in view,
While daemon starts its interval brew—
A simpler paint, a cleaner way! 🎨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly describes the main objective: improving banner contrast across terminals, which is the primary focus of all changes in the pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-banner-contrast

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/cli/ascii-banner.ts

Oops! Something went wrong! :(

ESLint: 8.27.0

Error: ESLint configuration in --config » eslint-config-oclif is invalid:

  • Unexpected top-level property "__esModule".

Referenced from: /.eslintrc
at ConfigValidator.validateConfigSchema (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2156:19)
at ConfigArrayFactory._normalizeConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2998:19)
at ConfigArrayFactory._loadConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2963:21)
at ConfigArrayFactory._loadExtendedShareableConfig (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3264:21)
at ConfigArrayFactory._loadExtends (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3135:25)
at ConfigArrayFactory._normalizeObjectConfigDataBody (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3074:25)
at _normalizeObjectConfigDataBody.next ()
at ConfigArrayFactory._normalizeObjectConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3019:20)
at _normalizeObjectConfigData.next ()
at ConfigArrayFactory.loadFile (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2829:16)

src/cli/commands/daemon.ts

Oops! Something went wrong! :(

ESLint: 8.27.0

Error: ESLint configuration in --config » eslint-config-oclif is invalid:

  • Unexpected top-level property "__esModule".

Referenced from: /.eslintrc
at ConfigValidator.validateConfigSchema (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2156:19)
at ConfigArrayFactory._normalizeConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2998:19)
at ConfigArrayFactory._loadConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2963:21)
at ConfigArrayFactory._loadExtendedShareableConfig (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3264:21)
at ConfigArrayFactory._loadExtends (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3135:25)
at ConfigArrayFactory._normalizeObjectConfigDataBody (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3074:25)
at _normalizeObjectConfigDataBody.next ()
at ConfigArrayFactory._normalizeObjectConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3019:20)
at _normalizeObjectConfigData.next ()
at ConfigArrayFactory.loadFile (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2829:16)

test/cli/ascii-banner.test.ts

Oops! Something went wrong! :(

ESLint: 8.27.0

Error: ESLint configuration in --config » eslint-config-oclif is invalid:

  • Unexpected top-level property "__esModule".

Referenced from: /.eslintrc
at ConfigValidator.validateConfigSchema (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2156:19)
at ConfigArrayFactory._normalizeConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2998:19)
at ConfigArrayFactory._loadConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2963:21)
at ConfigArrayFactory._loadExtendedShareableConfig (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3264:21)
at ConfigArrayFactory._loadExtends (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3135:25)
at ConfigArrayFactory._normalizeObjectConfigDataBody (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3074:25)
at _normalizeObjectConfigDataBody.next ()
at ConfigArrayFactory._normalizeObjectConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3019:20)
at _normalizeObjectConfigData.next ()
at ConfigArrayFactory.loadFile (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2829:16)


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@tomcasaburi tomcasaburi marked this pull request as ready for review May 26, 2026 08:06
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
test/cli/ascii-banner.test.ts (1)

29-33: ⚡ Quick win

Add an explicit NO_COLOR + forceColor precedence test.

Please add a case asserting renderBanner({ env: { NO_COLOR: "1" }, forceColor: true, stdoutIsTTY: false }) stays uncolored, so the intended precedence is locked in by tests.

As per coding guidelines, "Add a test when you add a feature or fix a bug".

Also applies to: 41-45

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/cli/ascii-banner.test.ts` around lines 29 - 33, Add a test that asserts
renderBanner({ env: { NO_COLOR: "1" }, forceColor: true, stdoutIsTTY: false })
produces an uncolored banner (i.e., does NOT contain color escape sequences like
"\x1b[94m"), ensuring NO_COLOR takes precedence over forceColor; add the same
precedence assertion for the parallel case around the other test (the one
similar to the block at lines 41-45) so both capture-paths verify NO_COLOR wins
over forceColor.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@test/cli/ascii-banner.test.ts`:
- Around line 29-33: Add a test that asserts renderBanner({ env: { NO_COLOR: "1"
}, forceColor: true, stdoutIsTTY: false }) produces an uncolored banner (i.e.,
does NOT contain color escape sequences like "\x1b[94m"), ensuring NO_COLOR
takes precedence over forceColor; add the same precedence assertion for the
parallel case around the other test (the one similar to the block at lines
41-45) so both capture-paths verify NO_COLOR wins over forceColor.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d7bdbf71-32ad-4a94-8fba-732e240d7c1c

📥 Commits

Reviewing files that changed from the base of the PR and between 95aec49 and 0c1f6b3.

📒 Files selected for processing (3)
  • src/cli/ascii-banner.ts
  • src/cli/commands/daemon.ts
  • test/cli/ascii-banner.test.ts

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