Skip to content

Control CLI output and improve command discovery#43

Merged
yarlson merged 13 commits into
mainfrom
fix/cli-output-behavior
Apr 25, 2026
Merged

Control CLI output and improve command discovery#43
yarlson merged 13 commits into
mainfrom
fix/cli-output-behavior

Conversation

@yarlson

@yarlson yarlson commented Apr 25, 2026

Copy link
Copy Markdown
Owner

Why

CLI output was inconsistent across flags and error paths, and host-specific
workflows lacked clear guidance. This adds output control, sharpens the
--quiet contract for automation, and makes host guidance more discoverable.

What

  • Add global --colors and --quiet options to control output formatting
  • Make --quiet suppress bootstrap script output (both lnk bootstrap and
    the auto-bootstrap path in lnk init -r), not just framing messages
  • Make lnk diff --quiet exit 0 when clean and 1 when dirty, without
    materializing the patch — usable as a CI/script "is the repo dirty?" check
  • Add per-host pull hints to init and list commands for workflow discovery
  • Fix edge cases in status, pull, and rm commands including no-remote handling
  • Improve output for file backups and restoration workflows

How to verify

  • Run commands with --colors and --quiet; verify output respects flags
  • In a repo with a bootstrap.sh that prints, run lnk --quiet bootstrap
    and lnk --quiet init -r <repo>; confirm no script output leaks
  • Run lnk diff --quiet on a clean repo (echo $? → 0) and on a dirty
    repo (echo $? → 1); confirm no stdout/stderr in either case
  • Run init -r clone and list --all; confirm host-specific pull hints appear
  • Run status on a repository without a remote; verify informative output
  • Run pull with file conflicts; verify backup notices are displayed
  • Run test suite and verify all output scenarios are covered

yarlson added 13 commits April 25, 2026 08:29
- Extract path formatting logic into FormatManagedPath() and storageRootForHost()
  helpers to eliminate duplication across cmd/add.go, cmd/rm.go, and cmd/status.go
- Rename package-shadowing 'lnk' variables to 'l' in commands
- Update README and help text to clarify LNK_HOME and XDG_CONFIG_HOME overrides
- Add 8 new tests covering absolute paths, nested files, custom LNK_HOME env var,
  and host-scoped storage paths to prevent regression of path display bugs
- Document FormatManagedPath helper in facade layer (architecture.md)
- Add path display invariant to practices (all CLI output uses FormatManagedPath)
- Update status flow to reflect dynamic repo path in messages (sync.md)
…atch display

- Display home-relative paths (~/dir/file) instead of basenames for clarity when multiple files share the same filename in different directories
- Add displaySourcePath helper to normalize path display across dry-run and success output
- Limit batch file listing to 5 entries with "...and N more files" hint for large operations
- Only emit carriage-return progress updates in TTY contexts to avoid mangling piped output
- Add IsTerminal method to Writer for detecting terminal output
- Show relative paths in progress callbacks for better context
- Add comprehensive test coverage for path disambiguation, batch truncation, and non-TTY behavior
- Document displaySourcePath pattern for home-relative source path rendering to disambiguate same-basename files
- Document TTY-aware progress updates that only emit carriage returns in terminal contexts
- Document batch output truncation (first 5 entries shown, remainder as "...and N more files")
- Clarify distinction between storage paths (FormatManagedPath) and source paths (displaySourcePath)
- Update dry-run, multi-file add, and recursive add sections to reflect current behavior
- Add Colors() and Quiet() accessor methods to Writer
- Refactor diff command to respect --quiet and --colors flags
- Add documentation for global options in README
- Add comprehensive tests for color output modes and quiet suppression
- Enumerate host configs during init and display pull hints for each
- Add per-host pull guidance to list --all output
- Update list --all prompts to be more explicit
- Add comprehensive tests for host hint scenarios
- Update documentation to reflect new host guidance feature
- Document per-host hints emitted during init -r clone
- Clarify list --all output includes per-host pull guidance
- Reference findHostConfigs enumeration in init flow
- Add displayNoRemoteStatus to handle repositories without a remote configured
- Update Pull() and RestoreSymlinks() to return RestoreInfo with backup info
- Add writeBackupNotice to report files renamed to .lnk-backup during restore
- Improve rm command output when removing symlinks
- Update all related tests and type exports
- Document RestoreInfo return type for Pull and RestoreSymlinks
- Update sync flow documentation for no-remote handling in status command
- Add terminology for .lnk-backup files and RestoreInfo struct
- Document improved remove/force-remove command output with host support
- Update doctor flow to reflect BackedUp field reporting
- Clarify backup file handling and restoration behavior
Two gaps in the --quiet contract on this branch:

- `lnk bootstrap` and the auto-bootstrap path in `lnk init -r` invoked
  RunBootstrapScript with raw os.Stdout/os.Stderr, so any script that
  printed leaked through despite --quiet. Route script I/O through the
  cobra command's writers, and substitute io.Discard in both slots when
  the writer reports Quiet().

- `lnk -q diff` still called Diff(false), which buffered the entire
  patch only to discard it. Add Git.HasDiff (running `git diff --quiet`
  and decoding the exit code) plus matching Syncer/Lnk delegates, and
  use it from the diff command's quiet branch so the patch is never
  produced.
The previous round preserved exit code 0 in `lnk diff --quiet` (matching
the prior test) but that defeats the documented "exit code only" contract
— CI/scripts cannot detect uncommitted changes from quiet mode.

