Skip to content

feat: add -C <path> flag to change directory before running#3442

Merged
maphew merged 3 commits into
gastownhall:mainfrom
rjc123:feat/directory-flag
Apr 27, 2026
Merged

feat: add -C <path> flag to change directory before running#3442
maphew merged 3 commits into
gastownhall:mainfrom
rjc123:feat/directory-flag

Conversation

@rjc123

@rjc123 rjc123 commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds persistent -C/--directory flag to the root command, matching git -C behaviour
  • Calls os.Chdir() early in PersistentPreRun — before any .beads/ discovery, environment loading, or store initialisation
  • Allows running bd commands against a different project directory without cd first

Motivation

AI coding agents (Claude Code, Cursor, etc.) often run in a working directory different from the beads project. Currently this requires either:

  • cd /path/to/project && bd ready (chaining, which some agent frameworks disallow)
  • Setting BEADS_DIR env var (verbose, easy to forget)

git -C solves this problem cleanly for git — bd -C brings the same ergonomics.

Example

# From any directory:
bd -C ~/projects/myapp ready
bd -C ~/projects/myapp show bd-abc123

Test plan

  • Integration test: ready_with_C_flag in ready_embedded_test.go — runs bd ready from a temp dir using -C to target the beads project
  • Existing commands without -C continue to work (no default changes)

🤖 Generated with Claude Code

@codecov-commenter

codecov-commenter commented Apr 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 28.16901% with 51 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
internal/beads/beads.go 0.00% 35 Missing ⚠️
cmd/bd/main.go 55.55% 12 Missing and 4 partials ⚠️

📢 Thoughts on this report? Let us know!

@rjc123 rjc123 force-pushed the feat/directory-flag branch from 7b3593a to 2cc297d Compare April 26, 2026 08:58
@rjc123

rjc123 commented Apr 26, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto current main. Resolved one conflict in ready_embedded_test.go — upstream added the --exclude-label test in the same location; kept both test cases. The ready_with_C_flag subprocess test runs bd -C <dir> ready from a directory with no .beads/, which exercises the os.Chdir path in main.go and should resolve the patch coverage gap.

@maphew maphew left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the -C flag implementation. The feature is useful, but I’m requesting changes because the current implementation mutates process-global cwd in PersistentPreRun via os.Chdir. That risk profile is too high for this CLI: in-process command executions/tests can leak cwd state across commands, and startup/global command behavior is already sensitive.\n\nPlease rework this toward selected-context routing or target repo resolution instead of global cwd mutation. At minimum, add stronger coverage for invalid -C paths and repeated/in-process command execution so cwd cannot leak across commands.\n\nSuggested validation after rework: scripts/pr-preflight.sh 3442 --repo gastownhall/beads; CGO_ENABLED=1 go test -tags gms_pure_go ./cmd/bd -run '^TestEmbeddedReady/ready_with_C_flag$'; make test.

Adds a persistent -C/--directory flag (matching git -C) that calls
os.Chdir before .beads/ discovery or database initialisation. Allows
running bd commands against a different project without changing
directory first.

Example: bd -C ~/projects/myapp ready

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rjc123 rjc123 force-pushed the feat/directory-flag branch from 2cc297d to b3c8ab8 Compare April 27, 2026 14:59
@rjc123

rjc123 commented Apr 27, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the os.Chdir concern.

What changed: Instead of permanently mutating the process cwd, the -C handler now:

  1. Saves the original cwd
  2. Temporarily Chdirs to the target directory
  3. Calls beads.FindBeadsDir() to resolve .beads/ using the existing git-aware discovery logic
  4. Sets BEADS_DIR to the resolved path
  5. Restores the original cwd immediately

Net effect: the process cwd is unchanged after -C processing. BEADS_DIR is already the canonical mechanism for pointing at a project, and FindBeadsDir() checks it first, so all subsequent command logic works correctly.

New test coverage (three cases added):

  • ready_with_C_flag_invalid_dir — passes a non-existent path; verifies the command fails with a clear "cannot change to directory" message. Covers the previously-missing error branch.
  • ready_with_C_flag_does_not_leak_cwd — runs two sequential subprocesses from the same tmpDir (no .beads/): first with -C succeeds, second without -C fails. Both use the same stripped env (no BEADS_*), proving the fix does not leak BEADS_DIR between invocations.
  • Existing ready_with_C_flag continues to pass.

Resolve -C by binding command selection to the target project's .beads directory instead of calling os.Chdir. Add focused coverage for invalid targets and no process cwd mutation.\n\nCo-authored-by: Robin Carswell <2803445+rjc123@users.noreply.github.com>
@maphew

maphew commented Apr 27, 2026

Copy link
Copy Markdown
Collaborator

Addressed the os.Chdir concern in f68f3d3ae241e3fab9781ad51d5c4d4505adf491.\n\nChanges:\n- Removed the os.Chdir-based -C implementation.\n- Added target-directory resolution via beads.FindBeadsDirFrom, then binds the command to the resolved project through BEADS_DIR without mutating process cwd.\n- Restores selector env after command execution for in-process/repeated command safety.\n- Fails clearly for invalid -C targets and existing directories that are not beads projects, avoiding fallback to the caller cwd.\n- Kept the contributor subprocess coverage and added unit coverage for no cwd mutation.\n\nLocal validation:\n- go test -tags gms_pure_go ./cmd/bd -run 'TestResolveChangeDirBeadsDir'\n- go test ./internal/beads\n- BEADS_TEST_EMBEDDED_DOLT=1 CGO_ENABLED=1 go test -tags gms_pure_go ./cmd/bd -run '^TestEmbeddedReady/ready_with_C_flag' -count=1 -v\n- make test\n\nPreflight now sees the new head but remains blocked while GitHub checks are pending and the existing CHANGES_REQUESTED review is still in force.

@maphew maphew left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The cwd-mutation concern is addressed in f68f3d3. The implementation now resolves the target beads project without os.Chdir, scopes/restores selector env, and has focused invalid-target/no-cwd-mutation coverage. Local validation passed: targeted cmd/bd resolver test, internal/beads test, embedded ready -C subtests with BEADS_TEST_EMBEDDED_DOLT=1, and make test.

t.TempDir() returns paths under /var/folders on macOS, but
resolveChangeDirBeadsDir canonicalizes via EvalSymlinks to
/private/var/folders. Resolve projectDir up front so the
expected and actual paths match on every OS.
@maphew maphew merged commit 7358de6 into gastownhall:main Apr 27, 2026
38 of 39 checks passed
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.

3 participants