Audited: 2026-05-10
Version: Peekaboo 3.0.0
Source: Apps/CLI/Sources/PeekabooCLI/
Guidelines: clig.dev (main branch, May 2025)
- Argument parsing library — Uses
Commander(Swift), a proper argument parsing framework that handles flags, arguments, help rendering, and subcommand routing. - Exit codes — Returns
EXIT_SUCCESS(0) on success,EXIT_FAILURE(1) on error, viaPeekabooEntryPoint.swift:31-40. Non-zero exit codes map to specific failure modes. - stdout for primary output — Commands emit results (JSON, text) to stdout via
print(). - stderr for messaging — Logger writes all log/debug messages to stderr via
fputs(..., stderr)(CLILogger.swift:123). Errors in non-JSON mode also go to stderr (PeekabooEntryPoint.swift:65,82).
-hand--helpsupported — Both flags trigger help display (CommanderRuntimeRouter.swift:179-180). Works for root and all subcommands.helpsubcommand pattern —peekaboo help,peekaboo help <command>,peekaboo <command> --helpall work (CommanderRuntimeRouter.swift:67-93).- Concise help on bare invocation — Running
peekaboowith no args prints the root help card with usage , categorized command list, and global flags (CommanderRuntimeRouter.swift:15-17,201-221). Commands withshowHelpOnEmptyInvocation: truealso show help when invoked without required args. - Formatted help text — Bold headings, colored accents, and structured layout via
HelpTheme(CommanderRuntimeRouter+Help.swift:149-177). Colors are disabled gracefully when not in a TTY. - Most common flags displayed first — Global flags section shows
--json,--verbose,--log-levelprominently (CommanderRuntimeRouter+Help.swift:54-74). - Commands categorized — Root help groups commands by category (Core, Interaction, System, Vision, AI, MCP) (
CommanderRuntimeRouter.swift:206-216). - Examples in help text —
ListCommandandCompletionsCommandinclude detailed examples and usage patterns in theirdiscussionfields. - Spelling/typo suggestions — Commander framework provides unknown-command error messages (
PeekabooEntryPoint.swift:53-54).
--jsonflag for machine-readable output — Supported globally via--json,-j, and--json-output(PeekabooEntryPoint.swift:43-45). JSON responses follow a consistent{success, data, messages, debug_logs, error}envelope (JSONOutput.swift:24-44,167-172).- Color disabled when not a TTY —
TerminalDetection.swiftchecksisatty(),NO_COLOR,TERM=dumb, CI environments, and piped output. NO_COLORenvironment variable respected — Explicitly checked; sets output mode to.minimal(TerminalDetection.swift:213-215).FORCE_COLOR/CLICOLOR_FORCErespected — Both force enhanced output mode (TerminalDetection.swift:218-220).TERM=dumbhandled — Falls back to no-color on non-macOS whenTERM=dumb(TerminalDetection.swift:148).- CI environment detection — Checks 20+ CI env vars (GitHub Actions, GitLab CI, Jenkins, etc.) and disab
les rich output (
TerminalDetection.swift:69-87). - Terminal dimensions detected — Uses
ioctl(TIOCGWINSZ)with fallback toCOLUMNS/LINESenv vars (TerminalDetection.swift:90-105). - Spinner/progress indicators —
PeekabooSpinnershows progress during long operations; adapts to color capabilities (PeekabooSpinner.swift). - Errors sent to stderr — In non-JSON mode, errors print to stderr. In JSON mode, errors are structured in the JSON envelope.
- Structured error codes — 30+ specific
ErrorCodevalues for programmatic error handling (JSONOutput.swift:66-103).
- Full-length flag versions — All flags have long forms (e.g.,
--json/-j,--verbose/-v,--help/-h,--version/-V). - Standard flag names — Uses conventional names:
--help/-h,--version/-V,--verbose/-v,--json/-j,--force,--path,--app. - Flags preferred over positional args — Most commands use named flags (
--app,--mode,--path, etc.) rather than positional arguments.
- Consistent across subcommands — All commands share global flags (
--json,--verbose,--log-level), consistent help rendering, and the same JSON response envelope. - Consistent noun-based naming — Commands follow a
noun verbpattern:list apps,list windows,permissions status,permissions grant,capture live,capture video. - Default subcommands —
listdefaults toapps,permissionsdefaults tostatus— sensible defaults for the most common operation.
- Responsive output — Spinner starts immediately for long operations.
- Input validation — Flag values are validated early with descriptive errors (e.g.,
CaptureCommandOptionParservalidates diff strategy values).
- Config precedence — Follows the recommended order: flags > env vars > project config > user config > defaults (
CLIConfiguration.swift:118-131). PEEKABOO_LOG_LEVELenv var — Configurable via environment (CLILogger.swift:54-57).PEEKABOO_OUTPUT_MODEenv var — Controls output verbosity via environment (TerminalDetection.swift:204-210).- Config stored in
~/.peekaboo— Follows home-directory convention for user config.
- Uppercase names — All env vars use uppercase with underscores (e.g.,
PEEKABOO_LOG_LEVEL,PEEKABOO_OUTPUT_MODE,NO_COLOR). - Standard env vars checked —
NO_COLOR,FORCE_COLOR,TERM,COLUMNS,LINES,SHELL.
- Simple, memorable name —
peekaboois lowercase, memorable, and distinctive. - Lowercase with no special characters — Follows the convention perfectly.
- Single binary — Swift compiles to a native binary; distributed as a single executable.
- Ctrl-C handling — Spinner clears on interruption; async tasks use Swift's cooperative cancellation.
- Completions for zsh, bash, fish —
peekaboo completionsgenerates shell-specific completion scripts with auto-detection of the current shell (CompletionsCommand.swift).
--versionflag — Displays full version info including git commit, branch, and build date (Version.swift:9-11,CommanderRuntimeRouter.swift:154-159).
- Files:
CommanderRuntimeRouter+Help.swift,CommanderRuntimeRouter.swift:201-221 - Issue: The root help text does not include a URL to file issues, a website link, or a pointer to web-based documentation. Users encountering problems have no guidance on where to seek help.
- Fix: Add a footer line to
printRootHelpsuch as"Documentation: https://peekaboo.dev | Issues: https://github.com/<org>/peekaboo/issues". - CLIG section: Help — "Provide a support path for feedback and issues" and "In help text, link to the web version of the documentation."
- Files: Global flag set in
CommanderRuntimeRouter+Help.swift:54-74 - Issue: The CLI offers
--jsonfor machine-readable output, but no--plainmode for simple tabular t ext suitable forgrep/awk. Commands that list apps, windows, or screens emit formatted text with emoji and color that breaks pipeline usage. - Fix: Add a global
--plainflag that disables emoji, color, and formatting, emitting tab-separated or fixed-width rows. - CLIG section: Output — "If human-readable output breaks machine-readable output, use
--plainto display output in plain, tabular text format."
- Files:
TerminalDetection.swift - Issue: Color can be disabled via the
NO_COLORenv var andPEEKABOO_OUTPUT_MODE=minimal, but there is no--no-colorcommand-line flag. CLIG recommends--no-coloras a flag option alongside the env var. - Fix: Add
--no-colorto the global runtime flags inCommandRuntimeOptions. - CLIG section: Output — "The user passes the option
--no-color."
- Files: Various list/help commands
- Issue: Commands like
peekaboo list appsorpeekaboo helpcan produce output that exceeds the terminal height, but output is never piped through a pager likeless. - Fix: For commands that may produce long output, pipe through
$PAGER(orless -FIRX) when stdout is an interactive TTY. - CLIG section: Output — "Use a pager (e.g.
less) if you are outputting a lot of text."
- Files:
PeekabooSpinner.swift - Issue: The spinner does not check whether stdout is an interactive terminal before starting. If output is piped or redirected, spinner escape sequences could corrupt the stream. The spinner adapts to color capa bility but not to TTY-ness.
- Fix: Guard
PeekabooSpinner.start()with anisatty(STDOUT_FILENO)check; skip the spinner entirely when not interactive. - CLIG section: Output — "If
stdoutis not an interactive terminal, don't display any animations."
- Files:
CommanderRuntimeRouter.swift:184 - Issue: The short version flag is
-V(uppercase). While not strictly wrong, CLIG notes that-vis ambiguous between verbose and version, and recommends using-dfor verbose to free-vfor version. The current mapping (-v= verbose,-V= version) inverts the more common convention where lowercase-vmeans version (e.g.,curl -vis verbose, butgit -vis version). This inconsistency may confuse users. - Fix: Consider this a minor style choice. Document the convention clearly. No change strictly required, but be aware of the ambiguity.
- CLIG section: Arguments and Flags — "
-v: This can often mean either verbose or version."
- Files: Global flag set
- Issue: There is no
--no-inputflag. Scripts calling potentially interactive commands (e.g.,peekaboo agent,peekaboo config) cannot reliably suppress prompts. - Fix: Add a global
--no-inputflag that disables all prompting and treats missing required input as an error. - CLIG section: Interactivity — "If
--no-inputis passed, don't prompt or do anything interactive."
- Files: Global flag set
- Issue: There is no global
-q/--quietflag. Only theagentcommand has a quiet concept (AgentMes sages.quietDisabled). For scripting, users should be able to suppress all non-essential output across any command. - Fix: Add
-q/--quietto global flags, suppressing all non-essential human-readable output (success messages, hints, tips). - CLIG section: Output — "Provide a
-qoption to suppress all non-essential output."
- Files:
PeekabooEntryPoint.swift:74-89 - Issue: When an unexpected error occurs (
printGenericError), the error message is printed but there is no suggestion to file a bug report or link to an issue tracker. - Fix: For
UNKNOWN_ERRORcodes, append a line like:"If this is unexpected, please report it at https://github.com/<org>/peekaboo/issues". - CLIG section: Errors — "If there is an unexpected error, provide instructions on how to submit a bug."
- Files:
CLIConfiguration.swift:21-22 - Issue: Configuration is stored in
~/.peekaboorather than following the XDG Base Directory Specification ($XDG_CONFIG_HOME/peekabooor~/.config/peekaboo). While~/.peekaboois a common convention, CLIG recommends XDG compliance to reduce home directory clutter. - Fix: Support
$XDG_CONFIG_HOME/peekabooas the primary location, falling back to~/.peekaboofor backward compatibility. - CLIG section: Configuration — "Follow the XDG-spec."
- Files:
ImageCommand+Output.swift,ImageCommand.swift - Issue:
peekaboo imagealways writes to a file and prints the path. There is no way to write binary image data to stdout using--path -(or-o -), which would allow piping directly into tools likeconvert,pngquant,base64, orpbcopy. This is a common UNIX convention for commands that produce file output. - Fix: When
--pathis set to-, write the image bytes to stdout instead of saving to a file. Suppress all non-essential human-readable output (emoji, path descriptions) in this mode, and ensure logging goes only to stderr. - CLIG section: Arguments and Flags — "If input or output is a file, support
-to read fromstdinor write tostdout."
- Files:
CommanderRuntimeRouter+Help.swift:26-28,49-51 - Issue: Both root and command help cards include a "Tip" suggesting
polter peekaboofor local development. This is developer-internal guidance that is meaningless to end users and violates the principle of not showing developer-only information by default. - Fix: Remove the "Tip" section from user-facing help, or gate it behind
--verbose/ aDEBUGcheck. - CLIG section: Output — "By default, don't output information that's only understandable by the creators of the software."
- stdin piping — Reading from stdin is not a primary use case for a screen capture tool.
- Man pages — Nice-to-have but not critical for a macOS-specific tool; shell completions and
--helpcover discoverability. - Dry-run (
--dry-run) — Most commands are read-only (capture, list, see). Interaction commands (click, type) could benefit but the risk is low. - Password/secret prompting — Secrets are managed via config files in
~/.peekaboo, not passed as flags. This is already the recommended approach. - Analytics/telemetry — No evidence of any telemetry. This is compliant by absence.
- Arbitrary subcommand abbreviations — Not supported. This is correct per CLIG.
- Catch-all subcommand — Not used. Commands require explicit subcommand names.
25 passes | 12 violations | 7 not applicable
The CLI has strong fundamentals: proper stdout/stderr separation, structured JSON output, comprehensive help with categorized commands, terminal capability detection, NO_COLOR support, CI-aware output adaptation, and consistent subcommand patterns. The violations are primarily around missing global flags (--plain, --no-color, --quiet, --no-input), no stdout piping for binary output (- convention), the absence of a support/docs URL in help text, and the developer-facing "Tip" leaking into user-visible help.