Per-project session persistence for AI CLI tools
Project description
ai-session-manager
Per-project session persistence for AI CLI tools.
ai-session-manager adds automatic project-scoped resume behavior to supported AI CLIs so you can leave a project and come back without manually reopening the right conversation.
Works on Linux, macOS, and Windows.
[!WARNING] This tool renames installed CLI binaries and replaces them with wrapper scripts. Use it at your own risk, and make sure you understand how to restore the original binaries with
ai-session-manager teardown.
Why
Most AI CLIs support sessions, but they do not all resume the same way and they do not all make project-scoped resume automatic. This project adds one consistent wrapper layer across tools.
Today it supports:
| Tool | Auto-resume behavior |
|---|---|
agy |
Starts normally on first run, then stores/discovers a native conversation ID and resumes with agy --conversation <id> |
copilot |
Stores a stable session UUID and launches copilot --session-id <uuid> |
claude |
Stores a managed session UUID, starts with claude --session-id <uuid>, then resumes with claude -r <uuid> |
gemini |
Stores a managed session UUID, starts with gemini --session-id <uuid>, then resumes with gemini --resume <uuid> |
codex |
Starts normally on first run, then stores/discovers the native session ID and resumes with codex resume <id> |
Project-scoped state lives in:
.ai-session-manager/inside the project root, whether it is a git repo or a plain folder
Existing state is still recognized and migrated from:
.git/ai-session-manager/
Copilot legacy state is also recognized and migrated from:
.git/copilot-session.copilot-session
Requirements
- Python 3.8+
- One or more supported CLIs installed: Antigravity, Copilot, Claude Code, Gemini CLI, or Codex CLI
Installation
pip install --editable ~/ai-session-manager
Once published:
pip install ai-session-manager
Setup
Install wrappers for every supported tool found in PATH:
ai-session-manager setup
Or target specific tools:
ai-session-manager setup agy copilot claude gemini codex
Each selected binary is renamed to <tool>-real and replaced with a thin Python wrapper. From that point on, keep using the original command name.
Usage
Copilot
cd ~/my-project
copilot
# [ai-session-manager] New session 4f1a2b3c-... (my-project)
cd ~/my-project
copilot
# [ai-session-manager] Resuming session 4f1a2b3c-... (my-project)
AGY
agy
# [ai-session-manager] Starting new Antigravity CLI session (my-project)
agy
# [ai-session-manager] Resuming session 123e4567-... (my-project)
Claude / Gemini
claude
# [ai-session-manager] New session 4f1a2b3c-... (my-project)
claude
# [ai-session-manager] Resuming session 4f1a2b3c-... (my-project)
gemini
# [ai-session-manager] New session 7b2f8c1d-... (my-project)
gemini
# [ai-session-manager] Resuming session 7b2f8c1d-... (my-project)
Codex
codex
# [ai-session-manager] Starting new Codex session (my-project)
codex
# [ai-session-manager] Resuming session 019e94b3-... (my-project)
Supported tools are still fully usable with their own native session commands. If you pass an explicit resume or session-management flag/subcommand, the wrapper gets out of the way.
For example:
agy --conversation 123e4567-e89b-12d3-a456-426614174000
copilot --resume
claude -r my-session
gemini --list-sessions
codex resume --last
Start fresh in the current project
ai-session-manager reset
Or reset one tool only:
ai-session-manager reset claude
Commands
| Command | Description |
|---|---|
ai-session-manager setup [tools...] |
Install wrappers for all detected or selected tools |
ai-session-manager teardown [tools...] |
Remove wrappers and restore original binaries |
ai-session-manager status [tools...] |
Show platform, binary paths, and state files |
ai-session-manager reset [tools...] |
Delete persisted wrapper state for the current project |
ai-session-manager session convert --from <tool> --to <target> |
Rebuild a supported source session as a resumable session for a proven target tool |
State layout
project root:
.ai-session-manager/
copilot.json
claude.json
codex.json
gemini.json
agy.json
Copilot, Claude, and Gemini store an exact managed session identifier in their state files from the first launch.
AGY and Codex store the tool's own native conversation/session identifier once the wrapper can discover it from local history after a successful run. If no exact native ID is available yet, the wrapper falls back to the tool's native resume-latest/new-session behavior until it can record one.
Session migration
ai-session-manager currently supports these proven target combinations:
| From | To | Status |
|---|---|---|
copilot |
claude |
Supported |
codex |
claude |
Supported |
gemini |
claude |
Supported |
agy |
claude |
Supported |
claude |
gemini |
Supported |
copilot |
gemini |
Supported |
codex |
gemini |
Supported |
gemini |
gemini |
Supported |
agy |
gemini |
Supported |
Example:
ai-session-manager session convert --from copilot --to claude
ai-session-manager session convert --from claude --to gemini --source-session <claude-session-id>
For copilot, the converter can read the current project's stored source session ID from .ai-session-manager/copilot.json.
For claude, codex, gemini, and agy, pass the source session explicitly:
ai-session-manager session convert --from claude --to gemini --source-session <claude-session-id>
ai-session-manager session convert --from codex --to claude --source-session <codex-session-id>
ai-session-manager session convert --from gemini --to claude --source-session <gemini-session-id>
ai-session-manager session convert --from agy --to claude --source-session <agy-brain-id-or-transcript-path>
The converter rebuilds the visible user/assistant chat history for the chosen proven target:
claudetarget sessions are written to~/.claude/projects/...and futureclaudelaunches resume them withclaude -r <session-id>.geminitarget sessions are written to.ai-session-manager/gemini-session-<id>.jsonlin the project and futuregeminilaunches resume them with--session-file.
Important limits:
- Only visible chat history is transferred today.
- Source-tool calls, tool outputs, attachments, checkpoints, and other hidden internal state are not portable to other targets.
- Unsupported tool pairs fail explicitly instead of silently degrading to a summary handoff.
Platform details
| Linux | macOS | Windows | |
|---|---|---|---|
| Wrapper file | tool name (shebang script) | tool name (shebang script) | tool .cmd wrapper |
| Real binary | <tool>-real |
<tool>-real |
<tool>-real.exe or <tool>-real.cmd |
| Process launch | os.execv (true replace) |
os.execv (true replace) |
subprocess + exit code |
Project structure
ai-session-manager/
├── pyproject.toml
├── README.md
└── src/
├── ai_session_manager/
│ ├── wrapper.py
│ └── cli.py
Reinstalling a tool CLI
If a wrapped tool is manually reinstalled and overwrites the wrapper, run setup again:
ai-session-manager setup copilot
Uninstall
ai-session-manager teardown
pip uninstall ai-session-manager
Publishing to PyPI
This repository includes a GitHub Actions workflow at .github/workflows/publish-pypi.yml.
What it does:
- runs
pytest -q - builds the package with
python -m build - checks the artifacts with
python -m twine check dist/* - publishes to PyPI
Recommended setup: PyPI trusted publishing
Configure PyPI to trust this GitHub repository and workflow:
- PyPI project:
ai-session-manager - owner/repo:
DrFatihTekin/ai-session-manager - workflow file:
publish-pypi.yml - environment:
pypi
The workflow uses GitHub OIDC via pypa/gh-action-pypi-publish, so no PyPI API token needs to be stored in GitHub secrets once trusted publishing is configured on the PyPI side.
How to trigger a publish
Two triggers are enabled:
- Release publish: publish a GitHub Release from a tag that points to a commit already contained in
main - Manual dispatch: run the workflow from the Actions tab for a revision already contained in
main
The workflow explicitly checks that the revision being published is contained in origin/main, so it will fail instead of publishing a feature branch by mistake.
Typical release flow:
git checkout main
git pull --ff-only origin main
git tag v0.1.0
git push origin main --tags
Then publish a GitHub Release for that tag.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ai_session_manager-0.1.4.tar.gz.
File metadata
- Download URL: ai_session_manager-0.1.4.tar.gz
- Upload date:
- Size: 23.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f8123abfa8cf476619dfac5c3bb61e010e4fc0bdfa7ec7f525aebcb55c25782d
|
|
| MD5 |
cb44153d57809e372ab05fb4504676d5
|
|
| BLAKE2b-256 |
3c5bf0413378f47249411a2d57d54d9a0d33e22993162a5ee2e5bd721c71845f
|
Provenance
The following attestation bundles were made for ai_session_manager-0.1.4.tar.gz:
Publisher:
publish-pypi.yml on DrFatihTekin/ai-session-manager
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ai_session_manager-0.1.4.tar.gz -
Subject digest:
f8123abfa8cf476619dfac5c3bb61e010e4fc0bdfa7ec7f525aebcb55c25782d - Sigstore transparency entry: 1726070098
- Sigstore integration time:
-
Permalink:
DrFatihTekin/ai-session-manager@a1a5f982733e074c31939c53a982d19e1f87e943 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/DrFatihTekin
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@a1a5f982733e074c31939c53a982d19e1f87e943 -
Trigger Event:
release
-
Statement type:
File details
Details for the file ai_session_manager-0.1.4-py3-none-any.whl.
File metadata
- Download URL: ai_session_manager-0.1.4-py3-none-any.whl
- Upload date:
- Size: 18.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7e411847f737282f999411637f76ecd640e016657c087fb8eba0081233e96cd
|
|
| MD5 |
65de33aefcfd2e931b091b93d6151a8c
|
|
| BLAKE2b-256 |
9ea20de847bde26e09e3f040ecf35756849b52caf334cd0d11d903dd5c339312
|
Provenance
The following attestation bundles were made for ai_session_manager-0.1.4-py3-none-any.whl:
Publisher:
publish-pypi.yml on DrFatihTekin/ai-session-manager
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ai_session_manager-0.1.4-py3-none-any.whl -
Subject digest:
a7e411847f737282f999411637f76ecd640e016657c087fb8eba0081233e96cd - Sigstore transparency entry: 1726070189
- Sigstore integration time:
-
Permalink:
DrFatihTekin/ai-session-manager@a1a5f982733e074c31939c53a982d19e1f87e943 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/DrFatihTekin
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@a1a5f982733e074c31939c53a982d19e1f87e943 -
Trigger Event:
release
-
Statement type: