AI agents and Git, without handing over the keys.
The AI-coding wave has a quiet failure mode nobody likes to talk about: when you let an agent run git for you, it can commit things you never reviewed. People have already watched agents auto-commit secrets straight into git history, which is immutable, so the secret is there forever even after you "delete" it. FluxGit makes that impossible by construction, not by policy: the agent never holds a write capability. There is no tool it can call to commit, merge, rebase or reset. It can only propose. The desktop app shows the exact diff, you approve or reject, and only then does anything execute.
The two failure modes today.
A strictly read-only Git MCP is the safe default and the path most servers take. The agent can explain why a branch is divergent, summarize a diff, suggest a rebase strategy, walk the reflog after a bad reset. It cannot help do any of it. The user reads the explanation and then context-switches to a terminal or a GUI to actually move the refs. The agent is a research assistant trapped behind glass.
A direct-write Git MCP is the other extreme. The agent gets merge, rebase,
reset, apply-patch as ordinary tools and decides for itself when to call them. This works
beautifully in demos and breaks badly in production. Hallucinations, prompt injection from a malicious README, or
a model that has misunderstood the task all become destructive Git operations. The audit trail says the agent did
it, but nobody approved it.
The third path needs something neither extreme has: an application that can render an approval modal. An MCP server alone cannot ask the user a question; it answers tool calls. Wire an MCP server to a desktop app you already trust for Git, and the loop closes. Agents propose, the app shows the preview, you decide.
This is also why the secrets scenario from the opening cannot happen here. A leaked credential reaches history
through a commit nobody read. In FluxGit's model there is no commit the human did not read: the proposed change
is rendered as a real diff in the approval card, so an .env file or an API key sitting in the patch
is staring at you before anything touches the repository. And the whole handshake runs on loopback between the
sidecar, the gateway and the app on your machine; the proposal never transits a cloud service.
What shipped on 2026-05-28, and what landed since.
The full surface is live in FluxGit's MCP layer. Twenty-two read-only tools cover repository inspection:
repo.brief (one-call situational awareness, advertised first because it replaces the 6-10 raw git
calls an agent burns just learning where it is), repo.scope (everything about one monorepo subtree
in a single call), repo.status, repo.refs, repo.branchStack,
repo.history, repo.reflog, commit.details, worktree.changes,
worktree.list, submodule.status,
diff.text, diff.semantic with explicit fallback, diff.semanticFallbacks,
repo.conflictPreflight, conflict.read (an active conflict as structured data instead of raw markers, shipped 2026-06-11), fleet.radar, safety.timeline,
safety.eventDetails, flux.latestRestorePoint, flux.restorePoints,
flux.restorePointDetails. Each call returns a structured payload tagged with
source: "local-git" or source: "fluxgit-app", so the agent always knows whether the data
came from raw git or from FluxGit's enriched layer.
Six write tools complete the loop, and they all dispatch through the same UI handshake:
operation.preview.merge, operation.preview.rebase, operation.preview.discard,
operation.preview.reset, operation.preview.patch, and since 2026-06-10
operation.preview.plan, which lets an agent propose up to ten steps as one reviewable plan with a
single approval and stop-on-failure execution. None of them touch refs directly. Each
one opens an approval card in the desktop app, pre-filled with the agent's reason in plain language, and waits for
the user.
The handshake itself is a simple HTTP loop. The sidecar POSTs the proposal to a loopback gateway. The gateway
mounts an approval card inside the FluxGit app via the existing Tauri bridge. The user clicks Approve or Reject.
On approval, FluxGit calls the same internal function a manual operation would have called - the merge runs
through mergeRefIntoCurrentBranch, the rebase runs through the existing rebase action, and so on -
so restore points, preflight checks and the safety timeline all apply unchanged. On rejection, the operation
stops and the audit log records the reason. The sidecar polls for the result and returns it to the agent.
The wire contract is forward-stable. Clients written today against operation.preview.merge keep
working when the other four operations land in their MCP host's UI. The protocol carries an explicit
operationType field so audit consumers can route by type without parsing URLs, and a
previewId that threads through every layer: agent intent, user decision, executed commit. If the
handshake server is unreachable the sidecar returns error code 10003
(write_handshake_pending) instead of silently failing, which keeps the contract honest for hosts
that connect before FluxGit is running.
The audit log is opt-in Ed25519 signed. Set FLUXGIT_MCP_AUDIT_SIGN_KEY to a PEM PKCS8 private key
and every appended entry carries a signature over the canonical JSON of the entry (the
signature field stripped, keys sorted lexicographically, default compact serialization). A public
verify-audit CLI subcommand walks the JSONL with the matching public key and prints
verified / failed / unsigned / malformed counts. Unsigned entries are counted separately so a team
can roll signing out incrementally without breaking the verifier on older history. This is the bridge between
AI provenance and human accountability: the audit chain links the agent's intent, the user's approval, and the
resulting commit SHA, and that link can be cryptographically verified after the fact.
What the agent sends.
Every write proposal is a small JSON body with the operation type, the refs or paths involved, a free-form
reason, and a previewId. Here is what an MCP-compatible code agent sends when it wants
to merge a feature branch into main:
POST /v1/mcp/operation/preview/merge
{
"previewId": "a8f3-7c21-...",
"agentId": "external-mcp-sidecar",
"operationType": "merge",
"repoPath": "/Users/eng/work/checkout",
"sourceRef": "feature/checkout-redesign",
"targetRef": "main",
"reason": "Checkout redesign work is complete; tests pass on the feature branch.",
"strategy": "merge",
"requestedAt": "2026-05-28T09:50:11.123Z"
}
The gateway responds 202 Accepted immediately and the agent polls the shared status endpoint until
the user makes a decision. The completion payload carries the commit SHA and the restore point ID - facts the
agent could not have invented:
GET /v1/mcp/operation/status/a8f3-7c21-...
{
"previewId": "a8f3-7c21-...",
"operationType": "merge",
"status": "completed",
"result": {
"commitSha": "9b7c4e2f...",
"restorePointId": "rp_2026_05_28_0950_11",
"conflicts": null
}
}
If the user rejects, status becomes rejected and the payload carries an optional
rejectionReason. If the proposal expires (default TTL is five minutes), status becomes
expired. The agent treats anything other than completed as a non-error signal to ask
the user what happened in plain language, not as a transport failure.
One concrete narrative.
An engineer asks their code agent to merge feature/checkout-redesign into main. The
agent calls repo.status to confirm the working tree is clean, asks diff.semantic for
a structured view of the change (and gracefully falls back to diff.text if the semantic engine is
not wired), then calls operation.preview.merge with a one-sentence reason. FluxGit
mounts an approval card inside the desktop app with a banner reading "Requested by AI agent", the
source and target refs, the agent's reason in plain language, and a note that a restore point will be created
before the merge applies.
The engineer reads the card. The diff matches what they expected. They click Approve. The modal swaps to an "Applying merge..." spinner while FluxGit captures the restore point and runs the merge through the same internal function a manual merge would have used. The history view updates. The safety timeline gains an entry. The audit log records the agent's intent, the engineer's approval, the preview ID, and the resulting commit SHA - signed end to end if signing is on. The agent's last message updates with the commit SHA and the restore point ID, and the loop closes. Total elapsed time: about seventy-five seconds.
What is not shipped - explicit honesty.
A few pieces are still in flight, and saying so is part of the contract. Interactive rebase is rejected at the approval pipeline because the handshake does not carry an interactive step list yet; non-interactive rebase works end to end. Real-time agent-to-app notification is implemented as a 1.5-second poll, not a push channel, which is fine for one developer but will need a push transport for shared deployments. A cloud-hosted MCP for teams who do not want to install the desktop app on every machine is on the roadmap; the current sidecar is stdio only. The launch demo video is in the can but not yet edited and posted. Everything in the section above is shipped code with tests; everything in this paragraph is honest about what comes next.
Why this matters.
The Model Context Protocol is open. FluxGit speaks it like everyone else, and the standalone shell works
without the FluxGit app for most of the read-only surface: twelve tools served purely from local
git, plus four hybrids (fleet radar, semantic diff and conflict preflight among them) that answer
locally and say so honestly when the app is not wired. That buys distribution: any
MCP-compatible code agent can connect, no vendor lock-in, no special client wiring. Per playbook stance, the
generic JSON config block is the default; per-host cheat sheets, when added, will live behind a neutral dropdown
rather than as the primary CTA.
The interesting parts of the surface require the desktop app, and that is by design rather than by accident. The safety timeline is synthesized from FluxGit restore points and the reflog. The approval modal lives inside the app's existing UI shell. The write handshake terminates at a Tauri command bridge that calls the same internal Git actions a manual click would call. Cloud-hosted MCP servers without an app cannot do any of this - they have no UI to render an approval card in. That is the business model and the moat at the same time.
The practical pitch for developers is short. Let the agent do the planning. Keep yourself in the loop on the
writes. Pay nothing for inspection - the free shell speaks MCP and answers repo.status,
diff.text, the rest of the read-only surface against local git. Pay FluxGit when you
want the safety nets: restore points, predictive conflict preflight, the safety timeline, fleet radar, the
signed audit chain, and the approval modal that turns operation.preview.merge from a slogan into
a closed loop.