See CLAUDE.md for working agreements, jj/version-control rules, and Rust + testing conventions.
Normal tests use unit tests, fake-gh integration tests, and real local jj
repositories. They do not create network resources. Never mock jj or git —
only gh may be faked. See CLAUDE.md for the full testing policy.
The real GitHub E2E is opt-in:
FORKLIFT_REAL_GITHUB_E2E=1 \
FORKLIFT_E2E_OWNER=<owner> \
FORKLIFT_E2E_REPO_PREFIX=forklift-e2e \
cargo test --test real_github -- --nocapture
It creates a disposable private repository with gh repo create, submits a
two-change stack, edits one submitted change, submits again, verifies the same
PRs were updated, attempts forklift merge, and deletes the repository with
gh repo delete --yes. Set FORKLIFT_E2E_KEEP_REPO=1 to keep the disposable
repo and local temp dir for debugging. Cleanup requires the delete_repo scope:
gh auth refresh -s delete_repo.
Global options:
--dry-run: plan actions without mutating local cache, remote refs, jj, or GitHub.--verbose: print resolved config, stack details, planned mutations, external commands, and recovery phases.
Debug logs are written automatically to .jj/repo/stack/logs/ when possible,
falling back to $XDG_STATE_HOME/forklift/logs/. FORKLIFT_LOG controls the
file log filter and defaults to warn,forklift=debug; set it to trace for a
full trace or off to disable file logging. Stderr tracing is opt-in via
FORKLIFT_LOG_STDERR=1, or set FORKLIFT_LOG_STDERR to a tracing filter.
Stack commands accept --revset <REVSET> to operate on a narrower jj stack than
the default trunk()..@ & ~::(immutable_heads() | root()) & ~empty().
Configuration is read from jj config, then git config, then defaults:
stack.remote: defaults tooriginstack.trunk: defaults tomainstack.require-approval: defaults totruestack.branch-prefix: defaults tostack
GitHub repository and username are resolved through the gh CLI.