cli.sgit.ai / Guides / Pack mode: a playbook for agents

Pack mode: a playbook for agents

This page is written for an agent that has been told to use sgit pack vaults in a project. It is also for the person setting that agent up. Follow the recipes in order. Every command and every message quoted here was run against sgit-ai 0.24.0 on dev.send.sgraph.ai. What a pack vault is, and the numbers, are in the 0.24.0 release notes.

0. Three rules before anything else

  1. Experiment on a vault you created for the experiment. Never on a vault other people or agents are using. Delete it when you are done: sgit vault delete-on-remote --yes inside its folder.
  2. A vault key is the whole credential. Print it once, save it where your project keeps secrets, and never write it into a file inside a vault, a log, a commit message or a chat.
  3. Never copy, zip or commit .sg_vault/local/. It holds this clone's key and token. The shareable part of a vault is .sg_vault/bare/.

1. Install and check

$ python -m pip install --upgrade sgit-ai
$ sgit version
sgit-ai v0.24.0                      # 0.24.0 or later; an older client is refused by every pack vault
$ sgit pack --help                   # lists import, export, compact, ls, verify, stats

Credentials. Network commands need the server and an access token:

2. Decide: pack vault or normal vault

The vault will be …ChooseWhy
Cloned whole, by CI jobs or by agents starting freshpackA clone is 3 or 4 requests whatever the history: 8.1 s against 28.6 s on a 2,087-object vault, 25 s against 3½ minutes on a 33,000-object history
Mostly text: Markdown, JSON, logs, emailpackFiles are compressed before encryption: 1.66× on a mixed vault, 3.7× on prose and JSON, 8.8× on JSONL logs
Pushed to often, by several writerspackA push is one zip whatever its size, and the ref moves exactly as before
Browsed in the web view (vault.sgraph.ai, a vault app, a published vault page)normalThe browser does not read packs
Large, with agents that each take one folder (--path <folder> --depth 1)normal, for nowOn a pack vault --path and --depth download the packs whole; on a normal vault one folder of a 527 MB vault is 3 MB
Read with clone-branch or clone-rangenormalThose two refuse a pack vault

When in doubt, use a pack vault for anything an agent clones whole and a normal vault for anything a person browses. You can move between the two later (section 4).

3. Recipe: a new pack vault

$ mkdir my-vault && cd my-vault
$ sgit init --packs --base-url https://dev.send.sgraph.ai
Vault created!  Vault ID: <id>  (pack vault)
  Vault key: <the key: save it now>
$ # … add files …
$ sgit commit -m "first"
$ sgit push --token <token>          # the first push uploads one snapshot

sgit create --packs <name> makes the folder and the vault in one step. It prints "Pushing to remote … Vault ready", but nothing reaches the server until a first commit is pushed, and until then a clone with the key fails. So add a file, sgit commit, then sgit push, as above. A normal sgit create behaves the same way.

To join a pack vault that already exists, sgit clone <vault key> <dir> --base-url <server> --token <token>. The clone prints what it fetched:

  ▸ Packs fetched (1 pack(s), 2087 objects, 4 request(s) in 6.2s)

The request count stays at 3 or 4 whatever the size of the history. If a clone of a pack vault ever reports fetching objects one by one, stop and report it (section 9).

4. Recipe: convert an existing vault, and cut a team over to it

A vault is never converted in place. You make a new pack vault from a full clone of the old one, check it, hand out the new key, and keep the old vault until nobody needs it.

# 1. Stop writes to the old vault (tell the other agents), then take a FULL clone
$ sgit clone <old vault key> old-full --base-url <server> --token <token>
#    (no --path, no --depth: see the note below)

# 2. Make the pack vault (local only, nothing is uploaded yet)
$ sgit pack import old-full new-packs
  Imported into a new pack vault: new-packs/
  Vault key: <the NEW key: save it now>
  History:   17 commits, 244 trees, 1826 blobs
  Blobs:     213.0 MB -> 128.6 MB (x1.66, 1811 deflated)

# 3. Check, then push
$ cd new-packs && sgit status       # "This vault has never been pushed … 17 commits waiting"
$ sgit push                         # "Pushed 17 commit(s), 2087 object(s) uploaded."

# 4. Prove it: a fresh clone must match the old one file for file
$ cd .. && sgit clone <NEW key> check --base-url <server> --token <token>
$ diff -rq old-full check -x .sg_vault && echo IDENTICAL

Things to know:

5. The daily loop

Nothing changes:

$ sgit pull
$ # … work …
$ sgit commit -m "what changed"
$ sgit push

What the output should look like:

Expect a few seconds per network command: about 5 to 6 s for a push and 3 to 4 s for a pull on a 2,000-object vault from a cloud sandbox. On a long history, push and pull also spend time in local merge and status walks. That is the same on a normal vault.

6. Compaction: who, when, how

Every push adds one small zip to bare/packs/commits/. Compaction folds them into one new snapshot of the head and moves the old zips to bare/packs/archive/. Nothing is ever deleted without its copy being listed in archive/ first, and archive/ itself is never deleted.

Who. Give the job to one agent, or to the vault's owner. Two compactions at the same moment are safe (tested live: both finish, the vault is intact), but they do the same work twice.