Quiet mode now returns a sentinel error when `HasDiff` reports changes,
which yields exit 1 while the writer continues to suppress all stdout
and the global quiet config keeps DisplayError silent. Test updated to
assert: clean → no error, dirty → error, both with empty stdout/stderr.

Also picks up a gofmt-only whitespace fix in cmd/init.go.
@yarlson yarlson merged commit 30123d5 into main Apr 25, 2026
7 checks passed
polymorcodeus pushed a commit to polymorcodeus/lnk that referenced this pull request May 29, 2026
* chore: ignore .snap directory for snapcraft builds

* refactor: consolidate path formatting and add comprehensive path tests

- Extract path formatting logic into FormatManagedPath() and storageRootForHost()
  helpers to eliminate duplication across cmd/add.go, cmd/rm.go, and cmd/status.go
- Rename package-shadowing 'lnk' variables to 'l' in commands
- Update README and help text to clarify LNK_HOME and XDG_CONFIG_HOME overrides
- Add 8 new tests covering absolute paths, nested files, custom LNK_HOME env var,
  and host-scoped storage paths to prevent regression of path display bugs

* docs: update context documentation for path formatting refactor

- Document FormatManagedPath helper in facade layer (architecture.md)
- Add path display invariant to practices (all CLI output uses FormatManagedPath)
- Update status flow to reflect dynamic repo path in messages (sync.md)

* refactor: disambiguate files using home-relative paths and optimize batch display

- Display home-relative paths (~/dir/file) instead of basenames for clarity when multiple files share the same filename in different directories
- Add displaySourcePath helper to normalize path display across dry-run and success output
- Limit batch file listing to 5 entries with "...and N more files" hint for large operations
- Only emit carriage-return progress updates in TTY contexts to avoid mangling piped output
- Add IsTerminal method to Writer for detecting terminal output
- Show relative paths in progress callbacks for better context
- Add comprehensive test coverage for path disambiguation, batch truncation, and non-TTY behavior

* docs: update context documentation for path display and output behavior

- Document displaySourcePath pattern for home-relative source path rendering to disambiguate same-basename files
- Document TTY-aware progress updates that only emit carriage returns in terminal contexts
- Document batch output truncation (first 5 entries shown, remainder as "...and N more files")
- Clarify distinction between storage paths (FormatManagedPath) and source paths (displaySourcePath)
- Update dry-run, multi-file add, and recursive add sections to reflect current behavior

* feat: add --colors and --quiet global options for CLI output control

- Add Colors() and Quiet() accessor methods to Writer
- Refactor diff command to respect --quiet and --colors flags
- Add documentation for global options in README
- Add comprehensive tests for color output modes and quiet suppression

* docs: update context to reflect Colors() and Quiet() accessor methods and --colors/--quiet behavior in diff

* feat: add per-host pull hints to init and list commands

- Enumerate host configs during init and display pull hints for each
- Add per-host pull guidance to list --all output
- Update list --all prompts to be more explicit
- Add comprehensive tests for host hint scenarios
- Update documentation to reflect new host guidance feature

* docs: update context for per-host pull hints in init and list

- Document per-host hints emitted during init -r clone
- Clarify list --all output includes per-host pull guidance
- Reference findHostConfigs enumeration in init flow

* fix: handle edge cases in CLI output for status, pull, and rm commands

- Add displayNoRemoteStatus to handle repositories without a remote configured
- Update Pull() and RestoreSymlinks() to return RestoreInfo with backup info
- Add writeBackupNotice to report files renamed to .lnk-backup during restore
- Improve rm command output when removing symlinks
- Update all related tests and type exports

* docs: update context to document RestoreInfo API and improved CLI output

- Document RestoreInfo return type for Pull and RestoreSymlinks
- Update sync flow documentation for no-remote handling in status command
- Add terminology for .lnk-backup files and RestoreInfo struct
- Document improved remove/force-remove command output with host support
- Update doctor flow to reflect BackedUp field reporting
- Clarify backup file handling and restoration behavior

* fix: honor --quiet for bootstrap output and skip diff materialization

Two gaps in the --quiet contract on this branch:

- `lnk bootstrap` and the auto-bootstrap path in `lnk init -r` invoked
  RunBootstrapScript with raw os.Stdout/os.Stderr, so any script that
  printed leaked through despite --quiet. Route script I/O through the
  cobra command's writers, and substitute io.Discard in both slots when
  the writer reports Quiet().

- `lnk -q diff` still called Diff(false), which buffered the entire
  patch only to discard it. Add Git.HasDiff (running `git diff --quiet`
  and decoding the exit code) plus matching Syncer/Lnk delegates, and
  use it from the diff command's quiet branch so the patch is never
  produced.

* fix: signal dirty state via non-zero exit in `diff --quiet`

The previous round preserved exit code 0 in `lnk diff --quiet` (matching
the prior test) but that defeats the documented "exit code only" contract
— CI/scripts cannot detect uncommitted changes from quiet mode.

Quiet mode now returns a sentinel error when `HasDiff` reports changes,
which yields exit 1 while the writer continues to suppress all stdout
and the global quiet config keeps DisplayError silent. Test updated to
assert: clean → no error, dirty → error, both with empty stdout/stderr.

Also picks up a gofmt-only whitespace fix in cmd/init.go.
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