Skip to main content

git-strata

Use when working in a repo managed by git-strata (macOS), or when the user asks you to start, checkpoint, diff, restore, publish or remove a git-strata session. Gives each agent session its own isolated APFS-cloned workspace over a shared base snapshot; covers the CLI workflow, the JSON envelope, error codes, and the commands an agent must hand to a human.

Quellinformationen

Repository
dickwu/git-strata
Letzte Quellaktivität
30. Oktober 2026 um 19:59
Erkannte Sprache von SKILL.md
Englisch
Sterne
0
Forks
0

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
2 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
git-strata
description
Use when working in a repo managed by git-strata (macOS), or when the user asks you to start, checkpoint, diff, restore, publish or remove a git-strata session. Gives each agent session its own isolated APFS-cloned workspace over a shared base snapshot; covers the CLI workflow, the JSON envelope, error codes, and the commands an agent must hand to a human.
# git-strata git-strata gives every coding session its own workspace: an APFS clone of a shared, sealed base snapshot of each repo (plus its dependency set). One session's edits never change another session's files, but they are readable: `status --all`, `grep`/`files` with `--session S` or `--all`, and `diff --session S` / `--between` show other sessions' content. Edits are recorded as checkpoints, combined and committed by `publish`, and sent to the remote only by `git-strata push` or a publish that is configured to push. macOS only (APFS, FSEvents, launchd). Use it when the user (or the repo's setup) works in git-strata sessions, when several agents edit the same repos in parallel, or when you are asked to checkpoint / restore / publish. `git strata ...` and `git-strata ...` are the same binary. Full command and flag table: [reference.md](reference.md). ## Prerequisites - `git-strata` is on `PATH`. The config lives in `~/Library/Application Support/git-strata/config.toml`; the daemon socket is `~/Library/Application Support/git-strata/daemon.sock`, the pinned safety flags `~/Library/Application Support/git-strata/pins.json` (no env var or flag changes them; only `$HOME` does). Workspaces live under the data root (`[paths] root`, default `~/.strata`) as `<root>/sessions/<session-id>/<repo>/`. - The daemon reads `config.toml` only at start; after a config change, tell the human the daemon needs a restart. Do not restart it yourself. - **Agents never start, stop or restart the daemon** (`git-strata daemon start` / `stop` are human-only; never run them, or `launchctl`, yourself, not even with a temp `HOME`: the LaunchAgent domain is per user, not per HOME). Check it with `git-strata daemon status` (`data.running`). If it is down, keep working in the workspace and tell the human it is down so they can run `git-strata daemon start`. While it is down the hook answers `Busy` `daemon_down` and that checkpoint is not recorded: tell the human which edits were not checkpointed. Do not write a plist yourself. - Without the daemon, only these work (read-only, straight from the store): `status`, `grep`, `files`, `diff`, `deps list`, `daemon status`, and a repeated `checkpoint --tool-call ID` whose checkpoint already exists. Every other command returns `Busy` with `detail.reason = "daemon_down"`. ## Workflow ```sh # 1. New session (ticket is just a label). Name the repos you will touch with # --repo (repeatable): only those get a workspace, all tracked. This is the # fast form; use it. A repo that links a sibling by relative path (../x) # needs that sibling too: pass it, or add it later (step 1b). # (Without --repo, `--repos A,B` gives EVERY configured repo a workspace # and tracks only A,B; do not edit the untracked siblings.) git-strata new PROJ-123 --repo tool --repo core-lib # data.manifest.id -> session id, e.g. "s-k3q7xm2a" # data.manifest.repos.<repo>.path -> that repo's workspace directory # data.warnings -> [] when fine # data.manifest.agent -> the agent recorded for this session # The session records which AI agent created it. Claude Code, Codex and # Cursor are detected from their environment. Any other agent: run # `export STRATA_AGENT=<name>` (e.g. aider; 1-64 of [A-Za-z0-9._-], # starting with a letter or digit) before `new`, or pass --agent <name>. # A warning of kind AgentNotRecorded means the running daemon is older # than this CLI; the session is fine, only the agent is not recorded. # 1b. Need another repo later? Add it to the same session (tracked): git-strata add --repo front # or: --session S --repo front # data.added.<repo>.path; data.already lists repos it had already. # 2. Work inside the workspace. Commands without --session use the cwd. cd "<data.manifest.repos.tool.path>" # ... edit files normally ... # 3. Checkpoint (one of --tool-call / -m, never both) git-strata checkpoint -m "parse config before connect" git-strata checkpoint -m "only these" --path src/a.ts --path ../core-lib/x.php # 4. Inspect git-strata status # this session; --all for every session git-strata diff # this session vs its pinned base (= --base) git-strata diff --between s-aaaa1111 s-bbbb2222 --repo tool # two sessions git-strata grep 'TODO' # this session; --session S or --all git-strata files 'src/**/*.ts' # glob optional # 5. Undo to a checkpoint (all paths, or only the listed ones) git-strata restore 42 git-strata restore 42 src/a.ts # 6. Publish checkpointed content into a commit git-strata publish --from s-k3q7xm2a:src/a.ts --from s-k3q7xm2a:src/b.ts # 7. Push the publish chain (only if the human asked; may need a TTY) git-strata push tool # 8. Remove the session once its work is published git-strata rm --session s-k3q7xm2a ``` Notes: - `--session` takes a session id or a ticket. A ticket shared by several sessions gives `AmbiguousMatch`; use an id from `detail`. `--session` and `--all` together is `InvalidInput` (`both_selectors`). - `checkpoint` may record more than one repo of the session: every path is mapped to the session repo whose workspace contains it; paths outside the session are skipped. With no paths, every tracked repo of the session is scanned. `data.checkpoints` has one row per repo recorded. - `-m` records a new checkpoint only when something changed since the latest one; with no change it returns that latest checkpoint (its id and message, not yours). `--tool-call ID` is idempotent per (session, repo, ID): every new ID records a row (even with no change), and repeating it returns the same rows. - `publish` publishes the selected paths' current content: before sending the publish it records a fresh `BeforePublish` checkpoint of each `--from` batch, so edits made to a selected file up to that moment are included. There is no option to publish an older checkpoint; to keep an edit out, revert it (or `restore` the path) before publishing. Without `--from` it is interactive on a TTY and `InvalidInput` (`no_batch`) otherwise, so agents always pass `--from SESSION:PATH`. PATH is relative to the repo root with no repo prefix (`billing-api/app/x.php` is `--from "${S}:app/x.php"`). Write `"${S}:path"`, never `"$S:path"`: zsh reads `$S:t`, `$S:h`, ... as modifiers. Path mistakes come back before any TTY check: `InvalidInput` `from_repo_prefix` (rerun with `error.detail.expected`), `InvalidInput` `from_path` (no workspace has it), `AmbiguousMatch` `from_repo` (several have it and not exactly one of their checkpoints changed it; rerun with one of `detail.expected`). To pick the repo yourself use `--from "${S}:REPO:PATH"` (e.g. `"${S}:admin:src/a.ts"`); the middle part is REPO only when it is one of the session's repos. - `publish` replies only after checks, commit, push and the rebase of every session. `git push` waits for the remote's own hooks (bounded at 120 s, then `Unknown` `push_unknown`), the rebase is unbounded: a minute or two of silence after the remote branch moved is normal. Wait; do not interrupt or rerun. - Release builds never run in a workspace (no remotes, detached `HEAD`, push guard). Publish (and push), then in the main checkout `git pull --ff-only`, check `HEAD` equals `data.commits.<repo>`, and run the build there; the build script is the human's step unless they asked you to run it. See README "Release builds from a session". - Multi-repo `publish` commits repo by repo. When one repo hits `Conflict`, repos before it have already committed (and pushed, if push is on); the call does not roll them back. See "Publish conflict: fix and re-run" below. - `diff` and `diff --between` preview current workspace content, checkpointed or not. Identical files are not listed; binary / >64 MiB entries carry `code: "Binary"` / `"TooLarge"` instead of a preview and the call stays ok. - `grep` with no hits is `ok` with `"hits": []` (not an error). Skipped binary or oversized files are listed in `data.skipped`. - `deps propose [--session S] [--repo R]` proposes a new dependency set after you change install inputs; `deps list` shows open proposals. Add `--switch` to move your own session onto the proposed set right away (no prompt; other sessions stay pinned). Check `data.switched.kind`: `skipped` with `code: OpenFiles` means a process holds files in your deps dir; stop it (only if you started it) and run again. Approving for other sessions is human-only (below). `data.pending_proposals: [{id, repo}]` in any envelope means a proposal waits for the human. - If you change install inputs (package.json deps, bun.lock, patches, pubspec.yaml / pubspec.lock, ...) and publish without switching, publish still runs the checks with deps that match the staged inputs: it uses a sealed set (warning `DepsSubstituted`) or installs one first (slower; warning `DepsReinstalled`, and the history shows an extra row stopped with `Drift`). Plain drift does not refuse the publish; it can still stop with `Drift` when the inputs move again during that install (`deps_drift`) or when the deps dirs overlap files you publish (`deps_select_failed`, `tracked_overlap`: follow its `fix`/`hint`). Still run the warning's `fix` (`deps propose --switch`) so your workspace matches. `status` shows the same `drift.fix`. If that install fails (`detail.stage: "deps_install"`), hand it to the human with `detail.log_tail`; do not retry in a loop (a retry returns `previous_attempt`). ## Publish conflict: fix and re-run This is the expected loop for agents; the human is not needed unless the conflict is `assigned`. 1. `publish` returns `ok: false`, `error.code = "Conflict"`. - `error.detail.repo` is the repo that conflicted; nothing was committed there. - `error.detail.conflicts` lists its paths (with the hunks). - `data.commits` / `data.pushes` hold repos that already landed in this call (also in `error.detail.published_before`). They stay landed. The same holds for any publish error: a repo whose commit was written before its push timed out (`Unknown`) or was refused (`PushRefused`) is in `data.commits` and `data.pushes` too. 2. Fix the listed paths in that repo's workspace (merge in the upstream change; `git-strata diff` helps). 3. Optionally `git-strata checkpoint -m "resolve conflict" --path P ...` to keep a named point; the re-run snapshots the paths itself. 4. Re-run the exact same `publish --from ...` command. Repos that already landed are not committed again: they appear in `data.already_published` as `{repo, publish, commit, push}`, and only the rest is published (`data.commits`). The check is per `--from` path and by content: a path (or directory) whose content is exactly what landed is skipped; anything new or changed under it since (including new files in a directory you selected) is published as a new commit, and the unchanged paths of the same `--from` list do not cause `NoMatch`. 5. Repeat while another repo conflicts. ## Dev servers and `tauri dev`: per-session ports Every session workspace gets its own block of 4 ports (a lease), so two sessions can run `tauri dev` (or any dev server) at the same time. The main checkout has no lease and keeps the project's default ports. Never change ports by editing committed files (`tauri.conf.json`, `package.json`, `next.config.*`, `.env`); start the server through git-strata instead: ```bash cd <your workspace> # data.manifest.repos.<repo>.path git-strata session ports # read the lease: data.leases[0].ports / .env git-strata session exec -- bun run dev # any server that reads $PORT (Next.js does) git-strata session exec -- sh -c 'vite --port "$PORT" --strictPort' git-strata session exec --tauri -- bun run tauri dev ``` - `exec` runs the command in place of itself (its output, its exit code) in exactly one workspace (`--repo R` when the session has several) with: `PORT` = `STRATA_DEV_PORT` (web), `STRATA_CONNECTOR_PORT`, `STRATA_CONNECTOR_MCP_PORT`, `STRATA_AUX_PORT`, `STRATA_SESSION`, `STRATA_REPO`, `TAURI_CONNECTOR_PROJECT` (the Tauri app dir) and `STRATA_TAURI_DEV_CONFIG`. Child processes (e.g. Tauri's `beforeDevCommand`) inherit them. - `--tauri` adds `--config $STRATA_TAURI_DEV_CONFIG` to `tauri dev`, which points `build.devUrl` at `http://localhost:$PORT`. The frontend dev server must then listen on `$PORT`. It understands `tauri dev`, `cargo tauri dev`, `npx|bunx|pnpx tauri dev`, `pnpm exec tauri dev`, and `bun|pnpm|yarn|npm run <script>` when that script is literally `tauri dev ...` (or the bare `tauri` CLI, with `dev` right after the script name: `bun run tauri dev`, `npm run tauri -- dev`). Always write `run`: `bun <script>` without it is refused, since the package manager may run its own command of that name. Options that pick another package (`--prefix`, `--filter`, `-w`, `--workspace`, `--cwd`, ...) and, for npm, any option before its `--` are refused. Anything else is `InvalidInput` `tauri_launcher`; use the form in `detail.fix`: `git-strata session exec -- sh -c 'tauri dev --config "$STRATA_TAURI_DEV_CONFIG"'`. - `exec` does not set tauri-connector's variables. tauri-connector 0.17.7+ binds exactly `TAURI_CONNECTOR_PORT`, `TAURI_CONNECTOR_MCP_PORT` and `TAURI_CONNECTOR_BRIDGE_PORT`; map the lease onto them: `git-strata session exec -- sh -c 'TAURI_CONNECTOR_PORT=$STRATA_CONNECTOR_PORT TAURI_CONNECTOR_MCP_PORT=$STRATA_CONNECTOR_MCP_PORT TAURI_CONNECTOR_BRIDGE_PORT=$STRATA_AUX_PORT exec tauri dev --config "$STRATA_TAURI_DEV_CONFIG"'`. Precedence: a port in the app's builder code > the exact env variable > `TAURI_CONNECTOR_*_PORT_RANGE` > a builder range > the default. A busy exact port is not replaced: the connector does not start (the app keeps running); free the port or `--reassign`, then restart. The bound ports are in the `.connector.json` under your workspace's `target/` (copies from the main checkout are removed when the session is created). - `exec`'s variables reach only the command it starts and its children, not a later connector command or an MCP server that is already running. When you talk to the app from such a client, select it explicitly: `tauri-connector ... --project <tauri_app_root>` (`tauri_app_root`, else `path`, from `git-strata session ports`), or wrap the client: `git-strata session exec --no-check -- sh -c 'TAURI_CONNECTOR_PORT=$STRATA_CONNECTOR_PORT tauri-connector ...'` (without `--port` the CLI uses `TAURI_CONNECTOR_PORT`). Never connect to the connector's default ports (9555/9556): they may be another session's app. - Before starting, `exec` checks the lease's ports (`--no-check` skips it; `session ports --check` only reports): - `PortInUse` `already_running`: a process of this workspace already listens. Reuse it; stop it only if you started it. - `PortInUse` `foreign`: something else holds a port. Nothing moves on its own: run `detail.fix` (`git-strata session ports --reassign --session S --repo R`) for your own session, then `exec` again. Never kill a process you did not start. - `Busy` `port_unidentified` / `port_probe_error`: retry shortly. - A workspace without a lease yet (e.g. one created before this feature) gets one from the daemon on first `ports` / `exec`; an existing lease works without the daemon. `Busy` `daemon_down` from `ports` / `exec`: report it to the human; do not start the daemon yourself. `Busy` `ports_exhausted` (`ports` shows the workspace with `"ports": null`): no free block; tell the
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen