Skip to content

Commit bcd740a

Browse files
Fold the remaining docs into the README and CONTRIBUTING
docs/mcp.md and docs/embed.md become the README's AI agents and Embed a graph in a web page sections, with the reference tables in collapsed blocks, and pre-flight's checks and text graph move under Pre-flight. docs/testing.md and the build and publishing notes from docs/vscode.md move into CONTRIBUTING.md. docs/ now holds only the README's images. Signed-off-by: Jacob Stopak <jacob@initialcommit.io>
1 parent e05b233 commit bcd740a

9 files changed

Lines changed: 198 additions & 506 deletions

File tree

‎.gitignore‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ git_sim.egg-info/
1616
vscode/*.vsix
1717
vscode/LICENSE.txt
1818

19-
# the sanity run's clones, results and logs (docs/testing.md)
19+
# the sanity run's clones, results and logs (CONTRIBUTING.md)
2020
tests/sanity/.work/

‎CONTRIBUTING.md‎

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,23 +55,48 @@ $ git-sim merge dev
5555
- `src/git_sim/live.py`, `preflight.py`, `mcp_server.py`, `claude_hook.py`: live mode, pre-flight, the MCP server, and the agent hook
5656
- `vscode/`: the VS Code extension
5757
- `integrations/`: the GitHub CLI extension (`gh sim`) and the GitHub Action
58-
- `docs/`: guides for live mode, pre-flight and agents, embedding, integrations, and testing
58+
- `docs/img/`: the README's images
5959
- `scripts/`: the scripts that draw the README's graphs
6060

6161
## Running the tests
6262

63-
Three suites, each answering a different question. [docs/testing.md](docs/testing.md) explains them in detail.
64-
6563
```console
6664
$ pytest tests/unit_tests # the pieces, in isolation
67-
$ pytest tests/validation # every command and option, checked against what git does
65+
$ pytest tests/validation # every command and option, checked against what Git does
6866
$ pytest tests/e2e_tests # the raster images, pixel by pixel
6967
```
7068

69+
GitHub Actions runs the unit tests on Linux, macOS, and Windows with every supported Python version on each push.
70+
7171
- **Clear your own settings first.** Any `git_sim_*` environment variables you've set (a dark theme, an image format) change what git-sim draws, so unset them before running the suites.
72-
- **The e2e suite** needs `VIRTUAL_ENV` set to your virtual environment's absolute path.
73-
- **The validation suite** compares what git-sim draws with golden models in `tests/validation/golden/`. When you change what a command draws on purpose, review the diff, then accept it with `pytest tests/validation --update-golden`.
74-
- **New options need a case.** A new command or option needs a case in `tests/validation/cases.py`, and `test_coverage.py` fails until it has one.
72+
- **The e2e suite** needs `VIRTUAL_ENV` set to your virtual environment's absolute path. Its reference images use a bundled font so they match across systems.
73+
- **The validation suite** builds repo shapes with git-dummy, runs git-sim as a real subprocess, reads the SVG back into a model of what was drawn, and checks it against Git (`oracle.py`), against a golden model in `tests/validation/golden/`, and for clean failures. When you change what a command draws on purpose, review the diff, then accept it with `pytest tests/validation --update-golden`. It's almost 400 renders, so `pip install pytest-xdist` and `pytest -n auto` help, and `-m "not slow"` skips the large repo shape.
74+
- **New options need a case.** A new command or option needs a one-line case in `tests/validation/cases.py`, and `test_coverage.py` fails until it has one.
75+
- **The MCP server** can be checked against one of your repos with `python scripts/mcp_smoke_test.py /path/to/repo`.
76+
77+
### The sanity run
78+
79+
Before each release, `tests/sanity/sanity.py` runs git-sim the way a user would on six open-source repos, up to git/git, and compares every simulation with what Git actually does. It isn't collected by pytest and takes about half an hour:
80+
81+
```console
82+
$ python tests/sanity/sanity.py clone # once: about 400 MB, most of it git/git
83+
$ python tests/sanity/sanity.py run # all six repos, three at a time
84+
$ python tests/sanity/sanity.py run flask --scenario "merge: conflict"
85+
$ python tests/sanity/sanity.py list # the repos and scenario names
86+
```
87+
88+
`run` ends with a report of the scenarios that matched Git and every problem with the command that showed it, also saved to `tests/sanity/.work/report.md`. A problem is either in git-sim or in the scenario, so check the scenario's `check=` and `refuse=` in `sanity.py` first. A real git-sim bug usually deserves a validation case too, so it stays fixed.
89+
90+
## The VS Code extension
91+
92+
The extension in `vscode/` is plain JavaScript that runs the `git-sim` command line tool, so there's nothing to compile. Open `vscode/` in VS Code and press F5 to try changes. To package it without Node:
93+
94+
```console
95+
$ python vscode/build_vsix.py
96+
$ code --install-extension vscode/git-sim-0.4.0.vsix
97+
```
98+
99+
The same `.vsix` is published to the Visual Studio Marketplace (`initialcommit` publisher, at marketplace.visualstudio.com/manage or with `vsce publish`) and to Open VSX for Cursor, Windsurf, and VSCodium (`npx ovsx publish -p <token>`). Both show `vscode/README.md` as the extension's page, so images in it need absolute links.
75100

76101
## Code style
77102

‎README.md‎

Lines changed: 162 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ It names, animates, and tracks every change to your Git repo, so you can step ba
125125

126126
By default, the page opens in the git-sim viewer on initialcommit.com which connects to a lightweight web server `git-sim live` runs on your machine, reachable only from `127.0.0.1` and with a session key. All Git data is compressed and stored in the URL #fragment, so nothing about your repo leaves your machine, and `--open-in local` serves the page from git-sim itself instead if you prefer not to invoke initialcommit.com's git-sim viewer and run purely local.
127127

128-
**Runs inside VS Code:** the VS code extension shows the same live graph in its **Live graph** tab and sidebar view (see [docs/vscode.md](https://github.com/initialcommit-com/git-sim/blob/main/docs/vscode.md)).
128+
**Runs inside VS Code:** the VS code extension shows the same live graph in its **Live graph** tab and sidebar view (see the [extension's page](https://github.com/initialcommit-com/git-sim/tree/main/vscode)).
129129

130130
**How it watches your repo:** live mode reads what Git reports between checks, rather than watching `.git`, and waits for the repo to settle, so a rebase or a pull shows as one change. It names each change from the reflog when it can (`git commit`, `git reset <commit>`, `git switch -c <branch>`), and otherwise from what changed (a branch created, a file staged, a stash popped). Chrome and Edge ask once for permission to reach the local server. If a browser refuses, the page offers the local version.
131131

@@ -148,13 +148,171 @@ Set `GIT_SIM_LIVE_DEBUG=1` to log each detected change.
148148
$ git-sim preflight reset --hard HEAD~2
149149
```
150150

151-
[![git-sim preflight reporting what a hard reset would lose](https://raw.githubusercontent.com/initialcommit-com/git-sim/main/docs/img/preflight.png)](https://github.com/initialcommit-com/git-sim/blob/main/docs/mcp.md)
151+
[![git-sim preflight reporting what a hard reset would lose](https://raw.githubusercontent.com/initialcommit-com/git-sim/main/docs/img/preflight.png)](https://github.com/initialcommit-com/git-sim#ai-agents)
152152

153153
git-sim's pre-flight mode shows a deterministic evaluation of whether any Git command is safe or potentially destructive to your repo, including how risky it is, which commits might become unreachable, which changes would be lost for good, and the command that undoes it, all without impacting your repo.
154154

155155
This can be wired into AI agents to bring yourself (the human) into the loop to approve/deny Git commands that could be destructive. Run `git-sim wire-agents` to set up the automatic git-sim pre-flight for AI agents.
156156

157-
The `--markdown` flag formats the report for a pull request comment, and the VS Code extension shows it in an editor tab.
157+
Git's own options pass straight through, and quoting the whole command works too (`git-sim preflight "git stash drop"`). `-C <path>` checks another repo, `--json` prints the report as JSON, and `--markdown` formats it for a pull request comment. The VS Code extension shows it in an editor tab.
158+
159+
<details>
160+
<summary>What pre-flight checks</summary>
161+
162+
- `reset`: the commits left behind and the uncommitted changes thrown away
163+
- `clean`: the exact files it would delete (from `git clean -n`)
164+
- `rebase`: the commits it replays, and whether any were already pushed
165+
- `merge`: whether it fast-forwards, and whether it would conflict (from `git merge-tree`)
166+
- `push`: whether a force-push would overwrite commits on the remote, and branches `push --delete` would remove
167+
- `branch -d` and `-D`: commits not merged anywhere else
168+
- `restore`, `checkout`, and `switch`: local changes they would throw away
169+
- `stash drop` and `stash clear`: the stashed changes lost, including stashes from branches checked out in other worktrees
170+
- `commit --amend`: whether the commit was already pushed
171+
- `worktree remove` and `prune`: uncommitted changes deleted with the worktree, and stale records
172+
- `rm`: uncommitted changes deleted with the file
173+
- `reflog expire` and `delete`, `gc --prune`, and `filter-branch`
174+
- `submodule deinit` and `update --force`: local changes inside the submodule
175+
- `--abort`, `--continue`, `--skip`, and `--quit` for merges, rebases, cherry-picks, and reverts in progress
176+
177+
Commands that only read, or only add (`add`, `mv`, `init`, `clone`, `cherry-pick`, `revert`), are `safe`. `pull` is `safe` unless it's `pull --rebase` with local commits, which is `caution`. Commands pre-flight doesn't know are `caution`.
178+
179+
When a repo has more than one worktree, as with agents running in parallel, every report says which worktree the command runs in and checks what it could reach in the others: shared stashes, branches checked out elsewhere, and branches built on commits a rebase replays.
180+
181+
</details>
182+
183+
<details>
184+
<summary>The text graph</summary>
185+
186+
Every report has a plain-text graph for places an image can't go, like a permission prompt, an SSH session, or CI logs. It's Git's own `log --graph` layout with a marker beside each commit the command affects, then the affected files:
187+
188+
```text
189+
* c362a60 (HEAD -> mcp-server) Add Claude Code PreToolUse hook for autom... <- ABANDONED
190+
* d31d48b Add MCP server with deterministic git pre-flight engine <- ABANDONED
191+
* ccd3d99 (tag: v0.3.5, main) Bump version to 0.3.5 <- NEW HEAD
192+
* 4f7c57e Update logo entry in manifest
193+
... 212 earlier commit(s) not shown
194+
195+
Working tree:
196+
modified README.md <- DISCARDED (not recoverable)
197+
```
198+
199+
The markers are `ABANDONED` and `NEW HEAD` (reset), `REPLAYED (new hash)` and `NEW BASE` (rebase), `INCOMING` (merge), `PUSHED` and `OVERWRITTEN (remote only)` (push), `ABANDONED (branch deleted)` (`branch -D`), `REPLACED (new hash)` (`commit --amend`), and `SWITCH TARGET` (checkout and switch).
200+
201+
</details>
202+
203+
## AI agents
204+
205+
AI coding agents run Git commands for you. git-sim shows you what a risky one will do before it runs, worked out from your actual repo rather than guessed by the model, in two ways:
206+
207+
- **The pre-flight hook** stops the agent before a risky Git command and asks you to approve it, with the facts in front of you and the simulation open. The agent can't skip it.
208+
- **The MCP server** gives the agent two tools it can call itself: `git_preflight(command, repo_path)` to check a command, and `git_simulate(command, repo_path)` to draw one (`interactive=true` for the interactive page). Neither ever changes your repo.
209+
210+
To set up both in every agent on your machine, run:
211+
212+
```console
213+
$ git-sim wire-agents
214+
```
215+
216+
Then restart any agents that are running. It sets up the hook and the MCP server in Claude Code, Codex CLI, Cursor, GitHub Copilot CLI, Gemini CLI, and VS Code (Copilot), and the MCP server only in Windsurf, Cline, Roo Code, Amazon Q Developer CLI, and Claude Desktop, which have no hooks.
217+
218+
`--agent claude --agent cursor` sets up only those agents, `--scope project` writes to the current repo instead of your home folder, `--no-hook` or `--no-mcp` skips one, and `--dry-run` shows what would change. Running it again updates git-sim's entries, and `git-sim unwire-agents` removes exactly what it added.
219+
220+
Here's what a Claude Code prompt looks like:
221+
222+
```
223+
git-sim preflight: DESTRUCTIVE git reset -q --hard HEAD~2
224+
Moves main from e35b0b7 to cb54632 (hard reset).
225+
Loses: 2 commits removed from branch main; unstaged changes in README.md (NOT recoverable)
226+
Undo: Commits stay in the reflog ~90 days: git reset --hard e35b0b7
227+
```
228+
229+
Claude Code, Cursor, and Copilot ask you directly. Codex and Gemini hooks can only allow or deny, so the hook denies the command and tells the agent to show you the facts and, if you approve, rerun it starting with `GIT_SIM_APPROVE=1`. Safe commands and anything that isn't Git go straight through, and if the hook hits an error of its own, it lets the command through rather than blocking your agent.
230+
231+
<details>
232+
<summary>Hook settings</summary>
233+
234+
Set these as environment variables:
235+
236+
| Variable | Default | What it does |
237+
|---|---|---|
238+
| `GIT_SIM_HOOK_ASK_ON` | `caution` | The lowest risk that stops the agent: `caution` or `destructive` |
239+
| `GIT_SIM_HOOK_MODE` | `ask` | `ask` prompts you, `deny` denies risky commands outright (for unattended runs), `warn` lets them run with the facts attached |
240+
| `GIT_SIM_HOOK_RENDER` | `1` | `0` skips drawing the simulation, for just the facts |
241+
| `GIT_SIM_HOOK_OPEN` | `always` | `always` opens the simulation, `never` doesn't, `ask` asks first in a small system dialog |
242+
| `GIT_SIM_HOOK_OPEN_IN` | `hosted` | `local` opens the saved `.html` file instead of the git-sim viewer |
243+
| `GIT_SIM_HOOK_TEXT` | `0` | `1` adds the text commit graph to the prompt |
244+
| `GIT_SIM_HOOK_REPORT_SAFE` | `1` in VS Code, `0` elsewhere | `1` adds a one-line SAFE or CAUTION note to Git commands that don't stop the agent |
245+
| `GIT_SIM_HOOK_AGENT` | detected | Which agent's hook format to answer in (`claude`, `codex`, `cursor`, `copilot`, `gemini`) |
246+
| `GIT_SIM_APPROVE` | | Set on a single command to let it through after you've approved it (Codex and Gemini) |
247+
248+
</details>
249+
250+
<details>
251+
<summary>Setting up by hand</summary>
252+
253+
The hook in Claude Code, in `.claude/settings.json` or `~/.claude/settings.json`:
254+
255+
```json
256+
{
257+
"hooks": {
258+
"PreToolUse": [
259+
{
260+
"matcher": "Bash|PowerShell",
261+
"hooks": [{ "type": "command", "command": "git-sim-hook", "timeout": 120 }]
262+
}
263+
]
264+
}
265+
}
266+
```
267+
268+
The MCP server in Claude Code:
269+
270+
```console
271+
$ claude mcp add git-sim -- git-sim-mcp
272+
```
273+
274+
Or in any client that supports stdio servers:
275+
276+
```json
277+
{ "mcpServers": { "git-sim": { "command": "git-sim-mcp" } } }
278+
```
279+
280+
</details>
281+
282+
## Embed a graph in a web page
283+
284+
Put a git-sim graph in any blog post, tutorial, or docs page, with the full interactive viewer. Save the graph as an SVG (or use **Download SVG** in any git-sim page's Share menu):
285+
286+
```console
287+
$ git-sim --img-format svg rebase main
288+
```
289+
290+
Copy it next to your page, then add:
291+
292+
```html
293+
<div class="git-sim" data-src="/img/rebase-main.svg" data-title="git rebase main">
294+
<a href="https://initialcommit.com/tools/git-sim">git rebase main, created with git-sim</a>
295+
</div>
296+
<script src="https://initialcommit.com/js/tools/git-sim-embed.js" defer></script>
297+
```
298+
299+
The script turns every element with the `git-sim` class into the viewer, each in its own frame so they never clash with your page or each other. The link becomes a credit under the graph, and is what readers see if the script can't run.
300+
301+
<details>
302+
<summary>Embed attributes</summary>
303+
304+
| Attribute | What it does |
305+
| --- | --- |
306+
| `data-src` | The SVG (or saved git-sim page) to show, on the same site as your page or a host that allows cross-origin requests |
307+
| `data-title` | The command, used in the share text and the frame's title |
308+
| `data-state` | `before`, `after`, or `step=N` holds the graph at that point. Without it, the graph plays on a loop |
309+
| `data-theme` | `dark` or `light`. By default it follows the reader's setting |
310+
| `data-controls` | `full` (the default) or `compact`, which keeps just the slider and Share |
311+
| `data-height` | A fixed height, like `480px`. By default the embed fits the graph |
312+
313+
Style `.git-sim-credit` to change the credit's look. If your page adds content after it loads, call `GitSimEmbed.scan(element)` to set up new graphs inside it.
314+
315+
</details>
158316

159317
## Supported Git commands
160318

@@ -686,7 +844,7 @@ Every option can also be set with an environment variable named `git_sim_` plus
686844

687845
The `[global options]` apply to the overarching `git-sim` simulation itself, including:
688846

689-
`--img-format`: Output format, i.e. `html` (default: the interactive page), `jpg`, `png`, or `svg` (the graph alone, for [embedding in a page](https://github.com/initialcommit-com/git-sim/blob/main/docs/embed.md)). Set `git_sim_img_format=jpg` in your environment to make an image the default.
847+
`--img-format`: Output format, i.e. `html` (default: the interactive page), `jpg`, `png`, or `svg` (the graph alone, for [embedding in a page](https://github.com/initialcommit-com/git-sim#embed-a-graph-in-a-web-page)). Set `git_sim_img_format=jpg` in your environment to make an image the default.
690848
`--open-in`: Where the interactive page opens: `hosted` (default) shows it in the git-sim viewer at initialcommit.com, `local` opens the saved `.html` file. The page is saved locally either way, and the hosted page says where. Set `git_sim_open_in=local` to make local the default.
691849
`--reverse, -r` / `--no-reverse`: By default the newest commit is on the left and arrows point right toward parents, so history reads left to right. `--no-reverse` puts the newest commit on the right with arrows pointing left, the original layout.
692850
`-n <number>`: Number of commits to display from each branch head.

0 commit comments

Comments
 (0)