When. When commits/ holds more than 50 packs, or more bytes than a tenth of the newest snapshot (sgit's own thresholds). Nothing triggers it automatically. Check with pack ls --json, which only lists the host:

$ sgit pack ls --json > packs.json
$ python3 -c "import json; d=json.load(open('packs.json')); c, s = d['commits'], d['snapshots']; \
  print('compact' if len(c) > 50 or sum(e['size'] for e in c) > 0.10 * (s[-1]['size'] if s else 0) else 'not yet')"

Avoid pack stats for this check on a big vault. It decrypts every file to compute the compression ratio, which took 52 s on a 33,000-object history.

Run it when the team is quiet. After a compaction, every clone that was behind downloads the whole new snapshot on its next pull (130 MB and 9.5 s on a 2,087-object vault), instead of the few packs it lacked.

How:

$ sgit pull                                    # compaction refuses a clone that is behind
$ sgit status                                  # and a dirty working tree
$ sgit pack compact --dry-run                  # the plan: what goes to archive/
$ sgit pack compact
  Did snapshot head obj-cas-imm-…: <epoch>__obj-cas-imm-…__<bytes>.zip
  3 pack(s) absorbed by the snapshot -> archive/
  1 pack(s) superseded snapshots -> archive/
  4 pack(s) archived. Nothing was deleted without its copy in archive/.
$ sgit pack verify                             # every member of every pack checked: "ok"

What gets archived and what stays:

7. Patterns

A CI job.

sgit clone "$VAULT_KEY" work --base-url "$SGIT_SERVER" --token "$SGIT_TOKEN"
cd work && ./run-the-job.sh && sgit commit -m "run $RUN_ID" && sgit push

Many agents on one vault.

Read-only readers. A clone made with a read key takes and pulls packs. It cannot push or compact, and it says so.

A throwaway vault per task. sgit create --packs <name>, work, then sgit vault delete-on-remote --yes when the task is done. Check the deletion: a clone with the old key must now fail.

8. Health checks

CheckGoodNot good
sgit pack lssnapshots/ 1 or more, commits/ some, archive/ growing over time; * marks what this clone absorbedsnapshots/ empty on a vault that has been pushed
sgit pack statsloose objects under bare/data/: 0 (tag objects are counted apart)any loose objects: something wrote a normal object into a pack vault
sgit pack verifyN pack(s), M member(s) checked against their ids then okanything else
A fresh clonePacks fetched (…, 3 or 4 request(s) …) and diff -rq against a working clone is emptyobjects fetched one by one, or a difference

9. Messages you will meet, and what to do

MessageMeaningWhat to do
this vault needs sgit-ai >= 0.24.0 and this is 0.23.0: run sgit update, then try againThe client is older than pack modepython -m pip install --upgrade sgit-ai, check sgit version, retry
this is a pack vault (objects travel as packs): sgit clone-branch and clone-range do not read packs yet. Use sgit clone (or clone-headless, whose fetch does).Those two clone modes do not read packsUse sgit clone, or sgit clone-headless then sgit fetch <path>
no access token configured. Pass --token …This folder has no saved tokenPass --token <token> once; it is saved for the folder
working directory has uncommitted changes; commit or stash them, then compactCompaction needs a clean treeCommit or stash, then compact
this clone's named head (…) is not the server's (…): run sgit pull first, then compactSomeone pushed since your last pullsgit pull, then compact
the named branch moved while compacting: nothing was archived (the snapshot … stays on the host). Pull and run sgit pack compact again.A push landed during compactionsgit pull, then compact again. The extra snapshot is harmless and the next compaction archives it
… pack(s) archived (n already in archive)Another compaction of the same head did part of the workNothing
This vault has never been pushed. It only exists on this machine.A new or freshly imported vaultsgit push
A pull or clone that names a pack and refuses its membersA pack failed its checks; nothing from it was writtenStop, do not retry in a loop, and report it (below)

Reporting a problem. Send the output of sgit version, the exact command, the command again with --debug, and the output of sgit pack ls and sgit pack verify. Never send the vault key, the token or anything from .sg_vault/local/.

10. Never

11. A block for an agent's own instructions

Paste this into the instructions of an agent that will use a pack vault, with your own values in the first three lines:

## Vault (sgit pack vault)
- Server: https://dev.send.sgraph.ai
- Vault key: in <where your project keeps secrets>; never print it, never write it into a file in the vault.
- Token: passed once with --token on the first network command in a folder; sgit saves it in .sg_vault/local/.
- Requires sgit-ai >= 0.24.0 (`sgit version`). Playbook: https://cli.sgit.ai/docs/pack-mode-for-agents.md
- Start of a session: `sgit pull`. End: `sgit commit -m "<what changed>"` then `sgit push`.
- Use `sgit clone`, never clone-branch or clone-range. --path/--depth download the whole vault on a pack vault.
- Do not run `sgit pack compact` unless you are the designated compactor.
- Never copy, zip or commit .sg_vault/local/; never delete anything under bare/packs/.
- If a pack fails its checks, or a clone fetches objects one by one: stop and report
  (sgit version, the command, --debug output, `sgit pack ls`, `sgit pack verify`), with no keys.

Written by cli.sgit.ai's build agent on 22 October 2026, from the CLI's code at the 0.24.0 merge and from live trials on dev.send.sgraph.ai. The CLI team's own pages are the feature reference and the tester's how-to.

This page as markdown · its source, admin/content/docs/pack-mode-for-agents.md