Skip to content

feat(cli): add post-exec status, fix interactive flag, show stderr#35

Open
pablopunk wants to merge 2 commits into
mainfrom
task-34-dot
Open

feat(cli): add post-exec status, fix interactive flag, show stderr#35
pablopunk wants to merge 2 commits into
mainfrom
task-34-dot

Conversation

@pablopunk

@pablopunk pablopunk commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Summary

Issue #34 reported that dot commands produce no output on success in non-verbose mode, leaving users unsure whether operations completed.

Changes

  • Interactive mode (default TUI): Previously silent after the TUI closed. Now prints per-component status lines (✓ name, ✗ name, ~ name, - name) for every operation, plus a ✓ Done. summary line. Failures are counted and reported to stderr.
  • Always show stderr on failure: Removed the --verbose guard on error output in installComponent() and uninstallComponent(). If a subprocess fails, its stderr is now always printed, matching the behavior already present in hooks.
  • Fix options.interactive flag: The TUI mode was incorrectly setting interactive: false for subprocesses (the flag was isTty && args.mode === "direct"). Changed to isTty so that interactive installers (brew, password prompts, etc.) receive terminal input when launched from the TUI.
  • New tests: Added tests/feedback.test.ts with 10 unit tests covering all visual states of the new printResultStatus and printLinkStatus functions.

These changes make dot's output behavior consistent between interactive and direct modes, and ensure users always see what happened after running a command.

Summary by CodeRabbit

  • New Features

    • Added clear success, failure, skipped, and dry-run status indicators throughout CLI operations.
    • Interactive sessions now display per-step progress and a final “Done.” message.
    • Interactive terminal sessions can provide input to running commands.
  • Bug Fixes

    • Failed commands now display error details even when verbose output is disabled.
    • Improved feedback for missing or skipped operations.
  • Tests

    • Added coverage for status formatting, error output, and interactive input behavior.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The CLI adds shared status helpers for install, uninstall, link, import/export, and hook operations. Interactive mode now reports success, failure, dry-run, and skipped states, tracks non-dry-run failures, and always prints completion output. Direct mode receives consistent status output and unconditional completion output. Installer failures now print trimmed subprocess stderr regardless of verbose mode, and interactive TTY detection preserves terminal input. Tests cover status formatting, failure output, and interactive behavior.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as main()
  participant Installer as installComponent/uninstallComponent
  participant Subprocess
  participant Output as stdout/stderr
  CLI->>Installer: execute component operation
  Installer->>Subprocess: run command
  Subprocess-->>Installer: return result and stderr
  Installer->>Output: print stderr when the command fails
  Installer-->>CLI: return operation result
  CLI->>Output: print operation status
  CLI->>Output: print failure count when needed
  CLI->>Output: print Done.
Loading
🚥 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 clearly summarizes the main CLI feedback, interactive flag, and stderr 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.

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/feedback.test.ts (1)

176-233: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Interactive feedback tests simulate output rather than exercising the actual code path.

These tests call process.stdout.write/process.stderr.write directly to verify the format, but don't invoke main() with mocked dependencies. They pass even if the interactive mode implementation diverges from the simulated strings. Consider mocking runInteractive, installComponent, etc. and calling main() to verify end-to-end behavior.

🤖 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 `@tests/feedback.test.ts` around lines 176 - 233, Replace the simulated
stdout/stderr writes in the “interactive mode feedback patterns (Change 1)”
tests with end-to-end tests that invoke main() using mocked runInteractive,
installComponent, and other required dependencies. Assert the actual output
produced by main(), including Done. formatting, failure count behavior, colors,
and output streams, so the tests detect divergences in the implementation.
🤖 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.

Inline comments:
In `@src/index.ts`:
- Around line 324-326: In the direct-mode results handling loop, avoid adding
the same component multiple times when several links fail. Replace the
per-result push logic in the `for (const r of results)` block with a single
`results.some(r => r.failed && !r.dryRun)` check, pushing `name` only when at
least one qualifying failure exists, matching the interactive-mode behavior.

---

Nitpick comments:
In `@tests/feedback.test.ts`:
- Around line 176-233: Replace the simulated stdout/stderr writes in the
“interactive mode feedback patterns (Change 1)” tests with end-to-end tests that
invoke main() using mocked runInteractive, installComponent, and other required
dependencies. Assert the actual output produced by main(), including Done.
formatting, failure count behavior, colors, and output streams, so the tests
detect divergences in the implementation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 23ed5d20-dcef-4b62-8b7a-f498aae8b19e

📥 Commits

Reviewing files that changed from the base of the PR and between 2095d78 and e07c64d.

📒 Files selected for processing (7)
  • .task-artifacts/002-plan.md
  • .task-artifacts/004-implement.md
  • .task-artifacts/005-implement.md
  • src/index.ts
  • src/installer.ts
  • tests/feedback.test.ts
  • tests/installer.test.ts

Comment thread src/index.ts
Comment on lines 324 to 326
for (const r of results) {
if (r.failed && !r.dryRun) failures.push(name);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Direct mode link handling inflates failure count.

failures.push(name) is called once per failed LinkResult, so a component with multiple failed links gets counted multiple times. Interactive mode (lines 173–174) correctly uses results.some() to push only once.

🐛 Proposed fix: use `some()` like interactive mode
        if (comp.hasLinks) {
          const results = createLinks(name, comp.link, process.cwd(), options);
-         for (const r of results) {
-           if (r.failed && !r.dryRun) failures.push(name);
-         }
+         const anyFailed = results.some((r) => r.failed && !r.dryRun);
+         if (anyFailed) failures.push(name);
          printLinkStatus(name, results);
📝 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.

Suggested change
for (const r of results) {
if (r.failed && !r.dryRun) failures.push(name);
}
const anyFailed = results.some((r) => r.failed && !r.dryRun);
if (anyFailed) failures.push(name);
🤖 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 `@src/index.ts` around lines 324 - 326, In the direct-mode results handling
loop, avoid adding the same component multiple times when several links fail.
Replace the per-result push logic in the `for (const r of results)` block with a
single `results.some(r => r.failed && !r.dryRun)` check, pushing `name` only
when at least one qualifying failure exists, matching the interactive-mode
behavior.

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