Skip to content

feat: git-aware context tools#2832

Open
TheArchitectit wants to merge 8 commits into
ultraworkers:mainfrom
TheArchitectit:feat/git-aware-tools
Open

feat: git-aware context tools#2832
TheArchitectit wants to merge 8 commits into
ultraworkers:mainfrom
TheArchitectit:feat/git-aware-tools

Conversation

@TheArchitectit
Copy link
Copy Markdown

@TheArchitectit TheArchitectit commented Apr 28, 2026

Summary

This PR adds five native, read-only git tools that replace ad-hoc bash invocations for common git operations: GitStatus, GitDiff, GitLog, GitShow, and GitBlame.

Problem

Before this change, the model had to use the generic bash tool for every git operation. This created several friction points:

Issue Impact
Requires DangerFullAccess Even read-only git commands need elevated permissions
Unstructured text output Model must parse raw CLI output; brittle across git versions
Not discoverable ToolSearch won't find "git diff" because no such tool exists
Inconsistent flags Each bash invocation may use different formatting options
Wastes context window Raw git log output with ANSI colors and padding consumes tokens

Solution

Five first-class tools with structured JSON output, ReadOnly permissions, and model-friendly descriptions:

Tool Purpose Key Parameters
GitStatus Branch and working tree status path (optional repo root)
GitDiff Show changes between commits, or working tree vs index staged, commit, path
GitLog Commit history with filtering options count, oneline, author, since
GitShow Details for a specific commit commit (hash or ref), stat
GitBlame Line-level authorship for a file path, start_line, end_line

All tools:

  • Use PermissionMode::ReadOnly — safe in restricted environments
  • Return structured JSON — no parsing required
  • Are discoverable via ToolSearch with keywords like "git", "diff", "blame", "history"
  • Include detailed doc comments explaining when to use the tool vs. generic bash

Implementation

  • Added tool structs in rust/crates/tools/src/git.rs with ToolDescription derive macros
  • Implemented run() for each tool using the existing git_stdout() helper
  • Added comprehensive error handling for "not a git repo" and "file not found" cases
  • All tools validate the target path is within the workspace sandbox

Test Plan

  • GitStatus returns correct branch and file status JSON
  • GitDiff with staged: true shows cached changes
  • GitLog with count: 5 and oneline: true returns condensed history
  • GitShow with a commit hash returns the diff and metadata
  • GitBlame with a file path and line range returns per-line authorship
  • All tools report clear errors when run outside a git repository
  • All tools are listed by ToolSearch with relevant keywords
  • Permission mode is ReadOnly for all five tools

Impact

  • Safer: Read-only git operations no longer require DangerFullAccess
  • More reliable: Structured output eliminates parsing brittleness
  • More discoverable: Model can find and use git tools without being told they exist
  • Token-efficient: JSON output is more compact than raw git CLI formatting
  • Backward compatible: Existing bash git invocations continue to work

TheArchitectit and others added 8 commits May 10, 2026 21:26
…w, GitBlame)

Add five native git tools that provide structured read-only access to
repository state, replacing ad-hoc bash git commands with purpose-built
tool definitions the model can discover and invoke directly.

- GitStatus: working tree status with --short --branch
- GitDiff: diff with optional staged/commit/path filters
- GitLog: commit log with count, oneline, author, since/until, path
- GitShow: show commit/tree content with optional stat and path
- GitBlame: line-level blame with optional start/end line range

All tools use the existing git_stdout() helper and are PermissionMode::ReadOnly.
Some OpenAI-compatible providers (e.g., GLM-5) omit the `id` field in
streaming and non-streaming responses. Adding #[serde(default)] allows
the parser to accept these responses instead of failing with
"missing field `id`".

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds scripts/install.sh that builds the release binary and links it
to ~/.local/bin/claw. Run after code changes to update the CLI.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
When a provider returns HTML (e.g., error page, wrong endpoint) instead
of JSON in an SSE stream, provide a clear error message instead of
hanging or failing with a cryptic parse error.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
When a provider returns a JSON error (e.g., {"error":{"message":"..."}})
without SSE framing (no "data:" prefix), the SSE parser was silently
ignoring it and hanging. Now detects and surfaces these errors.

Also handles HTML responses that lack SSE framing.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Some providers (GLM, DeepSeek) emit reasoning tokens in `reasoning_content`
or nested `thinking.content` fields instead of `content`. Added support
for these fields so reasoning models work correctly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The final streaming chunk from some providers contains only finish_reason
and usage, with no delta field. Made it optional to prevent parse errors.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
When preserve_recent_messages == 0, raw_keep_from equals messages.len(),
causing index out of bounds when accessing session.messages[k].

Added k >= session.messages.len() check to prevent panic.

Reason: Compaction with preserve_recent_messages=0 triggered OOB access
when checking for tool-use/tool-result pair preservation at boundary.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@TheArchitectit TheArchitectit force-pushed the feat/git-aware-tools branch from fd03455 to 7aedde7 Compare May 10, 2026 21:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant