Skip to main content

Checkpoints on a paired machine

When the worker auto-pulls a project via git, the paired machine ends up with a real git repo at ~/.shogo/projects/<projectId>/.git. That means every checkpoint Shogo has ever recorded for the project — auto-checkpoints from agent chat turns, manual snapshots you took in Studio, even rollback points — is a regular reachable git commit on your VPS.

This is the inverse of "Shogo manages git for you." The cloud still owns the write path (the worker pushes commits up; the cloud's post-receive hook materializes a ProjectCheckpoint row); but locally you have an ordinary git repo you can git log, git diff, and git checkout like any other.

See the timeline​

cd ~/.shogo/projects/<projectId>
git log --oneline -20

You'll see entries like:

e3f8a01 auto: 2026-05-15T14:32:11.480Z
4b2c109 AI: edit_file (3 tool calls)
a0e774d Before pricing-page refactor ← named checkpoint
…

The same SHAs are visible in Studio's checkpoint panel — that's the single source of truth in ProjectCheckpoint Postgres rows, populated by the cloud on every push.

Roll the workspace back​

shogo project checkout wraps git fetch && git reset --hard and resolves named checkpoints against the cloud's /checkpoints listing:

# By full or short SHA
shogo project checkout <projectId> --at a0e774d

# By named checkpoint (case-insensitive substring match on name/message)
shogo project checkout <projectId> --at "before pricing-page refactor"

# Fast-forward to the latest commit in the cloud
shogo project checkout <projectId>

# Reach further back than the default --depth=1 clone
shogo project checkout <projectId> --at <old-sha> --unshallow

After a checkout the worker's agent-runtime (if running) will see the restored files on its next chat turn. The watcher pauses its push during a checkout to avoid race-pushing a "reverted" commit back up.

What about the runtime's own writes?​

When SHOGO_CLOUD_SYNC=1 is set (which the worker does whenever auto-pull is on), the agent-runtime skips its built-in S3 sync and its built-in checkpoint inserts. The cloud's post-receive hook is the single writer of ProjectCheckpoint rows in worker mode — so you can't end up with two rows for the same SHA, and you can't push from the worker faster than the cloud records it.

Audit trail​

Every push from the worker is authenticated with a shogo_sk_* key (yours, not someone else's). The post-receive hook stamps each new ProjectCheckpoint with that key's owner as createdBy, so you can grep the timeline for "who made this commit" without trawling git's author fields.

Caveats​

  • One writer per project. Shogo doesn't expect two workers (or a worker + the desktop) pushing into the same project's repo concurrently. If you set up two-machine redundancy, pin per-project to avoid push conflicts.
  • receive.denyCurrentBranch=updateInstead is set on the cloud-side repo, so pushes that fast-forward and find a clean working tree will also update the checkout. If the cloud-side workspace has uncommitted changes (only possible if the project was ever served from the cloud directly), the push will be rejected and you'll see error: cannot update the current branch in a non-bare repository.
  • .shogo/ is gitignored. Your SQLite history and per-checkpoint DB snapshots travel through the Files API, not the git wire. shogo project checkout does NOT touch them — running it leaves the on-disk DB alone, and the next request fixes things up.

Reverse operations​

If you want to push a commit you made locally on the worker into the cloud's checkpoint history (say, you edited a few files outside the agent flow):

cd ~/.shogo/projects/<projectId>
git add -A
git commit -m "manual: tweak landing copy"
git push origin HEAD

The cloud will record a ProjectCheckpoint for that commit with createdBy set to the API key's owner, isAutomatic: true, and the original commit message preserved. Studio's checkpoint panel will show it within a few seconds.