Skip to content

fix(screenshot): honor --output paths with a directory component#119

Open
HermeticOrmus wants to merge 2 commits into
VibiumDev:mainfrom
HermeticOrmus:fix/screenshot-honor-output-path
Open

fix(screenshot): honor --output paths with a directory component#119
HermeticOrmus wants to merge 2 commits into
VibiumDev:mainfrom
HermeticOrmus:fix/screenshot-honor-output-path

Conversation

@HermeticOrmus

@HermeticOrmus HermeticOrmus commented Apr 30, 2026

Copy link
Copy Markdown

Why

vibium screenshot -o /tmp/foo.png (or ./foo.png, or subdir/foo.png) silently lands at ~/Pictures/Vibium/foo.png — the daemon strips any path information down to the basename and joins with the configured screenshot dir. Driving vibium against SPAs from a project working dir, every screenshot needed a follow-up mv to land where I expected.

The basename-strip is guarded by a "prevent path traversal" comment, but the daemon is local-only and the flag is supplied by the operator who already controls the host — the guard wasn't buying real safety, just costing usability.

What changed

The CLI resolves any -o value with a directory component to an absolute path against the operator's CWD before sending to the daemon. The daemon honors a filename-with-directory as written; bare basenames still go to the configured screenshotDir, so the "Screenshots save to a sensible location automatically" default from CLAUDE.md is preserved.

Input Before After
-o foo.png ~/Pictures/Vibium/foo.png ~/Pictures/Vibium/foo.png (unchanged)
-o ./foo.png ~/Pictures/Vibium/foo.png <cwd>/foo.png
-o /tmp/foo.png ~/Pictures/Vibium/foo.png /tmp/foo.png
-o subdir/foo.png ~/Pictures/Vibium/foo.png <cwd>/subdir/foo.png (parent auto-created)

Help text and -o flag description updated to document the new behaviour.

How to test

make build-go
node --test tests/daemon/cli-commands.test.js

New cases under Daemon CLI: Screenshot honors --output path:

  • absolute path is honored as written
  • relative path with ./ prefix lands in CWD, not screenshot dir
  • subdir relative path creates parent and saves there
  • bare basename still goes to default screenshot dir (regression guard)

All 4 pass; the existing Screenshot --full-page test continues to pass with default behaviour unchanged.

Notes

  • The pre-existing Daemon CLI: quit command test fails on main too — it references a vibium quit command that no longer exists in the binary. Not introduced here, but flagging.
  • make test couldn't run on this Linux dev box because npm install errors with Invalid Version: during dedup of the @vibium/<platform> optionalDependencies (npm 11.12.1 + arborist quirk). Daemon test ran directly with node --test, which only depends on the locally-built binary at clicker/bin/vibium.

Before this change, `vibium screenshot -o /tmp/foo.png` (or `./foo.png`,
or `subdir/foo.png`) silently landed at `~/Pictures/Vibium/foo.png` —
the daemon stripped any path information down to the basename and joined
with the configured screenshot dir. The behaviour was guarded by a
"prevent path traversal" comment, but the daemon is local-only and the
flag is supplied by the operator who already controls the host, so the
guard was costing usability without buying real safety.

Now:

- `-o foo.png`            → `~/Pictures/Vibium/foo.png` (default preserved)
- `-o ./foo.png`          → `<cwd>/foo.png`
- `-o /tmp/foo.png`       → `/tmp/foo.png`
- `-o subdir/foo.png`     → `<cwd>/subdir/foo.png` (parent dir auto-created)

The CLI resolves any path with a directory component to an absolute path
against the operator's CWD before sending to the daemon, so relative
paths land where the operator typed them rather than against the daemon
process's CWD.

Backwards compatible: a bare basename (no separator) still uses the
configured `screenshotDir`, preserving the "Screenshots save to a
sensible location automatically" default from CLAUDE.md.

Tests:

- `tests/daemon/cli-commands.test.js` gains 4 new cases under
  "Daemon CLI: Screenshot honors --output path" covering absolute,
  relative, subdir, and bare-basename inputs.
- The existing `Screenshot --full-page` test continues to pass —
  it uses a bare basename and the default behaviour is unchanged.
- All 4 new tests pass locally; the only failing test in
  cli-commands.test.js is the pre-existing `Daemon CLI: quit
  command` which references a `vibium quit` command that no longer
  exists in the binary (unrelated to this PR).
Drop multi-line comment blocks and verbose flag prose for the project's
"one short line max" comment style.
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