Install
One command:
curl -fsSL https://dxcli.com/install.sh | bash
Or download a tarball for your platform and install manually:
tar xzf dx-0.7.0-linux-amd64.tar.gz
bash dx-0.7.0/install.sh
Available: linux-amd64 · darwin-arm64 · darwin-amd64 · windows-amd64
Then enable in any git repo:
cd my-project
dx enable
That's it. Make a commit and a session appears.
Commands
dx enable # Install post-commit hook in current repo
dx disable # Remove hook from current repo
dx init # Create a .dx config file with defaults
dx snap [uuid] # Save current Claude session (aliases: slap, yoink)
dx resume [id] # Resume a saved session (by number or uuid)
dx ui # Open session viewer in browser
dx log # Show recent sessions in terminal
dx log -a # Show all sessions
dx log -r # Filter to current repo
dx log -n 50 # Show last 50 sessions
dx sync setup # One-step cross-device setup (auto-detects gh CLI)
dx sync push [dst] # Push sessions to a private GitHub repo, local path, or rsync remote
dx sync pull [src] # Pull and merge sessions from the same
Snap & Resume
Save your current interactive Claude session at any point:
dx snap
# => Snapped! Session d29c9dca-4f49-459a-9a01-7241213d3db0 (27 messages)
# repo: my-project
# branch: main
# commit: b56e1a6
# resume: claude --resume d29c9dca-4f49-459a-9a01-7241213d3db0
Resume from any checkout of the same repo — even across different clones or from WSL when the session was created on Windows:
dx resume
# => Recent sessions for my-project:
# * [1] 5m ago b56e1a6 claude main d29c9dca...
# [2] 1h ago 463be4a claude feature-x 463be4ab...
#
# => Use: dx resume <number> or dx resume <uuid>
dx resume 1
# => Resuming session d29c9dca-4f49-459a-9a01-7241213d3db0...
Running dx resume with no arguments opens an interactive picker with search, arrow-key navigation, and keyboard shortcuts:
- Ctrl+A — toggle between current repo and all projects
- Ctrl+B — toggle branch badge and folder paths
- Ctrl+R — rename the selected session (persisted across invocations)
- Type to search by branch, commit, agent, folder, or custom name
- Tab toggles between search and list focus
If the session was created on a commit ahead of your current checkout, dx warns you before resuming.
Aliases: dx slap and dx yoink do the same as dx snap. Aliases: dx hop and dx zap do the same as dx resume.
Session Viewer
dx ui
Opens a local web viewer showing all your sessions — both auto-created (from commits) and manually snapped. Click any session with a chat icon to see the full Claude conversation with messages, thinking blocks, and tool calls. Filter by repo, agent, or type.
Supported Agents
| Agent | Binary | Session resume | Status |
|---|---|---|---|
| Claude Code | claude |
claude --resume (deterministic UUID, interactive picker) |
✅ Tested |
| Gemini CLI | gemini |
gemini --resume (search by commit slug) |
🚧 Untested |
| Cursor Agent | agent |
agent resume or agent --resume="<id>" |
🚧 Untested |
| OpenCode | opencode |
opencode run -s "<slug>" |
🚧 Untested |
| OpenAI Codex | codex |
codex resume [ID] |
🚧 Untested |
| GitHub Copilot CLI | gh copilot / copilot |
gh copilot --resume |
🚧 Untested |
By default, only claude is enabled. Other agents have hook scripts but are not yet tested. Configure via .dx file or DX_AGENTS env var. Missing binaries are silently skipped.
Configuration
.dx file
Run dx init to create one, or add it manually to your repo root:
# .dx
agents=claude gemini
# claude_args=--model opus
# gemini_args=
# cursor_args=--cloud
# opencode_args=
# codex_args=
# copilot_args=
Environment variable override
DX_AGENTS overrides the .dx file:
DX_AGENTS="gemini" git commit -m "test"
Per-agent args via env: DX_CLAUDE_ARGS, DX_GEMINI_ARGS, etc.
Priority: DX_AGENTS env var > .dx file > default (claude).
Sync
Keep your snapped sessions in sync across machines — laptop, Mac mini, workstation. dx uses a private git repo you already own as the transport, so there's no server to run, no account to create, and no ongoing cost. Since it's git, sync is store-and-forward: push while the other device is offline, pull whenever it comes back online.
One-step setup (recommended)
On each device, run:
dx sync setup
If you have the gh CLI installed and logged in, dx auto-creates a private <you>/dx-sessions repo on the first device and offers to reuse it on the others:
# Device 1 (laptop)
$ dx sync setup
=> Detected gh CLI logged in as @alice
? Create private repo github.com/alice/dx-sessions for sync? [Y/n] Y
=> Created github.com/alice/dx-sessions (private)
=> Saved sync target to ~/.dx/config
=> Done.
# Device 2 (Mac mini), same GitHub account
$ dx sync setup
=> Detected gh CLI logged in as @alice
Found existing repo github.com/alice/dx-sessions
? Sync from it? [Y/n] Y
=> Fetching existing sessions...
=> Saved sync target to ~/.dx/config
=> Done.
From then on, on any device:
dx sync push # upload local sessions
dx sync pull # download remote sessions and merge
Without gh — any git URL
If you don't have gh, dx sync setup asks for a git URL. Any private git repo you can push to works — GitHub, GitLab, Bitbucket, Codeberg, Gitea, self-hosted. Paste either form:
https://github.com/you/dx-sessions.git
git@github.com:you/dx-sessions.git
Auth uses whatever you already have set up — SSH keys, credential helpers, Keychain, Windows Credential Manager, or a PAT. dx doesn't manage credentials itself.
Cross-device walkthrough
# On the laptop
dx snap # save the current Claude session
dx sync push # upload it
# Later, on the Mac mini
dx sync pull # fetch and merge
dx resume # picker shows the session — hit Enter to resume
Conflicts and merges
When two devices push independently, dx fetches and re-integrates remote changes before committing, then retries the push. Merges are non-destructive:
- Session list — unioned by UUID; both devices' sessions are kept.
- Names — remote wins on TSV conflict (last push wins).
- Blobs — UUID-named, never collide; existing local blobs are never overwritten.
- Drops —
dx dropwrites a tombstone that propagates to other devices on the next pull, removing the session there too.
Target resolution
dx picks the sync target in this order (first match wins):
- Explicit arg:
dx sync push <target> DX_SYNCenvironment variablesync=<url>in~/.dx/config(written bydx sync setup)sync=<path>in the current repo's.dxconfig
Alternative targets (no git)
If you'd rather not use git, dx sync push|pull still works with:
dx sync push /mnt/backup # local path (USB, NAS, shared folder)
dx sync push user@host:~/dx-data # rsync over SSH
You can also point DX_SYNC at a folder synced by iCloud, Dropbox, or Syncthing — those services handle the transport, dx handles the merge.
Security notes
The repo is private, TLS in transit, and encrypted at rest by your git host. dx doesn't add client-side encryption, so sessions are readable by anyone with repo access (including, in principle, the git host's staff). For most threat models this is fine; if you need stronger guarantees, host on your own server or wrap blobs in age or gpg before snapping.
How It Works
A git post-commit hook runs after every commit. It:
- Extracts the commit message and hash
- Generates a slug:
fix-login-redirect-bug-a1b2c3d - Launches each configured agent in the background with the slug as prompt
- Logs the session to
~/.dx/data/sessions.tsv
dx snap finds the most recently modified Claude session file in ~/.claude/projects/ and records it. dx ui reads the session data and Claude's JSONL conversation files, builds a self-contained HTML viewer, and opens it in your browser.
The hook never blocks git. It skips during rebase, merge, and other non-interactive operations.
Requirements
gitandbash(always required)node(required fordx uionly)
Platform Support
| Platform | Status |
|---|---|
| macOS | Supported |
| Linux | Supported |
| Windows (Git Bash / MSYS2) | Supported |
| WSL | Supported |
Uninstall
Remove from a repo:
dx disable
Remove globally:
rm -rf ~/.dx ~/.local/bin/dx
If you added the PATH export to ~/.bashrc, remove that line too.