-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat: beautiful CLI with box-drawing, progress bar, and readable output #134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Replace the per-character color cycling shimmer effect with a subtle slow pulse between white and cyan. Much more readable and accessible while still providing visual feedback. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add box.ts with drawBox(), drawSeparator(), and renderProgressBar() helpers. Update ProgressRenderer with iteration tracking, progress bar display, and live cost indicator. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace plain separator lines with box-drawing UI throughout the executor. Adds a startup config summary box, per-iteration header boxes with agent/iteration info, and a clean completion banner with stats. Wire progress bar with iteration and cost tracking. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show a status separator between iterations with iteration count, task progress, cost, and elapsed time. Replace verbose validation error output with a compact one-line summary. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
💡 Issue Linking ReminderThis PR doesn't appear to have a linked issue. Consider linking to:
Using If this PR doesn't need an issue, you can ignore this message. |
📝 WalkthroughWalkthroughThe pull request enhances the executor's user interface by introducing styled terminal boxes, separators, and progress bars for improved visual feedback. New utilities in a dedicated Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
✔️ Bundle Size Analysis
Bundle breakdown |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@src/ui/box.ts`:
- Around line 56-68: In renderProgressBar, guard against total === 0 before
computing ratio so current/total doesn't produce NaN; for example, if total ===
0 set ratio = current > 0 ? 1 : 0 (then clamp with Math.min/Math.max as before)
so filled/empty are valid integers and the bar shows full when progress exists
or empty when none; update the ratio computation near the top of
renderProgressBar to handle this case.
🧹 Nitpick comments (1)
src/ui/box.ts (1)
24-30: Long lines may overflow the box boundaries.If a line's content exceeds
innerWidth, the padding becomes 0 but the line itself isn't truncated, causing visual misalignment with the box borders. Consider truncating long lines or wrapping them.💡 Optional fix to truncate long lines
for (const line of lines) { // Strip ANSI codes to measure real length // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape sequence detection requires control characters const stripped = line.replace(/\u001b\[[0-9;]*m/g, ''); - const padding = Math.max(0, innerWidth - stripped.length); - output.push(color('│') + line + ' '.repeat(padding) + color('│')); + const padding = innerWidth - stripped.length; + if (padding >= 0) { + output.push(color('│') + line + ' '.repeat(padding) + color('│')); + } else { + // Truncate line to fit (preserving ANSI codes is complex, so truncate stripped) + const truncated = stripped.slice(0, innerWidth - 1) + '…'; + output.push(color('│') + truncated + color('│')); + } }
| export function renderProgressBar( | ||
| current: number, | ||
| total: number, | ||
| options: { width?: number; label?: string } = {} | ||
| ): string { | ||
| const barWidth = options.width || 20; | ||
| const ratio = Math.min(1, Math.max(0, current / total)); | ||
| const filled = Math.round(ratio * barWidth); | ||
| const empty = barWidth - filled; | ||
| const bar = `${'█'.repeat(filled)}${'░'.repeat(empty)}`; | ||
| const info = options.label ? ` │ ${options.label}` : ''; | ||
| return `${chalk.cyan(bar)} ${current}/${total}${chalk.dim(info)}`; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Division by zero produces an empty progress bar.
When total is 0, the ratio calculation results in NaN, causing both filled and empty to be NaN. While String.prototype.repeat handles this gracefully (returning empty strings), the progress bar will appear empty rather than showing a meaningful state.
🛡️ Proposed fix to handle zero total
export function renderProgressBar(
current: number,
total: number,
options: { width?: number; label?: string } = {}
): string {
const barWidth = options.width || 20;
- const ratio = Math.min(1, Math.max(0, current / total));
+ const ratio = total > 0 ? Math.min(1, Math.max(0, current / total)) : 0;
const filled = Math.round(ratio * barWidth);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export function renderProgressBar( | |
| current: number, | |
| total: number, | |
| options: { width?: number; label?: string } = {} | |
| ): string { | |
| const barWidth = options.width || 20; | |
| const ratio = Math.min(1, Math.max(0, current / total)); | |
| const filled = Math.round(ratio * barWidth); | |
| const empty = barWidth - filled; | |
| const bar = `${'█'.repeat(filled)}${'░'.repeat(empty)}`; | |
| const info = options.label ? ` │ ${options.label}` : ''; | |
| return `${chalk.cyan(bar)} ${current}/${total}${chalk.dim(info)}`; | |
| } | |
| export function renderProgressBar( | |
| current: number, | |
| total: number, | |
| options: { width?: number; label?: string } = {} | |
| ): string { | |
| const barWidth = options.width || 20; | |
| const ratio = total > 0 ? Math.min(1, Math.max(0, current / total)) : 0; | |
| const filled = Math.round(ratio * barWidth); | |
| const empty = barWidth - filled; | |
| const bar = `${'█'.repeat(filled)}${'░'.repeat(empty)}`; | |
| const info = options.label ? ` │ ${options.label}` : ''; | |
| return `${chalk.cyan(bar)} ${current}/${total}${chalk.dim(info)}`; | |
| } |
🤖 Prompt for AI Agents
In `@src/ui/box.ts` around lines 56 - 68, In renderProgressBar, guard against
total === 0 before computing ratio so current/total doesn't produce NaN; for
example, if total === 0 set ratio = current > 0 ? 1 : 0 (then clamp with
Math.min/Math.max as before) so filled/empty are valid integers and the bar
shows full when progress exists or empty when none; update the ratio computation
near the top of renderProgressBar to handle this case.
|
Merged into staging/pre-conference branch for pre-conference release testing. Will be included in the stable release. |
Summary
Complete CLI visual overhaul for conference-ready demos:
┌─┐│└─┘) for startup summary, iteration headers, and completion banner████░░░░displaying iteration count and live costNew file
src/ui/box.ts—drawBox(),drawSeparator(),renderProgressBar()utilitiesChanges
src/ui/shimmer.ts— Replace per-character shimmer with slow pulsesrc/ui/progress-renderer.ts— Add progress bar, iteration tracking, live costsrc/loop/executor.ts— Box headers, startup summary, completion banner, status linesTest plan
pnpm buildpassespnpm test— 143 tests passGenerated by ralph-starter
🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
Improvements