Skip to content

feat(daemon): add --local flag for git-free daemon operation#433

Merged
steveyegge merged 3 commits intogastownhall:mainfrom
loupgaroublond:claude/decouple-git-daemon-01Dd46aFxX4KjjuMfGQE1Gw6
Dec 2, 2025
Merged

feat(daemon): add --local flag for git-free daemon operation#433
steveyegge merged 3 commits intogastownhall:mainfrom
loupgaroublond:claude/decouple-git-daemon-01Dd46aFxX4KjjuMfGQE1Gw6

Conversation

@loupgaroublond
Copy link
Copy Markdown
Contributor

Add --local mode to the daemon that allows it to run without a git repository. This decouples the daemon's core functionality (auto-flush to JSONL, auto-import from JSONL) from git synchronization.

NOTE: Claude Code did all the heavy lifting here, though I did apply amateur eyeballs to the code before submitting. I didn't see any signs this code will run rm -rf / on your grandma's computer.

Changes:

  • Add --local flag to daemon command
  • Skip git repo check when --local is set
  • Add validation that --auto-commit and --auto-push cannot be used with --local
  • Create local-only sync functions that skip git operations:
    • createLocalSyncFunc: export-only for polling mode
    • createLocalExportFunc: export without git commit/push
    • createLocalAutoImportFunc: import without git pull
  • Update startup message to indicate LOCAL mode
  • Update event loop to use local functions when in local mode

This enables use cases like:

  • Single-machine issue tracking without git
  • Auto-flush to JSONL for backup purposes
  • Running daemon in environments without git access

Multi-machine sync still requires git (as expected).

Add --local mode to the daemon that allows it to run without a git
repository. This decouples the daemon's core functionality (auto-flush
to JSONL, auto-import from JSONL) from git synchronization.

Changes:
- Add --local flag to daemon command
- Skip git repo check when --local is set
- Add validation that --auto-commit and --auto-push cannot be used with --local
- Create local-only sync functions that skip git operations:
  - createLocalSyncFunc: export-only for polling mode
  - createLocalExportFunc: export without git commit/push
  - createLocalAutoImportFunc: import without git pull
- Update startup message to indicate LOCAL mode
- Update event loop to use local functions when in local mode

This enables use cases like:
- Single-machine issue tracking without git
- Auto-flush to JSONL for backup purposes
- Running daemon in environments without git access

Multi-machine sync still requires git (as expected).
Copy link
Copy Markdown
Collaborator

@steveyegge steveyegge left a comment

Choose a reason for hiding this comment

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

PR Review: feat(daemon): add --local flag for git-free daemon operation

🔴 Critical Bug

validateDatabaseFingerprint will fail in local mode

At cmd/bd/daemon.go:396, validateDatabaseFingerprint() is called unconditionally. This function calls beads.ComputeRepoID() which executes git commands. In a non-git directory, this will fail and the daemon will exit.

// Line 396 - called regardless of localMode
if err := validateDatabaseFingerprint(ctx, store, &log); err != nil {

Fix: Skip validateDatabaseFingerprint when localMode is true.


🟡 Design Issues

1. Significant code duplication (~200 lines)

The three new functions are largely copy-paste of existing ones with git operations removed:

Original New Local Version
createSyncFunc createLocalSyncFunc
createExportFunc createLocalExportFunc
createAutoImportFunc createLocalAutoImportFunc

Suggestion: Refactor to use a single implementation with a skipGit bool parameter, or extract shared logic into helper functions.

2. Naming confusion

The codebase already has sync_local_only_test.go which tests repos without remotes (but still with git). The new --local flag means "no git at all". Consider --no-git or --standalone for clarity.


🟡 Missing Tests

No tests added for:

  • Daemon starting with --local flag
  • Validation that --local + --auto-commit fails
  • Validation that --local + --auto-push fails
  • Local sync/export/import functions working correctly

🟢 Good Things

  1. Good error messages with helpful hints
  2. Proper flag propagation through the call chain
  3. Correct startup message showing "LOCAL mode"
  4. Proper constraint validation for incompatible flags

Recommended Actions

  1. Must fix: Skip validateDatabaseFingerprint in local mode
  2. Should fix: Add tests for local mode
  3. Consider: Refactor to reduce code duplication
  4. Consider: Rename flag for clarity

@steveyegge steveyegge added the triaged Issue has been reviewed and responded to label Dec 1, 2025
@steveyegge
Copy link
Copy Markdown
Collaborator

Review: Add --local flag for git-free daemon operation

Good implementation overall. The decoupling of daemon core functionality from git sync is clean and well-structured.

Before merging, please address:

  1. Test coverage needed - 260+ lines of new code (3 new sync functions) without tests. Add tests for:

    • --local flag validation (rejects --auto-commit, --auto-push)
    • createLocalSyncFunc behavior
    • createLocalExportFunc behavior
    • createLocalAutoImportFunc behavior
  2. CI verification - No checks currently reported on this branch. Ensure tests pass with:

    go test ./...
    golangci-lint run ./...
    
  3. Code duplication - The lock-checking logic in the three new local functions duplicates existing ShouldSkipDatabase calls. Consider if this can be abstracted to reduce duplication.

Positive aspects:

  • ✅ Clear separation of concerns
  • ✅ Proper validation preventing invalid flag combinations
  • ✅ Comprehensive coverage of both polling and event-driven modes
  • ✅ Good logging distinguishing LOCAL mode status
  • ✅ No breaking changes to existing git-based workflows

Mark as ready to merge once tests are added and CI passes.

validateDatabaseFingerprint() calls beads.ComputeRepoID() which
executes git commands. This fails in non-git directories even
with --local flag.

Skip fingerprint validation entirely when running in local mode
since there's no git repository to validate against.
@loupgaroublond
Copy link
Copy Markdown
Contributor Author

I'm asking claude to take a look. First time trying Claude Code on the web, so it's pushing commits up to the PR before I have reviewed them, so expect a follow up note that this human has looked it over, eventually

Add tests for:
- Flag validation (--local incompatible with --auto-commit/--auto-push)
- Git check skip logic in local mode
- createLocalSyncFunc, createLocalExportFunc, createLocalAutoImportFunc
- Fingerprint validation skip in local mode
- Full integration test in non-git directory
- Export/import round-trip test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

triaged Issue has been reviewed and responded to

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants