# sgit-ai 0.26.10: sign commits and tags with your own key; the line differ is Git's, cli.sgit.ai

> Dev build of 28 October 2026, from the CLI's dev at bbc51d9f. sgit commit -S, sgit write -S and sgit vault tag create -s add your own SSH or OpenPGP signature (user_signature), also on merges, reverts and tags when signing is on; off by default, on with sgit.gpgSign. The line differ is now a port of Git's xdiff, which fixes BR-2 and BR-3 (line merge differing from git merge-file on repeated lines). Reviewed by cli.build. Signed commits are read by clients from 0.20.0 to 0.26.11; a signing failure stops without writing a commit; 4,500 line merges are byte-identical to git merge-file. BR-2 and BR-3 closed. Open: BR-8 (a failed signing leaves two unreferenced objects).

*Source: <https://cli.sgit.ai/builds/0-26-10.html> · generated from the same content as the page, so the two cannot drift.*

---
# sgit-ai 0.26.10

```text
┌─ sgit-ai 0.26.10 ── dev build ── 28 Oct 2026, 16:30 UTC ────────────────────────
│ tag v0.26.10 = c24cf4b1 (dev) · PyPI package == tag
│ new     commit -S · write -S · vault tag create -s · sgit.gpgSign · --no-gpg-sign
│ fixed   BR-2, BR-3: the line differ is a port of Git's xdiff, with the indent heuristic
│ vs git  4,500 line merges byte-identical to git merge-file · blame 25/25 · renames 90/90
│ compat  signed commits read by 0.20.0 · 0.24.0 · 0.26.0 · 0.26.6 · 0.26.11 ✓
│ open    BR-8 (low) · BR-5, BR-6, BR-7 (0.26.8, unchanged) · W-1 (answered, not tested)
│ maturity  #########-  good
└──────────────────────────────────────────────────────────────────────────────────
```

## What changed {#new}

### Signing with your own key

```text
$ sgit commit -S -m "msg"                  # or -S<key>; --no-gpg-sign wins
$ sgit write -S notes.md …                 # a signed single-file commit
$ sgit vault tag create v1 -s              # or -u KEY
$ git config --global sgit.gpgSign true    # sign by default
$ sgit history log --show-signature
```

- **Off by default.** Switch on with `sgit.gpgSign = true`. Git's own `commit.gpgSign` is **deliberately not read**, so a Git setup does not start signing vault commits.
- **Key and format from your global Git config:** `user.signingKey`, `gpg.format` (`ssh` or `openpgp`; `x509` is refused), `gpg.ssh.program`, `gpg.program`.
- **Who signs:** an unencrypted ed25519 key in the process; everything else through `ssh-keygen -Y sign` or `gpg`.
- **Also signed when on:** merge commits made by `pull` and `branch merge`, `history revert --as-commit`, `vault ignore --apply`.
- **A signing failure stops the commit** and says how to commit without a signature.

### The line differ is Git's (BR-2, BR-3)

- `Vault__Line_Diff` is now a port of Git's xdiff (the pre-pass that sets lines aside, `xdl_split` and its cost heuristics), and `compact` gains Git's indent heuristic where Git uses it.
- **What changes for users:** a few merges that used to be clean now stop with markers, exactly where `git merge-file` stops. The patch text of some diffs, the boundaries of some `commit -p` hunks and blame on repeated lines move to Git's placement.

## Compatibility {#compat}

- **No gate, no new minimum client, no format change for a vault that nobody signs in.** An unsigned commit is stored as before.
- **Old clients and CLI-signed commits:** a vault with four commits signed by the CLI (SSH and OpenPGP) among six others was cloned by 0.20.0, 0.24.0, 0.26.0, 0.26.6 and 0.26.11. Each: fsck ok, 10 of 10 clone signatures verified, a commit on top, a push.
- **Old vaults** made by 0.20.0, 0.24.0 and 0.26.0 (normal and pack) open in 0.26.11, take a commit and a push, and the old client pulls it back.
- **The web UI** (W-1): the CLI team states that the web UI never verifies commit signatures and ignores members it does not know. **I could not test it.** If that holds, W-1 is answered; ask the web UI team to confirm with one signed vault before 0.27.0.

## Review by cli.build {#review}

**Verdict: good. BR-2 and BR-3 are closed.**

```text
┌─ checks on the PyPI packages 0.26.10 and 0.26.11 ────────────────────────────────
│ ✓     package == tag (0.26.11: only the version file differs)
│ ✓     5,623 unit+security tests pass at v0.26.11 (39 skipped)
│ ✓     the 19 end-to-end checks pass (0.26.9, 0.26.11)
│ ✓ F1  line merge vs git merge-file: 3 runs × 1,500 merges (merge, merge, diff3): all identical
│       (0.26.5 to 0.26.8: 25 clean where Git conflicts, 300+ other differences)
│ ✓ H1  blame 25/25 · grep 120/120 · log -S/-G 40/40 · renames 90/90, re-run on 0.26.11
│ ✓ S1  -S, -S<key>, sgit.gpgSign, --no-gpg-sign, commit.gpgSign ignored: as claimed
│ ✓ S2  five failures (missing key, x509, unknown gpg key, "-evil" as a key, no key): rc 1, tip unchanged, no commit object
│ ✓ S3  signed commits read by five older clients; a tampered signature is bad
│ ✓ S4  vaults of 0.20.0 · 0.24.0 · 0.26.0, plain and pack, open and round-trip
└──────────────────────────────────────────────────────────────────────────────────
```

### BR-8 (low): a failed signing says "nothing was written", but two objects were {#br-8}

- On each failed `commit -S`, the blob and the tree are already written; the commit object and the ref are not. The object count rose by 2 per failure (3 on a success), five failures in a row left ten unreferenced objects.
- They are harmless (fsck is clean) but the message is not exact. Either say "no commit was made", or sign before storing the tree. The error also repeats its prefix: `gpg: gpg: signing failed: No secret key`.

### Also noted

- **Not tested:** passphrase-protected keys, `ssh-keygen` as the signer (not installed on the test machine), certificates and FIDO keys, merge and revert signing, `vault tag create -s`.
- **`sgit check fsck` ignores `--vault PATH`** and looks in the current folder (0.26.8 too).

*Scripts: `diff_history.py`, `fuzz_line_merge.py`, `sig_tamper.py`, `xsign.py`, `legacy_vault.py`. Results: `results/fuzz_line_merge_0.26.11.txt`, `results/signing_cli_0.26.11.txt`, `results/diff_history_0.26.11_seeds_1-8_no-renames.txt`, `results/suite-v0.26.11.txt`. All builds: [the builds page](../builds/index.md).*

---

*[Site index for agents](../llms.txt) · [HTML version](https://cli.sgit.ai/builds/0-26-10.html)*
