Skip to content

BULLPEN_HOME: run bullpen against an isolated state directory (#8) - #10

Merged
Steel-tech merged 2 commits into
mainfrom
feat/bullpen-home-env
Aug 8, 2026
Merged

BULLPEN_HOME: run bullpen against an isolated state directory (#8)#10
Steel-tech merged 2 commits into
mainfrom
feat/bullpen-home-env

Conversation

@Steel-tech

@Steel-tech Steel-tech commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Every bullpen process wrote to the one ~/.bullpen. There was no way to run a
demo, an end-to-end test, or a second copy of bullpen without it sharing
sessions, credentials, and background logs with the real one — the README's own
recorded demo had to work around it, and a script wanting a scratch store had
nothing to set. BULLPEN_HOME is that switch.

Decisions a reviewer would otherwise have to reverse-engineer

Scope is the directory, not the database. The store, auth.json, and the
background logs all move together and land directly in $BULLPEN_HOME with no
.bullpen segment appended. Issue #8 names only the db and auth.json, but
logs/ is the third occupant of the same directory and its filenames are
session ids from that database. Relocating the db while logs stayed under
$HOME would produce logs keyed to sessions living somewhere else — precisely
the split-brain a single-directory concept exists to prevent.

Empty counts as unset. env::var_os returns Some("") for BULLPEN_HOME=.
Taken literally that resolves the store to a bare relative bullpen.db in
whatever directory the process happened to start in — a silent relocation of
someone's existing sessions, which is the one failure this change must not
introduce.

The resolver is duplicated on purpose. bullpen-store and bullpen-auth
are siblings: neither depends on the other, both depend only on bullpen-llm,
so there is no existing crate to share from, and pushing a state-directory
concern down into bullpen-llm would be the wrong home for it. A new
one-function workspace crate is not worth its manifest. Each crate carries its
own private resolve_home and its own fallback test, so a divergence
between the two copies fails CI rather than quietly relocating one of the two
files. cli::bg calls the store's public home_dir() rather than adding a
third copy. Worth revisiting if a fourth caller appears.

Why the tests target a pure function instead of setting env vars. Edition
2024 (toolchain pinned 1.97.1) makes std::env::set_var unsafe, and cargo test runs a binary's tests multi-threaded in one process — a test that mutated
HOME or BULLPEN_HOME would race every other test alongside it. So
resolve_home(Option<OsString>, Option<PathBuf>) takes the env values as
arguments and home_dir() is a thin wrapper that reads the process
environment. This matches the existing convention in this repo (status::derive
vs for_session, CodexCliBorrow::new vs default_path).

The issue asked for a test pinning the unset fallback so a future refactor
cannot silently relocate existing sessions; that is
unset_bullpen_home_still_resolves_under_dot_bullpen, present in both crates,
and it also pins the pre-existing no-$HOME relative fallback.

Not in scope

Not a rename, not a migration, no --store flag. Nothing on disk moves, and
with the variable unset every path is byte-for-byte what it is on main.

Verification

  • cargo fmt --all --check — clean.
  • cargo clippy --workspace --all-targets -- -D warnings — clean.
  • cargo test --workspace98 passed, 0 failed (was 94; the +4 are the new
    tests, +2 store, +2 auth). No existing test needed modification.
  • Against the built binary, because the pure tests deliberately leave the
    env-reading home_dir() wrapper uncovered:
    BULLPEN_HOME=<tmp> bullpen sessions --json created <tmp>/bullpen.db with
    no .bullpen segment; the same command with the variable unset still read the
    pre-existing ~/.bullpen/bullpen.db and returned its real sessions.

Refs #8

Summary by CodeRabbit

  • New Features

    • Added support for configuring the application’s data directory with BULLPEN_HOME.
    • Database, authentication credentials, and background logs are now stored in the configured directory.
    • Added fallback to ~/.bullpen, or ./.bullpen when the home directory is unavailable.
  • Documentation

    • Updated architecture, setup, and command help documentation to describe configurable storage locations and fallback behavior.

Every bullpen process wrote to the one `~/.bullpen`, so there was no way to
run a demo, a test, or a second copy of bullpen without it sharing sessions,
credentials, and logs with the real one. The README's own recorded demo had
to work around this, and any script wanting a scratch store had nothing to
set.

`BULLPEN_HOME` moves the whole directory, not just the database. The store,
`auth.json`, and the background logs all land directly in it with no
`.bullpen` segment appended. Splitting them — a relocatable database with
logs still under `$HOME` — would leave logs keyed to session ids that live in
a database somewhere else, which is the split-brain the single-directory
concept exists to prevent.

Empty counts as unset. `env::var_os` hands back `Some("")` for
`BULLPEN_HOME=`, which taken literally would resolve the store to a bare
relative `bullpen.db` in whatever directory the process happened to start
in — a silent relocation of someone's sessions, the exact failure this change
must not introduce.

`store` and `auth` are siblings — neither depends on the other, both only on
`bullpen-llm` — so there is no existing crate to share the resolver from, and
a one-function crate is not worth its manifest. Each carries its own private
`resolve_home` and its own fallback test, so a divergence between the two
copies fails CI rather than quietly relocating one of the two files. `cli`
calls the store's public `home_dir()` for the logs directory.

Both `resolve_home`s are pure, taking the env values as arguments; only the
`home_dir()` wrapper reads the process environment. That is not a style
preference: edition 2024 makes `env::set_var` unsafe and `cargo test` runs
the suite multi-threaded in one process, so a test that mutated `HOME` would
race every other test in its binary.

Additive. No migration, no rename, no `--store` flag, and nothing on disk
moves. With the variable unset every path is byte-for-byte what it was.

Verified: fmt, clippy -D warnings, and 98 workspace tests green (4 new — the
required unset-fallback assertion and the override, in both crates). Also
checked against the built binary, since the pure tests deliberately leave the
env-reading wrapper uncovered: `BULLPEN_HOME=<tmp> bullpen sessions --json`
created `<tmp>/bullpen.db` with no `.bullpen` segment, and the same command
with the variable unset still read the pre-existing `~/.bullpen/bullpen.db`
and returned its real sessions.

Refs #8

Claude-Session: https://claude.ai/code/session_01PfAfAujueuZ3rDTiL9apx3

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5d91a21f-9d29-4995-8462-d96a3cbe49a0

📥 Commits

Reviewing files that changed from the base of the PR and between e43cf6c and f7b9992.

📒 Files selected for processing (2)
  • crates/auth/src/lib.rs
  • crates/store/src/lib.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/auth/src/lib.rs
  • crates/store/src/lib.rs

📝 Walkthrough

Walkthrough

Bullpen now supports BULLPEN_HOME for authentication, database, and background log storage. Authentication and store crates resolve this variable with fallback paths. CLI help and project documentation describe the configurable directory.

Changes

BULLPEN_HOME path resolution

Layer / File(s) Summary
Home resolution and default paths
crates/auth/src/lib.rs, crates/store/src/lib.rs, crates/cli/src/bg.rs
Added BULLPEN_HOME resolution with home-directory and relative fallbacks. Authentication, database, and log paths now use the resolved directory. Tests cover unset, empty, and override values.
CLI and documentation updates
crates/cli/src/main.rs, README.md, ARCHITECTURE.md
Updated CLI help and documentation to describe BULLPEN_HOME and the locations of database, authentication, and log files.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant HomeResolution
  participant Storage
  CLI->>HomeResolution: Resolve BULLPEN_HOME or fallback directory
  HomeResolution->>Storage: Provide resolved home directory
  Storage->>Storage: Build database and log paths
Loading

Possibly related issues

🚥 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 and concisely describes the main change: adding BULLPEN_HOME support for isolated state directories.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/bullpen-home-env

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 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 `@ARCHITECTURE.md`:
- Line 33: Update both BULLPEN_HOME directory references in ARCHITECTURE.md to
state that a non-empty BULLPEN_HOME value overrides the default ~/.bullpen
location, while an empty value continues to fall back to ~/.bullpen.

In `@crates/auth/src/lib.rs`:
- Around line 5-7: Update the module documentation describing BULLPEN_HOME to
state that only a non-empty value selects $BULLPEN_HOME/auth.json; explicitly
document that an unset or empty BULLPEN_HOME falls back to ~/.bullpen/auth.json.

In `@crates/store/src/lib.rs`:
- Around line 98-99: Update the documentation comment for the Bullpen state
directory to clarify that only a non-empty BULLPEN_HOME value overrides the
~/.bullpen fallback; an unset or empty value uses the fallback.

In `@README.md`:
- Around line 129-130: Update the README SQLite command to match the resolver’s
fallback behavior: when both BULLPEN_HOME and HOME are empty, resolve the
database path under ./.bullpen rather than /.bullpen. Preserve the existing
BULLPEN_HOME and HOME precedence.
🪄 Autofix

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3eddbcb6-e7df-4bbf-a058-0027fd8bd419

📥 Commits

Reviewing files that changed from the base of the PR and between 6e56c61 and e43cf6c.

📒 Files selected for processing (6)
  • ARCHITECTURE.md
  • README.md
  • crates/auth/src/lib.rs
  • crates/cli/src/bg.rs
  • crates/cli/src/main.rs
  • crates/store/src/lib.rs

Comment thread ARCHITECTURE.md
Comment thread crates/auth/src/lib.rs Outdated
Comment thread crates/store/src/lib.rs Outdated
Comment thread README.md
@Steel-tech
Steel-tech merged commit 7dbb753 into main Aug 8, 2026
5 checks passed
@Steel-tech
Steel-tech deleted the feat/bullpen-home-env branch August 8, 2026 07:38
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