Files
claude-code/rust/crates/tools/GIT_TOOLS_README.md
TheArchitectit 0975252976 feat: git-aware context tools
Adds git-aware context tools for improved repository understanding.
2026-05-25 11:24:37 +09:00

158 lines
5.2 KiB
Markdown

# Git-Aware Context Tools
Adds five native git tools to claw-code that provide structured, read-only access to repository state. These replace ad-hoc `git` commands via bash with purpose-built tool definitions the model can discover and invoke directly.
## Tools
### GitStatus
Show the working tree status (branch, staged, unstaged, untracked). Equivalent to `git status --short --branch`.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `short` | boolean | no | `true` | Use `--short --branch` format for concise output |
**Example input:**
```json
{}
```
**Example output:**
```json
{
"output": "## feat/git-aware-tools...upstream/main [ahead 1]\nM rust/crates/tools/src/lib.rs"
}
```
---
### GitDiff
Show changes between commits, the index, and the working tree. Supports staged changes, specific paths, commit ranges, and comparing two commits.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `staged` | boolean | no | `false` | Show staged changes (`git diff --cached`) |
| `commit` | string | no | — | Commit hash, tag, or branch to diff against |
| `commit2` | string | no | — | Second commit for range diff (`commit...commit2`) |
| `path` | string | no | — | File path to restrict the diff to |
**Example inputs:**
```json
{}
```
```json
{ "staged": true }
```
```json
{ "commit": "HEAD~3", "path": "rust/crates/tools/src/lib.rs" }
```
```json
{ "commit": "main", "commit2": "feat/git-aware-tools" }
```
---
### GitLog
Show commit history. Supports limiting count, filtering by author/date/path, and oneline format.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `count` | integer | no | `20` | Maximum number of commits to return |
| `oneline` | boolean | no | `false` | Use `--oneline` format (hash + subject only) |
| `author` | string | no | — | Filter commits by author pattern |
| `since` | string | no | — | Filter commits since date (e.g. `"2024-01-01"` or `"2.weeks"`) |
| `until` | string | no | — | Filter commits until date |
| `path` | string | no | — | File or directory path to filter commits by |
**Example inputs:**
```json
{ "count": 5, "oneline": true }
```
```json
{ "author": "alice", "since": "1.week", "path": "src/main.rs" }
```
---
### GitShow
Show a commit, tag, or tree object with its diff. Supports showing a specific file at a commit and stat-only mode.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `commit` | string | **yes** | — | Commit hash, tag, or branch ref to show |
| `path` | string | no | — | Show only this file at the given commit (`commit:path` syntax) |
| `stat` | boolean | no | `false` | Show diffstat summary instead of full diff |
**Example inputs:**
```json
{ "commit": "HEAD" }
```
```json
{ "commit": "abc1234", "stat": true }
```
```json
{ "commit": "main", "path": "src/lib.rs" }
```
---
### GitBlame
Show what revision and author last modified each line of a file. Supports line range filtering.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `path` | string | **yes** | — | File path to blame |
| `start_line` | integer | no | — | Start of line range (1-based) |
| `end_line` | integer | no | — | End of line range (1-based) |
**Example inputs:**
```json
{ "path": "src/main.rs" }
```
```json
{ "path": "src/main.rs", "start_line": 100, "end_line": 150 }
```
---
## Architecture
All five tools follow the same pattern:
1. **ToolSpec** — Defines the tool name, description, JSON input schema, and `PermissionMode::ReadOnly`
2. **Input struct** — Derives `Deserialize` with `#[serde(default)]` on optional fields
3. **Run function** — Builds git arguments, calls `git_stdout()`, wraps result in JSON via `to_pretty_json()`
4. **Dispatch** — Matched in `execute_tool_with_enforcer()` like all other tools
The existing `git_stdout(args: &[&str]) -> Option<String>` helper (at `tools/src/lib.rs`) handles running the `git` subprocess and returning trimmed stdout. Git tools simply construct the right arguments and delegate to this helper.
## Why native git tools?
Before this PR, the model had to use the `bash` tool for git operations, which has several drawbacks:
- **No structured output** — Bash returns raw text that the model must parse
- **Over-permissioned** — Bash requires `DangerFullAccess` even for read-only git commands
- **No discoverability** — The model can't search for git-capable tools via `ToolSearch`
- **Inconsistent** — Each invocation may use different flags or formatting
With native git tools:
- All five are `ReadOnly` — safe in restricted permission modes
- Structured JSON output — consistent, parseable results
- Discoverable via `ToolSearch` with keywords like "git", "diff", "blame"
- Model-friendly descriptions explain when to use each tool vs bash
## Testing
```bash
cd rust
cargo build --release
cargo test -p tools
```
The 3 pre-existing test failures (agent_fake_runner, agent_persists_handoff, worker_create_merges_config) are unrelated to this change — they fail due to local settings.json incompatibilities.