The largest group here, and the shape is consistent: the repo rides in the address and the verb is the route. Reading is history, differences and status; writing is staging, committing, branching, tagging, stashing, cherry-picking, reverting and pushing. Two routes cover a repo caught mid-merge or mid-rebase, and one answers what undoing would actually do before you undo it.
43 calls. Pick one to open it, or use the list on the right.
GET/git/changesUncommitted work across every repo
The workspace's whole review set in one answer: every repo that has something uncommitted, and within it every changed file with its status and line counts. This is what the Changes panel draws, and it is the call to make when you want to know whether a workspace is clean without walking the repos yourself.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.changes();
GET/git/reposEvery git repo in the workspace
The repos the daemon found under the workspace root, each with the id every other call in this group expects as its `{repo}` segment. The workspace root itself is always present as `root`.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.repos();
GET/git/remote-reposRepos matched to their remotes
The same repo list, but with the forge host and `owner/name` each one's remote points at. Use it to recognise a workspace repo in a list of names that came from somewhere else, such as a set of pull requests. Costs a remote lookup per repo, which is why it is separate from the plain repo list.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.remoteRepos();
GET/git/{repo}/logCommit history for one repo
A page of commits on the current branch, newest first, each with its author, subject, timestamp and the refs pointing at it. Paginate with the cursor the answer hands back rather than by offset, so a commit landing mid-scroll does not shift the page under you.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.log({ "repo": "root"});
GET/git/{repo}/commit-diffWhat one commit changed
The list of files a single commit touched, with per-file status and line counts but not the content. Fetch the content of any one of them with the commit file diff call, so a commit with a thousand files stays one cheap answer.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.commitDiff({ "repo": "root", "sha": "9f2c1ab3d4e5f60718293a4b5c6d7e8f90a1b2c3"});
GET/git/{repo}/commit-file-diffOne file's before and after at a commit
Both sides of a single file as of one commit: the content its parent had and the content that commit left. The daemon returns whole sides rather than a patch, so a caller can render the comparison however it likes.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.commitFileDiff({ "repo": "root", "sha": "9f2c1ab3d4e5f60718293a4b5c6d7e8f90a1b2c3", "path": "src/app.ts"});
GET/git/{repo}/operationWhether a merge or rebase is halted mid-flight
Names the git operation the worktree is stuck inside, if any: a conflicted merge, an interrupted rebase, a half-applied cherry-pick. Check this first when another call refuses, because a halted worktree is the usual reason and the abort call is the way out.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.operation({ "repo": "root"});
POST/git/{repo}/abortAbandon a halted merge or rebase
Runs git's own abort for whichever operation has the worktree halted, putting the repo back where it stood before the operation started. Nothing else clears that state.
What you send
Field
Type
Where
reporequiredWhich repository
string
address
What comes back
Field
Type
okWhether it worked
boolean
reasonWhy not, in git's own words
string
Try itanswered in this tab
curl
curl -X POST "$SANDBOX/git/root/abort" \ -H "x-intentic-control: $INTENTIC_TOKEN"
TypeScript
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.abort({ "repo": "root"});
GET/git/{repo}/undoWhat undoing the last action would do
Reads the branch's reflog to describe the move that undo would reverse, and hands back the commit it would land on. Pass that commit to the undo call as proof you looked, and an undo prepared against a view that has since moved is refused rather than landing somewhere unexamined.
What you send
Field
Type
Where
reporequiredWhich repository
string
address
What comes back
Field
Type
repoWhich repository
string
actionWhat undoing would reverse
object
kindWhat the last action was
"commit" | "amend" | "merge" | "rebase" … (9)
descriptionWhat undoing it would do, in…
string
branchWhich branch would move
string
shaWhere it stands now
string
previousShaWhere it would go back to
string
changesWorkingTreeUndoing would rewrite files as well…
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.undoable({ "repo": "root"});
POST/git/{repo}/undoMove the branch back one step
Walks the current branch back to where it pointed before its last action. This moves the branch ref and leaves the working tree alone, which is the opposite of restoring a checkpoint. Requires the commit the matching read handed you.
What you send
Field
Type
Where
reporequiredWhich repository
string
address
previousSharequiredWhere to go back to, from…
string
body
discardChangesAlso rewrite the files, rather than…
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.undo({ "repo": "root", "previousSha": "1a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d", "discardChanges": true});
GET/git/{repo}/stashesEverything set aside in the stash
The repo's stash entries, newest first, each with the message and the commit behind it. A stash entry is a commit, so it reads the same way a log entry does and its contents come back from the stash diff call.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.stashes({ "repo": "root"});
GET/git/{repo}/stash-diffWhat one stash entry holds
The files a single stash entry would bring back, with per-file status and line counts. The same shape a commit diff has, because a stash entry is a commit.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.stashDiff({ "repo": "root", "ref": "refs/heads/main"});
POST/git/{repo}/stashSet the current changes aside
Moves the working tree's changes onto the stash and leaves a clean tree behind. Nothing is lost: the entry is a commit you can inspect, apply or drop afterwards.
What you send
Field
Type
Where
reporequiredWhich repository
string
address
messageWhat to call it, so you…
string
body
includeUntrackedAlso set aside files git is…
boolean
body
What comes back
Field
Type
okWhether it worked
boolean
reasonWhy not, in git's own words
string
Try itanswered in this tab
curl
curl -X POST "$SANDBOX/git/root/stash" \ -H "x-intentic-control: $INTENTIC_TOKEN" \ -H "content-type: application/json" \ -d '{"message":"Fix the flaky parser test","includeUntracked":true}'
TypeScript
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.stashPush({ "repo": "root", "message": "Fix the flaky parser test", "includeUntracked": true});
POST/git/{repo}/stash/applyBring a stash entry back
Replays one stash entry onto the working tree. A conflict is reported in the answer rather than raised as a failure, because a conflicting apply is an ordinary outcome a screen has to render.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.pushTag({ "repo": "root", "name": "nightly changelog", "remote": "origin"});
POST/git/{repo}/checkoutSwitch to a branch or commit
Moves HEAD to a branch, tag or commit and reshapes the working tree to match. The daemon takes a checkpoint first, so an unexpected result is recoverable. Uncommitted work that would be overwritten is reported instead of being trampled.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.checkout({ "repo": "root", "ref": "refs/heads/main"});
POST/git/{repo}/cherry-pickReplay one commit onto this branch
Applies a single commit's changes on top of the current branch as a new commit. A conflict comes back in the answer, with the halted state readable from the operation call.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.cherryPick({ "repo": "root", "sha": "9f2c1ab3d4e5f60718293a4b5c6d7e8f90a1b2c3"});
POST/git/{repo}/revertUndo a commit with a new commit
Adds a commit that reverses an earlier one, leaving the history intact. This is the safe way to take something back on a branch other people have pulled.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.drop({ "repo": "root", "sha": "9f2c1ab3d4e5f60718293a4b5c6d7e8f90a1b2c3"});
POST/git/{repo}/mergeMerge another branch in
Merges a branch or commit into the current one. Conflicts are reported in the answer and leave the worktree halted, which the operation call explains and the abort call clears.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.merge({ "repo": "root", "sha": "9f2c1ab3d4e5f60718293a4b5c6d7e8f90a1b2c3"});
POST/git/{repo}/rebaseReplay this branch onto another
Moves the current branch's commits on top of a different base. History changes. Conflicts halt the rebase and are reported rather than raised, so the operation and abort calls are the way through.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.reset({ "repo": "root", "sha": "9f2c1ab3d4e5f60718293a4b5c6d7e8f90a1b2c3", "mode": "soft"});
GET/git/{repo}/file-diffOne file's committed and working copies
Both sides of a file as it stands right now: what the last commit holds and what is on disk. This is what a review pane shows for an uncommitted change.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.fileDiff({ "repo": "root", "path": "src/app.ts", "side": "staged"});
GET/git/{repo}/statusOne repo's branch and pending changes
The current branch, its sync position against the remote, and every staged, unstaged and untracked path. The single-repo counterpart to the workspace-wide changes call.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.status({ "repo": "root"});
POST/git/{repo}/commitCommit the pending changes
Records a commit with your message. Give it a list of paths to commit only those, or leave it out to commit everything pending. The answer carries the commit it created.
curl -X POST "$SANDBOX/git/root/commit" \ -H "x-intentic-control: $INTENTIC_TOKEN" \ -H "content-type: application/json" \ -d '{"message":"Fix the flaky parser test","all":false,"paths":["src/app.ts","README.md"]}'
TypeScript
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.commit({ "repo": "root", "message": "Fix the flaky parser test", "all": false, "paths": [ "src/app.ts", "README.md" ]});
POST/git/{repo}/discardThrow away pending changes
Restores files to their committed state and deletes untracked ones. Give it paths to discard only those. The daemon checkpoints the workspace first, so this is recoverable from the timeline.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.unstage({ "repo": "root", "paths": [ "src/app.ts", "README.md" ]});
GET/git/{repo}/branchesLocal branches and how far each has drifted
Every local branch with how many commits it sits ahead of and behind its remote counterpart, so a branch switcher can show sync state without a call per branch.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.deleteBranch({ "repo": "root", "name": "nightly changelog", "force": false});
GET/git/{repo}/remoteSync position against the remote
How far the current branch sits ahead of and behind its remote, as of the last fetch, plus whether a remote and working credentials exist at all. This is a read of what the daemon already knows, not a network call, which is why fetching is a separate button.
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.remote({ "repo": "root"});
POST/git/{repo}/fetchRefresh what the remote holds
Contacts the remote and updates the daemon's picture of it without touching your branch. Run this before trusting the sync position.
What you send
Field
Type
Where
reporequiredWhich repository
string
address
What comes back
Field
Type
okWhether it worked
boolean
reasonWhy not, in git's own words
string
Try itanswered in this tab
curl
curl -X POST "$SANDBOX/git/root/fetch" \ -H "x-intentic-control: $INTENTIC_TOKEN"
TypeScript
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.fetch({ "repo": "root"});
POST/git/{repo}/pullBring remote commits down
Fetches and integrates the remote's commits into the current branch. A pull that cannot fast-forward is reported in the answer rather than raised, because that is an ordinary thing to be told.
What you send
Field
Type
Where
reporequiredWhich repository
string
address
What comes back
Field
Type
okWhether it worked
boolean
reasonWhy not, in git's own words
string
Try itanswered in this tab
curl
curl -X POST "$SANDBOX/git/root/pull" \ -H "x-intentic-control: $INTENTIC_TOKEN"
TypeScript
import { sandbox } from "@intentic/sandbox-client";const result = await sandbox.git.pull({ "repo": "root"});
POST/git/{repo}/pushSend commits to the remote
Pushes the current branch, setting its upstream on first push. A rejected push, a missing remote and missing credentials all come back as reported outcomes rather than failures.
POST/git/{repo}/publish-fileWrite, commit and push one file
The three steps as a single call with a single answer, committing only the path you named and leaving any other pending work alone. Being on a side branch, having no remote and having no credentials are all reported rather than raised.
What you send
Field
Type
Where
reporequiredWhich repository
string
address
pathrequiredWhich file, relative to the repository
string
body
contentrequiredIts whole new contents
string
body
messagerequiredThe commit message
string
body
What comes back
Field
Type
okWhether the whole thing went through
boolean
wroteThe file was written
boolean
committedThe commit was recorded
boolean
pushedIt reached the remote
boolean
branchWhich branch it happened on
string
defaultBranchWhich branch the repository considers its…