This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This working tree is version-controlled by Libra, not Git: its metadata lives in .libra/ (there is no .git/). Run libra <command> for all version-control operations — git commands will not work here.
libra is installed on PATH. If it is missing locally, install it with:
curl --proto '=https' --tlsv1.2 -sSf https://download.libra.tools/install.sh | shIts CLI is largely Git-compatible, so the everyday commands map one-to-one — just swap the binary name:
libra status # not: git status
libra add <path> # not: git add
libra commit -m "..." # not: git commit
libra log # not: git log
libra diff # not: git diff
libra branch / switch / checkout / merge / rebase / push / pull / fetch …Compatibility is partial and governed by the four-tier matrix in COMPATIBILITY.md (supported / partial / unsupported / intentionally-different) — consult it before assuming a Git flag or subcommand behaves identically. Libra also adds AI-native subcommands with no Git equivalent (code, code-control, automation, usage, graph, sandbox, agent, publish).
(Note: this constraint is about operating in this repo. To build/test the Libra source itself, use the cargo commands in Build & Development Commands below; to run the in-tree build of the CLI use cargo run -- <command>.)
Libra is an AI agent–native version control system written in Rust. It partially implements a Git client with full on-disk format compatibility (objects, index, pack, pack-index) while using SQLite for transactional metadata (config, HEAD, refs). It is designed for monorepo/trunk-based development with tiered cloud storage (S3/R2) and a Cloudflare D1/R2 backup path.
The libra code command launches an interactive TUI (with a background web server, MCP server, and an automation-control session surface) for collaborative AI-agent and human-driven development. The Git surface is governed by a four-tier compatibility matrix (supported / partial / unsupported / intentionally-different) tracked in COMPATIBILITY.md; AI-only commands (code, code-control, automation, usage, graph, sandbox, agent, publish) are explicitly Libra-only extensions.
The repository also contains a Next.js frontend (web/) embedded into the binary via rust-embed and a Cloudflare Worker (worker/) for read-only libra publish hosting.
# Format code (requires nightly toolchain)
cargo +nightly fmt --all
# Lint — all warnings must be resolved before committing (all features on)
cargo clippy --all-targets --all-features -- -D warnings
# Quick compile check (skip the Next.js web build for speed)
LIBRA_SKIP_WEB_BUILD=1 cargo check
LIBRA_SKIP_WEB_BUILD=1 cargo build
# Run full test suite (L1 only by default; L2/L3 auto-skip when env vars are unset)
cargo test --all
# Run specific tests
cargo test command::init_test
cargo test add_test
# Run the CLI
cargo run -- <command> # e.g. cargo run -- status
# Build the embedded web frontend (normally driven by build.rs)
pnpm --dir web install --frozen-lockfile && pnpm --dir web build| Feature | Purpose |
|---|---|
worktree-fuse |
Enable Unix FUSE-backed worktree commands (Linux/macOS only) |
test-network |
Gate L2 tests requiring outbound network but no secrets |
test-live-ai |
Gate L3 tests calling real LLM APIs |
test-live-cloud |
Gate L3 tests hitting real D1/R2 endpoints |
test-provider |
Deterministic hidden provider for local TUI automation tests (requires LIBRA_ENABLE_TEST_PROVIDER=1) |
test-live-agent |
plan-20260713 live agent gate: real local claude/codex/opencode CLI data on the dev acceptance machine (requires LIBRA_RUN_LIVE_AGENT_GATE=1; missing stores print skipped) |
subagent-scaffold |
Schema-only sub-agent contract scaffold (CEX-S2-10, gated on CP-4 in production) |
test-upgrade |
plan-20260714 §A.11 auto-upgrade test hooks (trust-root/endpoint injection; needs LIBRA_TEST=1 at runtime; release builds must never enable it) |
otlp |
OTLP trace export (lore.md 1.7): one vetted command-span to an explicitly configured collector; default binary unaffected |
All PRs must pass these jobs on the [self-hosted] runner pool:
- compat-rustfmt —
cargo +nightly fmt --all --check - compat-clippy —
cargo clippy --all-targets --all-features -- -D warnings(withLIBRA_SKIP_WEB_BUILD=1) - compat-web-check —
pnpm --dir web lint+pnpm --dir web buildsoweb/out/cannot drift fromWebAssets - compat-redundancy — directory-shape check on
third-party/rust/crates - compat-offline-core —
cargo test --test compat_matrix_alignment compatibility_matrix_matches_cli_commands -- --exact+cargo test --all+ a second pass with--features test-providerfor the TUI automation matrices (code_ui_scenarios,harness_self_test,code_codex_default_tui_test,code_ui_remote_lease_matrix,code_ui_remote_sse_matrix) under--test-threads=1 - compat-network-remotes —
cargo test --features test-network --test network_remotes_test
Additional workflows: codeql.yml (security analysis), model-generation-nightly.yml (nightly model-generation matrix), release.yml (release pipeline).
Libra tests are organised into three layers — cargo test --all runs L1 only; L2/L3 are silently skipped when their env vars are unset. See docs/tests.md for the canonical guide.
| Layer | Dependencies | Trigger |
|---|---|---|
| L1 — Deterministic | None (tempdir, in-memory stores, mock models) | cargo test --all |
| L2 — Network | GitHub token for temporary repo creation | LIBRA_TEST_GITHUB_TOKEN + LIBRA_TEST_GITHUB_NAMESPACE |
| L3 — Live Services | Real AI API keys (DEEPSEEK_API_KEY, MOONSHOT_API_KEY, …) or cloud credentials (LIBRA_D1_*, LIBRA_STORAGE_*, LIBRA_TEST_S3_*) |
Set the relevant env vars |
Gate L2 / L3 tests with the small env_var_is_set(name) -> bool helper (see e.g. tests/cloud_storage_backup_test.rs:30) followed by an early eprintln!("skipped (...)") return when a required var is unset — missing vars print "skipped", never fail. Copy .env.test.example → .env.test and source it before running the full suite (the export prefix is required).
- Rust edition 2024, 4-space indentation
- Naming:
snake_casefor modules/functions,PascalCasefor types/traits,SCREAMING_SNAKE_CASEfor constants - Imports: Grouped as Standard → External → Crate per
rustfmt.toml(group_imports = "StdExternalCrate",imports_granularity = "Crate"); avoid wildcard imports except in tests
- CLI flows: Use
anyhow::Resultfor flexible error propagation - Library code: Use
thiserrorwith domain-specific error enums (e.g.,InitError,GitError) - Command handlers:
execute(args)is the public async entry; may return early without Result for simple CLI feedback - Database operations:
_with_connsuffix for transaction-safe variants acceptingConnectionTrait - Avoid
unwrap()/expect(): Prefer returningResultand propagating errors with?, attaching human-readable context via.context("...")or.with_context(|| format!(...))so end-users see actionable messages instead of panics.unwrap()/expect()are acceptable only in unit/integration tests and where the logic is obviously infallible (e.g., compile-time-known constants) with a brief// INVARIANT:comment. All other code — including program startup and initialization — must handle errors gracefully and return actionable messages. - User-friendly error messages: All errors surfaced to the user must be human-readable and actionable. Avoid exposing raw internal errors; wrap them with context that explains what went wrong, which resource was affected (path, ref, object ID), and how to fix it.
- Command structure: Each command in
src/command/<name>.rswith anArgsstruct (clap derive) andasync fn execute(args) - Extension traits:
TreeExt,CommitExt,BlobExtadd methods to git-internal types - Builder pattern: Used for
AgentBuilder, with validation in builder methods returningResult - Guard pattern (RAII):
ChangeDirGuardfor safe directory changes in tests - Provider pattern: Each AI provider has
mod.rs+client.rs+completion.rs - Global hash-kind preflight: Before dispatching most object-touching subcommands,
cli.rsreadscore.objectformat(defaulting to"sha1", also accepting"sha256") and callsgit_internal::hash::set_hash_kindso the entire process hashes consistently. New commands that read/write objects must run through this preflight rather than assuming SHA-1 or hard-coding object-ID byte lengths (20 vs 32).
- Module-level
//!doc comments explaining purpose - Function-level
///with# Arguments,# Returns,# Examplesections where helpful - Architecture notes as block comments (
/* ... */) for complex patterns like_with_conn - Add comments only when control flow is non-obvious (async handling, SQLite migrations)
- Integration tests in
tests/command/mirror real Git workflows; prefer these for new commands - Compatibility-surface tests in
tests/compat/guard against regressions in CLI flag/help wording, declined-feature drift, and the productionunwrap()audit. Each*.rsundertests/compat/must be registered as a[[test]]entry inCargo.toml(Cargo's default discovery only picks up files directly undertests/). New compat guards must also add a row to the inventory table intests/compat/README.md. Seedocs/tests.mdCompatibility-surface testssection for the full convention. - Cross-cutting
--helpEXAMPLES contract: every visible command insrc/cli.rs::Commandsships with apub const <CMD>_EXAMPLESconstant wired via#[command(after_help = …)](orafter_help = command::<name>::<CMD>_EXAMPLESon the parent subcommand binding incli.rsforSubcommand-style commands). Three compat guards protect this contract:compat_help_examples_banner(every<cmd> --helprenders an EXAMPLES section),cli::tests::root_after_help_lists_every_visible_command(every non-hidden command appears in a Command Groups row), andcompat_command_docs_examples_section(everydocs/commands/<name>.mdpage carries an Examples / Common Commands heading). New commands must satisfy all three. - Isolation: Use
tempfile::tempdir()andutils::test::ChangeDirGuardto isolate state - Serial execution: Mark tests
#[serial](fromserial_testcrate) if they mutate shared state - Async tests: Use
#[tokio::test](orflavor = "multi_thread"when needed) - Fixtures: Keep small and local in
tests/data/andtests/fixtures/; reuse helpers fromtests/command/mod.rs,tests/harness/, andtests/helpers/ - Gating: Use the
env_var_is_set(name)helper pattern (seetests/cloud_storage_backup_test.rs:30) plus an earlyeprintln!("skipped (set ...)")return so missing vars print a skip notice and do not fail the test. Match the L1/L2/L3 layering and the matchingtest-network/test-live-ai/test-live-cloudCargo features - Coverage: Pair new commands/options with at least one end-to-end test plus a focused unit test, and an entry in
COMPATIBILITY.mdif you change the Git surface. NewStableErrorCodevariants must also be added todocs/error-codes.md(thecompat_error_codes_doc_syncguard fails the build otherwise).
A change is considered done only when all three of the following pass locally with no manual fix-ups:
- Formatting —
cargo +nightly fmt --all --checkreports no formatting differences. - Lint —
cargo clippy --all-targets --all-features -- -D warningsreports no warnings. - Tests —
source .env.test && cargo test --allpasses in full (L1 always runs; L2/L3 print "skipped" rather than fail when their env vars are unset — that is acceptable, an actual failure is not).
These mirror the compat-rustfmt, compat-clippy, and compat-offline-core CI jobs, so passing them locally is the precondition for opening a PR. Run all three before reporting work as complete.
Use typed summaries with optional scope:
feat(status): support porcelain v2 (#82)
fix(push): record tracking reflog (#81)
refactor(ai): extract completion trait
test(merge): add three-way merge coverage
docs(readme): update provider table
- All CI checks pass (format, clippy zero-warnings, tests)
- State intent, linked issues, and tests run
- Include repro steps or sample CLI output for user-visible changes
- Keep changes small and cohesive
- Update README/CLI docs when adding flags or altering behavior
SQLite database at .libra/libra.db — inspect the concrete table set in the bootstrap SQL below (Git core, AI threads/scheduling, and AI runtime-contract groups).
Bootstrap files: sql/sqlite_20260309_init.sql (core + AI baseline) and sql/sqlite_20260415_ai_runtime_contract.sql (runtime-contract extension).
Versioned migrations live under sql/migrations/ and are applied by internal::db::migration::MigrationRunner. Filenames follow YYYYMMDDNN_<snake_case_name>.sql (forward) with optional matching *_down.sql (rollback). Forward DDL must be idempotent (CREATE TABLE IF NOT EXISTS …). See sql/migrations/README.md.
The publish Worker uses its own D1 schema in sql/publish/ (0001_publish.sql, 0002_publish_digest_check.sql, 0003_publish_max_preview_trigger_replace.sql, 0004_publish_refs_index.sql).
| Provider | API Key Env | Base URL Override |
|---|---|---|
gemini |
GEMINI_API_KEY |
— |
openai |
OPENAI_API_KEY |
OPENAI_BASE_URL |
anthropic |
ANTHROPIC_API_KEY |
ANTHROPIC_BASE_URL |
deepseek |
DEEPSEEK_API_KEY |
--api-base only (no env var) |
kimi |
MOONSHOT_API_KEY |
MOONSHOT_BASE_URL |
zhipu |
ZHIPU_API_KEY |
ZHIPU_BASE_URL |
ollama |
— | OLLAMA_BASE_URL or --api-base |
LIBRA_STORAGE_TYPE, LIBRA_STORAGE_BUCKET, LIBRA_STORAGE_ENDPOINT, LIBRA_STORAGE_REGION, LIBRA_STORAGE_ACCESS_KEY, LIBRA_STORAGE_SECRET_KEY, LIBRA_STORAGE_THRESHOLD, LIBRA_STORAGE_CACHE_SIZE, LIBRA_STORAGE_ALLOW_HTTP (set to "true" to permit non-TLS HTTP endpoints, useful for local/dev S3-compatible stores). Inspect the resolved tier/threshold/cache-budget with libra cache info (--json)
LIBRA_D1_ACCOUNT_ID, LIBRA_D1_API_TOKEN, LIBRA_D1_DATABASE_ID
LIBRA_SKIP_WEB_BUILD=1— skip the Next.js web build inbuild.rs(set by every CI job exceptcompat-web-check)LIBRA_LOG,RUST_LOG—tracing-subscriberenv filterLIBRA_LOG_FILE— tracing sink path (append-mode by default; time-rolled whenLIBRA_LOG_ROTATIONis set)LIBRA_LOG_ROTATION— rolling strategy forLIBRA_LOG_FILE:never(default) /minutely/hourly/daily(tracing-appender, time-split only — no old-file pruning); inspect vialibra logfile infoLIBRA_SYNC_DATA— set to1/true/yes/onto fsync local object writes for power-loss durability (same as the global--sync-dataflag)LIBRA_READ_POLICY— tiered-storage object read source:auto(default, local-first then remote) /offline/local(local-only) /remote(refresh from durable tier). An unrecognized value is a hard error (a typo must not silently re-enable remote reads). The global--offlineflag overrides this to local-only. No-op for local-only reposLIBRA_MAX_CONNECTIONS— max concurrent remote connections/requests (positive integer; default 16), bounding remote fan-out (e.g.exist_batch) on large repos/CI. The global--max-connectionsflag overrides it; an invalid value is a hard error. No-op for local-only operationsLIBRA_PAGER— pager override (falls back to systemPAGERthenless)LIBRA_NO_HIDE_PASSWORD— show password prompts in plain text (debugging)LIBRA_CONFIG_GLOBAL_DB— override the global config SQLite pathLIBRA_COMMITTER_NAME/LIBRA_COMMITTER_EMAIL— committer identity overridesLIBRA_SSH_COMMAND,LIBRA_SSH_STRICT_HOST_KEY_CHECKING— SSH protocol tuningLIBRA_CODE_LEASE_DURATION_MS—libra codeautomation lease lengthLIBRA_SANDBOX_ENFORCEMENT,LIBRA_SANDBOX_NETWORK_DISABLED,LIBRA_LINUX_SANDBOX_EXE,LIBRA_USE_LINUX_SANDBOX_BWRAP— sandbox toggles (docs/development/commands/sandbox.md)LIBRA_ERROR_JSON,LIBRA_FINE_EXIT_CODES— stable-error-code surface togglesOTEL_EXPORTER_OTLP_TRACES_ENDPOINT/OTEL_EXPORTER_OTLP_ENDPOINT,OTEL_SDK_DISABLED— OTLP telemetry gate (only with--features otlp; no default endpoint — unset means nothing is exported)
The following are baked-in constants (no env-var override) — listed here so contributors do not waste time trying to set them at runtime:
LIBRA_VCS_TIMEOUT_SECONDS(src/internal/ai/mcp/resource.rs:86) — MCP-side AI-VCS tool timeout, currently fixed at 120 s.LIBRA_VCS_DEFAULT_APPROVAL_SCOPE(src/internal/ai/sources/mcp.rs:28) — default approval scope forrun_libra_vcs, currentlyinteractive.LIBRA_ISSUES_URL(src/utils/error.rs:59) — canonical GitHub issues URL appended to internal-invariant error hints.
LIBRA_TEST_GITHUB_TOKEN,LIBRA_TEST_GITHUB_NAMESPACE— L2 GitHub gate (creates/deletes a temporarylibra-test-*repo)LIBRA_TEST_S3_ENDPOINT,LIBRA_TEST_S3_BUCKET,LIBRA_TEST_S3_ACCESS_KEY,LIBRA_TEST_S3_SECRET_KEY,LIBRA_TEST_S3_REGION,LIBRA_TEST_S3_ALLOW_HTTP— L3 S3 protocol gate (separate from the R2 backup credentials above)LIBRA_PUBLISH_LIVE_WORKER_ORIGIN,LIBRA_PUBLISH_LIVE_CLONE_DOMAIN,LIBRA_PUBLISH_LIVE_SLUG,LIBRA_PUBLISH_LIVE_FILE_PATH—publish_livedeploy-smoke gateLIBRA_TEST_MEGA_SERVER— LFS protocol live-server gateLIBRA_ENABLE_TEST_PROVIDER— activate thetest-providerdeterministic LLM for TUI scenarios (required alongside--features test-provider)LIBRA_TEST_LOG,LIBRA_TEST_HOME,LIBRA_TEST_ENV— test-only logging/home/sentinel overrides