git-memento
git-memento is a Git extension that records the AI coding session used to produce a commit.
It runs a commit and then stores a cleaned markdown conversation as a git note on the new commit.
Goal
- Create commits with normal Git flow (
-mor editor). - Attach the AI session trace to the commit (
git notes). - Keep provider support extensible (Codex first, others later).
- Produce human-readable markdown notes.
Command
Initialize per-repository memento settings:
git memento init git memento init codex git memento init claude
init stores configuration in local git metadata (.git/config) under memento.*.
git memento commit <session-id> -m "Normal commit message" git memento commit <session-id> -m "Subject line" -m "Body paragraph" git memento commit <session-id> --summary-skill default -m "Subject line" git memento amend -m "Amended subject" git memento amend <new-session-id> -m "Amended subject" -m "Amended body" git memento amend <new-session-id> --summary-skill session-summary-default -m "Amended subject" git memento audit --range main..HEAD --strict git memento doctor
Or:
git memento commit <session-id>
You can pass -m multiple times, and each value is forwarded to git commit in order.
When -m is omitted, git commit opens your default editor.
amend runs git commit --amend.
- Without a session id, it copies the note(s) from the previous HEAD onto the amended commit.
- With a session id, it copies previous note(s) and appends the new fetched session as an additional session entry.
- A single commit note can contain sessions from different AI providers.
--summary-skill <skill|default> (for commit and amend <session-id>) changes note behavior:
- The default notes ref (
refs/notes/commits) stores a summary record instead of the full transcript. - The full session is stored in
refs/notes/memento-full-audit. - The CLI prints the generated summary and asks for confirmation.
- If rejected, you must provide a prompt to regenerate.
defaultmaps to the repository skill atskills/session-summary-default/SKILL.md.- The default summary skill is always applied as a baseline; if a user-provided summary skill conflicts with it, user-provided instructions take precedence.
You can verify both notes after a summary run:
git notes show <commit-hash> git notes --ref refs/notes/memento-full-audit show <commit-hash>
Share notes with the repository remote (default: origin):
git memento share-notes git memento share-notes upstream
This pushes refs/notes/* and configures local remote.<name>.fetch so notes can be fetched by teammates.
Push your branch and sync notes to the same remote in one command (default: origin):
git memento push git memento push upstream
This runs git push <remote> and then performs the same notes sync as share-notes.
Sync and merge notes from a remote safely (default remote: origin, default strategy: cat_sort_uniq):
git memento notes-sync git memento notes-sync upstream git memento notes-sync upstream --strategy union
This command:
- Ensures notes fetch mapping is configured.
- Creates backup refs under
refs/notes/memento-backups/<timestamp>/.... - Fetches remote notes into
refs/notes/remote/<remote>/*. - Merges remote notes into local notes and pushes synced notes back to the remote.
- Syncs both
refs/notes/commitsandrefs/notes/memento-full-audit.
Configure automatic note carry-over for rewritten commits (rebase / commit --amend):
git memento notes-rewrite-setup
This sets local git config:
notes.rewriteRef=refs/notes/*notes.rewriteMode=concatenatenotes.rewrite.rebase=truenotes.rewrite.amend=true
Carry notes from a rewritten range (for squash/rewrite flows) onto a new target commit:
git memento notes-carry --onto <new-commit> --from-range <base>..<head>
This reads notes from commits in <base>..<head> and appends provenance blocks to <new-commit>.
It carries both refs/notes/commits and refs/notes/memento-full-audit.
Audit note coverage and note metadata in a commit range:
git memento audit --range main..HEAD git memento audit --range origin/main..HEAD --strict --format json
- Reports commits with missing notes (
missing-note <sha>). - Validates note metadata markers (
- Provider:and- Session ID:). - In
--strictmode, invalid note structure fails the command.
Run repository diagnostics for provider config, notes refs, and remote sync posture:
git memento doctor git memento doctor upstream --format json
Show command help:
git memento helpShow installed tool version (major.minor + commit metadata when available):
git memento --version
Provider Configuration
Provider defaults can come from env vars, and init persists the selected provider + values in local git config:
MEMENTO_AI_PROVIDER(default:codex)MEMENTO_CODEX_BIN(default:codex)MEMENTO_CODEX_GET_ARGS(default:sessions get {id} --json)MEMENTO_CODEX_LIST_ARGS(default:sessions list --json)MEMENTO_CODEX_SUMMARY_BIN(default:codex)MEMENTO_CODEX_SUMMARY_ARGS(default:exec -c skill.effective_path={effectiveSkillPath} -c skill.default_path={defaultSkillPath} -c skill.user_path={userSkillPath} "{prompt}")MEMENTO_CLAUDE_BIN(default:claude)MEMENTO_CLAUDE_GET_ARGS(default:sessions get {id} --json)MEMENTO_CLAUDE_LIST_ARGS(default:sessions list --json)MEMENTO_CLAUDE_SUMMARY_BIN(default:claude)MEMENTO_CLAUDE_SUMMARY_ARGS(default:-p --append-system-prompt "Skill paths: effective={effectiveSkillPath}; default={defaultSkillPath}; user={userSkillPath}. Prefer user skill when provided." "{prompt}")
Summary args template placeholders:
{prompt}: generated summary prompt{sessionId}: session id{skill}: user skill name orsession-summary-default{defaultSkillPath}: default skill file path (skills/session-summary-default/SKILL.md){userSkillPath}: user skill file path (empty when--summary-skill default){effectiveSkillPath}: user skill path when provided, otherwise default skill path
Security behavior:
- Session transcript is treated as untrusted data.
- Summary prompt explicitly instructs the model not to follow instructions embedded in transcript content.
Set MEMENTO_AI_PROVIDER=claude to use Claude Code.
Runtime behavior:
- If the repository is not configured yet,
commit,amend <session-id>,push,share-notes,notes-sync,notes-rewrite-setup, andnotes-carryfail with a message to rungit memento initfirst. - Stored git metadata keys include:
memento.providermemento.codex.bin,memento.codex.getArgs,memento.codex.listArgs,memento.codex.summary.bin,memento.codex.summary.argsmemento.claude.bin,memento.claude.getArgs,memento.claude.listArgs,memento.claude.summary.bin,memento.claude.summary.args
If a session id is not found, git-memento asks Codex for available sessions and prints them.
Build (AOT)
Requires .NET SDK 10 and native toolchain dependencies for NativeAOT.
macOS
dotnet publish src/GitMemento.Cli/GitMemento.Cli.fsproj -c Release -r osx-arm64 -p:PublishAot=true
Linux
dotnet publish src/GitMemento.Cli/GitMemento.Cli.fsproj -c Release -r linux-x64 -p:PublishAot=true
Windows (PowerShell)
dotnet publish src/GitMemento.Cli/GitMemento.Cli.fsproj -c Release -r win-x64 -p:PublishAot=true
Local Install as Git Tool
Git discovers commands named git-<name> in PATH.
- Publish for your platform.
- Copy the produced executable to a directory in your
PATH. - Ensure the binary name is
git-memento(orgit-memento.exeon Windows).
Then run:
git memento commit <session-id> -m "message"
Curl Install
Install from latest GitHub release:
curl -fsSL https://raw.githubusercontent.com/mandel-macaque/memento/main/install.sh | shRelease Automation
- Release assets are built with NativeAOT (
PublishAot=true) and packaged as a single executable per platform. - If the workflow runs from a tag push (for example
v1.2.3), that tag is used as the GitHub release tag/name. - If the workflow runs from
mainwithout a tag, the release tag becomes<Version>-<shortSha>(for example1.0.0-a1b2c3d4). install.shalways downloads fromreleases/latest, so the installer follows the latest published GitHub release.
Install Script CI Coverage
CI runs install smoke tests on Linux, macOS, and Windows that verify:
install.shdownloads the latest release asset for the current OS/architecture.- The binary is installed for the current user into the configured install directory.
git memento --versionandgit memento helpboth execute after installation.
Test
dotnet test GitMemento.slnx
npm run test:jsCommit Note Comments + CI Gate (GitHub Action)
This repository includes a reusable marketplace action with three modes:
mode: comment(default): readsgit notescreated bygit-mementoand posts a commit comment.mode: gate: runsgit memento auditas a CI gate and fails if note coverage checks fail.git-mementomust already be installed in the job.mode: merge-carry: on merged pull requests, carries notes from PR commits onto the merge commit and pushesrefs/notes/*.
Action definition:
action.ymlat repository root.install/action.ymlfor reusable git-memento installation.- Renderer source:
src/note-comment-renderer.ts - Runtime artifact committed for marketplace consumers:
dist/note-comment-renderer.js
Example workflow:
name: memento-note-comments on: push: pull_request: types: [opened, synchronize, reopened, labeled, unlabeled] permissions: contents: write pull-requests: read jobs: comment-memento-notes: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: mandel-macaque/memento@v1 with: mode: comment github-token: ${{ secrets.GITHUB_TOKEN }}
Inputs:
github-token(default:${{ github.token }})mode(default:comment) -comment,gate, ormerge-carrynotes-fetch-refspec(default:refs/notes/*:refs/notes/*)max-comment-length(default:65000)audit-range(optional, gate mode)base-ref(optional, gate mode pull request inference)strict(default:true, gate mode)ignore-label(default:ignore-notes, gate mode)- If present on a pull request, gate note checks are skipped and a PR comment with
Notes ignoredis posted.
- If present on a pull request, gate note checks are skipped and a PR comment with
carry-onto(optional, merge-carry mode) - target commit SHA. Defaults topull_request.merge_commit_sha.carry-range(optional, merge-carry mode) - explicit<base>..<head>source range.carry-base-sha(optional, merge-carry mode) - base SHA used whencarry-rangeis empty.carry-head-sha(optional, merge-carry mode) - head SHA used whencarry-rangeis empty.carry-provider(default:codex, merge-carry mode) - provider value set in local git config fornotes-carry.
Installer action inputs:
memento-repo(default:mandel-macaque/memento, release asset source)install-dir(default:${{ runner.temp }}/git-memento-bin)verify(default:true)
CI gate example:
name: memento-note-gate on: pull_request: types: [opened, synchronize, reopened, labeled, unlabeled] permissions: contents: read issues: write pull-requests: write jobs: enforce-memento-notes: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: mandel-macaque/memento/install@v1 with: memento-repo: mandel-macaque/memento - uses: mandel-macaque/memento@v1 with: mode: gate strict: "true" ignore-label: "ignore-notes"
Merge-carry example:
name: memento-notes-merge-carry on: pull_request: types: [closed] permissions: contents: write jobs: carry-notes-to-merge-commit: if: github.event.pull_request.merged == true runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: mandel-macaque/memento/install@v1 with: memento-repo: mandel-macaque/memento - uses: mandel-macaque/memento@v1 with: mode: merge-carry
Installer action example:
- uses: mandel-macaque/memento/install@v1 with: memento-repo: mandel-macaque/memento
Local workflow in this repository:
.github/workflows/memento-note-comments.yml.github/workflows/memento-note-gate.yml.github/workflows/memento-notes-merge-carry.yml- Uses the public action with
mode: merge-carry. - Carries notes from PR source commits onto the merge commit.
- Pushes updated
refs/notes/*so merged commits keep note visibility in downstream checks.
- Uses the public action with
Publish This Action To GitHub Marketplace
- Build and commit the action renderer artifact:
npm ci npm run build:action git add src/note-comment-renderer.ts dist/note-comment-renderer.js
- Ensure
action.ymlandinstall/action.ymlare in the default branch and README documents usage. - Create and push a semantic version tag:
git tag -a v1.0.0 -m "Release GitHub Action v1.0.0"
git push origin v1.0.0
git tag -f v1 v1.0.0
git push -f origin v1- In GitHub, open your repository page:
Releases->Draft a new release-> choosev1.0.0-> publish.
- Open the
Marketplace(GitHub Store) publishing flow from the repository and submit listing metadata. - Keep the major tag (
v1) updated to the latest compatible release.
Notes
- Notes are written with
git notes add -f -m "<markdown>" <commit-hash>. - Multi-session notes use explicit delimiters:
<!-- git-memento-sessions:v1 --><!-- git-memento-note-version:1 --><!-- git-memento-session:start --><!-- git-memento-session:end -->
- Legacy single-session notes remain supported and are upgraded to the versioned multi-session envelope when amend needs to append a new session.
- Conversation markdown labels user messages with your git alias (
git config user.name) and assistant messages with provider name. - Serilog debug logs are enabled in
DEBUGbuilds.