ai-handoff 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. ai_handoff-0.1.0/.github/workflows/ci.yml +87 -0
  2. ai_handoff-0.1.0/.github/workflows/release.yml +61 -0
  3. ai_handoff-0.1.0/.gitignore +11 -0
  4. ai_handoff-0.1.0/LICENSE +21 -0
  5. ai_handoff-0.1.0/PKG-INFO +266 -0
  6. ai_handoff-0.1.0/README.md +238 -0
  7. ai_handoff-0.1.0/install.ps1 +138 -0
  8. ai_handoff-0.1.0/install.sh +152 -0
  9. ai_handoff-0.1.0/pyproject.toml +58 -0
  10. ai_handoff-0.1.0/src/ai_handoff/__init__.py +3 -0
  11. ai_handoff-0.1.0/src/ai_handoff/__main__.py +3 -0
  12. ai_handoff-0.1.0/src/ai_handoff/activity.py +69 -0
  13. ai_handoff-0.1.0/src/ai_handoff/cli.py +470 -0
  14. ai_handoff-0.1.0/src/ai_handoff/completion.py +334 -0
  15. ai_handoff-0.1.0/src/ai_handoff/context_file.py +115 -0
  16. ai_handoff-0.1.0/src/ai_handoff/diffing.py +30 -0
  17. ai_handoff-0.1.0/src/ai_handoff/errors.py +18 -0
  18. ai_handoff-0.1.0/src/ai_handoff/graph.py +65 -0
  19. ai_handoff-0.1.0/src/ai_handoff/hooks.py +235 -0
  20. ai_handoff-0.1.0/src/ai_handoff/i18n.py +92 -0
  21. ai_handoff-0.1.0/src/ai_handoff/integrations/__init__.py +107 -0
  22. ai_handoff-0.1.0/src/ai_handoff/integrations/clients.py +393 -0
  23. ai_handoff-0.1.0/src/ai_handoff/integrations/files.py +135 -0
  24. ai_handoff-0.1.0/src/ai_handoff/integrations/parts.py +425 -0
  25. ai_handoff-0.1.0/src/ai_handoff/locales.py +413 -0
  26. ai_handoff-0.1.0/src/ai_handoff/paths.py +32 -0
  27. ai_handoff-0.1.0/src/ai_handoff/project.py +176 -0
  28. ai_handoff-0.1.0/src/ai_handoff/redact.py +49 -0
  29. ai_handoff-0.1.0/src/ai_handoff/server.py +132 -0
  30. ai_handoff-0.1.0/src/ai_handoff/setup_flow.py +192 -0
  31. ai_handoff-0.1.0/src/ai_handoff/store.py +434 -0
  32. ai_handoff-0.1.0/src/ai_handoff/ui.py +201 -0
  33. ai_handoff-0.1.0/src/ai_handoff/views.py +397 -0
  34. ai_handoff-0.1.0/tests/conftest.py +63 -0
  35. ai_handoff-0.1.0/tests/test_cli.py +175 -0
  36. ai_handoff-0.1.0/tests/test_completion.py +137 -0
  37. ai_handoff-0.1.0/tests/test_context_file.py +86 -0
  38. ai_handoff-0.1.0/tests/test_hooks.py +179 -0
  39. ai_handoff-0.1.0/tests/test_i18n.py +96 -0
  40. ai_handoff-0.1.0/tests/test_integrations.py +382 -0
  41. ai_handoff-0.1.0/tests/test_project.py +110 -0
  42. ai_handoff-0.1.0/tests/test_redact.py +61 -0
  43. ai_handoff-0.1.0/tests/test_server.py +102 -0
  44. ai_handoff-0.1.0/tests/test_store.py +277 -0
  45. ai_handoff-0.1.0/tests/test_views.py +270 -0
@@ -0,0 +1,87 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ workflow_call:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ lint:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v7
17
+ - uses: actions/setup-python@v7
18
+ with:
19
+ python-version: "3.14"
20
+ - run: python -m pip install ruff
21
+ - run: ruff check .
22
+ - run: ruff format --check .
23
+ - run: shellcheck install.sh
24
+
25
+ test:
26
+ name: test (${{ matrix.os }}, Python ${{ matrix.python }})
27
+ runs-on: ${{ matrix.os }}
28
+ strategy:
29
+ fail-fast: false
30
+ matrix:
31
+ os: [ubuntu-latest, macos-latest, windows-latest]
32
+ python: ["3.10", "3.12", "3.14"]
33
+ steps:
34
+ - uses: actions/checkout@v7
35
+ - uses: actions/setup-python@v7
36
+ with:
37
+ python-version: ${{ matrix.python }}
38
+ - run: python -m pip install -e ".[dev]"
39
+ - run: python -m pytest
40
+ - name: Smoke test the installed command
41
+ run: |
42
+ handoff --version
43
+ handoff setup --print-config
44
+
45
+ installer:
46
+ name: installer (${{ matrix.os }})
47
+ runs-on: ${{ matrix.os }}
48
+ strategy:
49
+ fail-fast: false
50
+ matrix:
51
+ os: [ubuntu-latest, macos-latest, windows-latest]
52
+ env:
53
+ HANDOFF_SOURCE: ${{ github.workspace }}
54
+ HANDOFF_NO_SETUP: "1"
55
+ steps:
56
+ - uses: actions/checkout@v7
57
+ - uses: actions/setup-python@v7
58
+ with:
59
+ python-version: "3.12"
60
+ - name: Install, upgrade and uninstall (sh)
61
+ if: runner.os != 'Windows'
62
+ run: |
63
+ # Runners already have ~/.local/bin on PATH; drop it so the profile update is exercised.
64
+ export PATH="$(printf '%s' "$PATH" | tr ':' '\n' | grep -vx "$HOME/.local/bin" | paste -sd: -)"
65
+ sh install.sh
66
+ "$HOME/.local/bin/handoff" --version
67
+ sh install.sh
68
+ test "$(cat ~/.bashrc ~/.bash_profile 2>/dev/null | grep -c 'Handoff installer')" = 1
69
+ sh install.sh --uninstall
70
+ test ! -e "$HOME/.local/bin/handoff"
71
+ ! cat ~/.bashrc ~/.bash_profile 2>/dev/null | grep -q 'Handoff installer'
72
+ - name: Install, upgrade and uninstall (Windows PowerShell)
73
+ if: runner.os == 'Windows'
74
+ shell: powershell
75
+ run: |
76
+ Get-Content -Raw install.ps1 | Invoke-Expression
77
+ & "$env:LOCALAPPDATA\handoff\bin\handoff.exe" --version
78
+ if ($LASTEXITCODE -ne 0) { exit 1 }
79
+ Get-Content -Raw install.ps1 | Invoke-Expression
80
+ $bin = "$env:LOCALAPPDATA\handoff\bin"
81
+ $userPath = (Get-Item 'HKCU:\Environment').GetValue('Path', '', 'DoNotExpandEnvironmentNames')
82
+ if (@($userPath -split ';' | Where-Object { $_ -eq $bin }).Count -ne 1) { throw 'PATH entry missing or duplicated' }
83
+ $env:HANDOFF_UNINSTALL = '1'
84
+ Get-Content -Raw install.ps1 | Invoke-Expression
85
+ if (Test-Path $bin) { throw 'bin folder still present' }
86
+ $userPath = (Get-Item 'HKCU:\Environment').GetValue('Path', '', 'DoNotExpandEnvironmentNames')
87
+ if (($userPath -split ';') -contains $bin) { throw 'PATH entry not removed' }
@@ -0,0 +1,61 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*.*.*"]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ ci:
12
+ uses: ./.github/workflows/ci.yml
13
+
14
+ build:
15
+ needs: ci
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v7
19
+ - uses: actions/setup-python@v7
20
+ with:
21
+ python-version: "3.14"
22
+ - name: Check that the tag matches the package version
23
+ run: |
24
+ version=$(python -c "import re,pathlib; print(re.search(r'__version__ = \"(.+?)\"', pathlib.Path('src/ai_handoff/__init__.py').read_text())[1])")
25
+ test "v$version" = "${GITHUB_REF_NAME}" || { echo "Tag ${GITHUB_REF_NAME} does not match version $version"; exit 1; }
26
+ - run: python -m pip install build
27
+ - run: python -m build
28
+ - uses: actions/upload-artifact@v7
29
+ with:
30
+ name: dist
31
+ path: dist/
32
+
33
+ publish-pypi:
34
+ needs: build
35
+ runs-on: ubuntu-latest
36
+ environment:
37
+ name: pypi
38
+ url: https://pypi.org/p/ai-handoff
39
+ permissions:
40
+ id-token: write # PyPI trusted publishing: no API token stored in the repository
41
+ steps:
42
+ - uses: actions/download-artifact@v8
43
+ with:
44
+ name: dist
45
+ path: dist/
46
+ - uses: pypa/gh-action-pypi-publish@release/v1
47
+
48
+ github-release:
49
+ needs: publish-pypi
50
+ runs-on: ubuntu-latest
51
+ permissions:
52
+ contents: write
53
+ steps:
54
+ - uses: actions/download-artifact@v8
55
+ with:
56
+ name: dist
57
+ path: dist/
58
+ - uses: softprops/action-gh-release@v3
59
+ with:
60
+ files: dist/*
61
+ generate_release_notes: true
@@ -0,0 +1,11 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .venv/
4
+ build/
5
+ dist/
6
+ *.egg-info/
7
+ .pytest_cache/
8
+ .ruff_cache/
9
+ .coverage
10
+ .handoff/
11
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 kdev1966
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,266 @@
1
+ Metadata-Version: 2.5
2
+ Name: ai-handoff
3
+ Version: 0.1.0
4
+ Summary: Shared, persistent memory that lets AI assistants hand work over to each other, through MCP.
5
+ Project-URL: Homepage, https://github.com/kdev1966/Handoff-CLI
6
+ Project-URL: Issues, https://github.com/kdev1966/Handoff-CLI/issues
7
+ Author: kdev1966
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: agents,ai,cli,handoff,mcp,memory,model-context-protocol
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: MacOS
15
+ Classifier: Operating System :: Microsoft :: Windows
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Topic :: Software Development
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: mcp<3,>=2.3
22
+ Requires-Dist: rich<16,>=13.7
23
+ Provides-Extra: dev
24
+ Requires-Dist: anyio>=4.9; extra == 'dev'
25
+ Requires-Dist: pytest>=8; extra == 'dev'
26
+ Requires-Dist: ruff>=0.15; extra == 'dev'
27
+ Description-Content-Type: text/markdown
28
+
29
+ # Handoff
30
+
31
+ [![CI](https://github.com/kdev1966/Handoff-CLI/actions/workflows/ci.yml/badge.svg)](https://github.com/kdev1966/Handoff-CLI/actions/workflows/ci.yml)
32
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
33
+
34
+ **Handoff** donne une mémoire persistante et partagée à vos assistants IA (Claude, GitHub Copilot, Cursor, Gemini, Codex…). Quand vous passez d'un outil à un autre sur un même projet, le suivant reprend là où le précédent s'est arrêté : stack technique, état actuel, prochaines actions.
35
+
36
+ Il fonctionne sous **Windows, macOS et Linux**, via le standard [MCP](https://modelcontextprotocol.io) et une CLI.
37
+
38
+ ## Fonctionnement
39
+
40
+ ```text
41
+ Claude / Copilot / Cursor / Gemini / Codex
42
+ │ MCP (stdio, local : aucun port réseau)
43
+ ▼
44
+ handoff serve ──┐
45
+ handoff save ──┼──► base SQLite locale (historique en ajout seul)
46
+ handoff show ──┘
47
+ │
48
+ ▼
49
+ <projet>/.handoff/context.md (vue générée, ignorée par git)
50
+ ```
51
+
52
+ - **En début de session**, la mémoire du projet est donnée à l'assistant : automatiquement par un hook quand l'outil le permet, sinon l'assistant l'obtient avec l'outil `memory_get`, comme le lui indique la consigne posée par `handoff setup`.
53
+ - **Avant de s'arrêter**, si le code a changé depuis la dernière passation, l'assistant est invité une fois à en enregistrer une (`memory_save`).
54
+ - Le projet est identifié par son **remote git** (`origin`). La mémoire suit donc le dépôt même si vous le déplacez ou le clonez à nouveau. Sans remote, c'est le chemin du dossier qui sert d'identifiant.
55
+ - Chaque passage de relais est **ajouté** à l'historique : rien n'est écrasé et vous pouvez revenir à un état antérieur.
56
+
57
+ ## Installation
58
+
59
+ Une seule commande, qui sert aussi à mettre à jour. Python 3.10 ou plus doit être installé.
60
+
61
+ **macOS / Linux :**
62
+
63
+ ```bash
64
+ curl -fsSL https://raw.githubusercontent.com/kdev1966/Handoff-CLI/main/install.sh | sh
65
+ ```
66
+
67
+ **Windows (PowerShell) :**
68
+
69
+ ```powershell
70
+ powershell -ExecutionPolicy ByPass -c "irm https://raw.githubusercontent.com/kdev1966/Handoff-CLI/main/install.ps1 | iex"
71
+ ```
72
+
73
+ Le script :
74
+ - installe Handoff dans un environnement virtuel privé, sans droits administrateur ni `sudo` ;
75
+ - ajoute la commande `handoff` à votre `PATH` ;
76
+ - à la première installation, vous propose deux modes :
77
+ 1. **Automatique** : tous les outils IA trouvés sont connectés avec les valeurs par défaut (lecture et enregistrement automatiques), sans autre question, et un récapitulatif s'affiche ;
78
+ 2. **Manuelle** : l'assistant `handoff setup` détaillé ci-dessous, où vous choisissez les outils et les options, voyez les changements prévus et confirmez.
79
+
80
+ Lors d'une mise à jour, la question n'est pas reposée : la configuration de vos outils est conservée.
81
+
82
+ Vous pouvez lire le script avant de l'exécuter : il est court et commenté. Variables utiles :
83
+
84
+ | Variable | Effet |
85
+ |---|---|
86
+ | `HANDOFF_VERSION=v0.1.0` | installe une version précise (par défaut : `main`) |
87
+ | `HANDOFF_NO_SETUP=1` | ne lance pas l'assistant de configuration (vous le lancerez avec `handoff setup`) |
88
+ | `HANDOFF_SETUP_YES=1` | connecte tous les outils trouvés, hooks compris, sans poser de questions |
89
+ | `HANDOFF_NO_MODIFY_PATH=1` | ne modifie pas le `PATH` |
90
+
91
+ **Désinstallation** (votre base de mémoire est conservée) :
92
+
93
+ ```bash
94
+ curl -fsSL https://raw.githubusercontent.com/kdev1966/Handoff-CLI/main/install.sh | sh -s -- --uninstall
95
+ ```
96
+
97
+ ```powershell
98
+ powershell -ExecutionPolicy ByPass -c "$env:HANDOFF_UNINSTALL=1; irm https://raw.githubusercontent.com/kdev1966/Handoff-CLI/main/install.ps1 | iex"
99
+ ```
100
+
101
+ Si vous préférez un gestionnaire d'outils Python : `pipx install git+https://github.com/kdev1966/Handoff-CLI` ou `uv tool install git+https://github.com/kdev1966/Handoff-CLI`.
102
+
103
+ ## Connecter vos assistants
104
+
105
+ `handoff setup` détecte les outils IA installés et propose le mode automatique ou manuel. En mode manuel, il vous laisse choisir, montre les changements prévus, puis les applique après confirmation :
106
+
107
+ ```text
108
+ Comment voulez-vous configurer vos outils IA ?
109
+ 1) Automatique : tous les outils trouvés, lecture et enregistrement automatiques (recommandé)
110
+ 2) Manuelle : choisir les outils et les options
111
+ > 2
112
+ Outils IA trouvés sur cette machine : Claude Code, Gemini CLI, Copilot CLI, VS Code, Cline, Kiro…
113
+ Que voulez-vous configurer ?
114
+ 1) Tous les outils trouvés
115
+ 2) Choisir outil par outil
116
+ 3) Rien pour l'instant (plus tard : handoff setup)
117
+ Lire et enregistrer la mémoire automatiquement (hooks) quand l'outil le permet ? [O/n]
118
+ Changements prévus (chaque fichier est sauvegardé avant modification) :
119
+ · Gemini CLI
120
+ ~/.gemini/settings.json: mcpServers.handoff
121
+ ~/.gemini/GEMINI.md: Handoff instructions
122
+ …
123
+ Appliquer ? [O/n]
124
+ ```
125
+
126
+ | Commande | Rôle |
127
+ |---|---|
128
+ | `handoff setup` | assistant interactif (ci-dessus) |
129
+ | `handoff setup --yes [--client NOM] [--no-hooks]` | sans questions, pour les scripts |
130
+ | `handoff setup --dry-run` | affiche les changements prévus sans rien écrire |
131
+ | `handoff setup --remove` | retire tout ce que Handoff a ajouté aux outils |
132
+ | `handoff doctor` | état de chaque outil : connecté, lecture et enregistrement automatiques, consigne |
133
+ | `handoff setup --print-config` | configuration JSON à copier pour un outil non pris en charge |
134
+
135
+ Ce que Handoff configure, selon ce que chaque outil permet :
136
+
137
+ | Outil | Connexion MCP | Lecture auto (hook) | Enregistrement auto (hook) | Consigne |
138
+ |---|---|---|---|---|
139
+ | Claude Code | ✅ `claude mcp add` | ✅ plugin `handoff@handoff` | ✅ plugin | consignes du serveur MCP |
140
+ | Codex | ✅ `codex mcp add` | ✅ ¹ | ✅ ¹ | `~/.codex/AGENTS.md` |
141
+ | Gemini CLI | ✅ | ✅ | ✅ | `~/.gemini/GEMINI.md` |
142
+ | GitHub Copilot CLI, VS Code | ✅ | ✅ `~/.copilot/hooks` | ✅ ² | `~/.copilot/instructions` |
143
+ | Cursor | ✅ | ✅ | ✅ | — |
144
+ | Junie | ✅ | — | ✅ | `~/.junie/AGENTS.md` |
145
+ | Cline, Kiro, opencode, Windsurf/Devin, Antigravity | ✅ | — | — | ✅ fichier de règles global |
146
+ | Zed | ✅ ³ | — | — | `AGENTS.md` global |
147
+ | Claude Desktop | ✅ (redémarrage requis) | — | — | — |
148
+ | Continue, JetBrains AI Assistant | à configurer à la main avec `--print-config` | | | |
149
+
150
+ ¹ Codex n'exécute un nouveau hook qu'après votre approbation unique dans `/hooks`.
151
+ ² Pour VS Code, le format de la réponse de fin de tour est documenté mais n'a pas été testé.
152
+ ³ Seulement si `settings.json` ne contient pas de commentaires ; sinon Handoff n'y touche pas et le signale.
153
+
154
+ **Ce que Handoff ne fait pas à votre place :**
155
+ - Il **ne pré-autorise jamais** ses outils : chaque assistant vous demande la permission la première fois, et vous décidez.
156
+ - Il **ne reconfigure rien en arrière-plan** : un outil installé plus tard apparaît dans `handoff doctor`, et vous relancez `handoff setup`.
157
+ - Il **sauvegarde** chaque fichier avant de le modifier (dossier `backups` dans le dossier de données), **conserve** tout le reste de son contenu, et **refuse** de réécrire un fichier qu'il ne sait pas relire à l'identique.
158
+
159
+ ## Outils MCP
160
+
161
+ | Outil | Rôle | Type |
162
+ |---|---|---|
163
+ | `memory_get(project_path)` | Lit le dernier passage de relais du projet | lecture seule |
164
+ | `memory_save(project_path, summary, next_actions, stack?, agent?)` | Enregistre un nouveau passage de relais | ajout, non destructif |
165
+ | `memory_history(project_path, limit?)` | Liste les passages de relais précédents | lecture seule |
166
+
167
+ Aucun outil ne permet à une IA de supprimer des données ni d'exécuter du SQL.
168
+
169
+ ## CLI
170
+
171
+ Handoff s'utilise comme `git` : on tape `handoff <commande>` dans le terminal. Ce n'est pas une session interactive avec des commandes `/` comme Claude Code.
172
+
173
+ - **`handoff`** seul affiche l'état du projet courant et toutes les commandes, regroupées par usage (Consulter, Enregistrer, Gérer, Configurer).
174
+ - **`handoff <commande> --help`** détaille les options d'une commande.
175
+ - **Touche Tab** : l'autocomplétion complète les commandes, les options et leurs valeurs (`handoff l` puis Tab propose `log` et `list` ; `--by` puis Tab propose `agent` et `branch`). Elle fonctionne avec zsh, bash et PowerShell. Elle est installée d'office en mode automatique et proposée en mode manuel ; sinon, `handoff completion --install` l'installe et `handoff completion --uninstall` la retire. Le script est écrit une fois dans le dossier de données, et votre profil shell ne fait que le charger : aucun ralentissement à l'ouverture du terminal.
176
+
177
+ | Commande | Rôle |
178
+ |---|---|
179
+ | `handoff show` | Affiche la dernière passation du projet courant, dans un panneau en Markdown |
180
+ | `handoff log [-l N] [--by agent\|branch]` | Historique en graphe, comme `git log --graph`, avec un couloir par agent ou par branche git |
181
+ | `handoff diff [ANCIEN] [NOUVEAU]` | Compare deux passations mot à mot (par défaut : les deux dernières) |
182
+ | `handoff stats` | Carte d'activité sur 12 semaines, répartition par agent et par branche |
183
+ | `handoff list` | Tous les projets, avec dernier agent, mini-courbe d'activité et statut (actif, inactif, en pause) |
184
+ | `handoff history [-l N]` | Passations précédentes en détail |
185
+ | `handoff save -s "état" -n "suite" [--stack "…"]` | Enregistre une passation (`-` lit l'entrée standard) |
186
+ | `handoff restore ID` | Rétablit une ancienne passation comme la plus récente |
187
+ | `handoff pause` / `handoff resume` | Suspend ou reprend le suivi d'un projet (travail confidentiel) |
188
+ | `handoff purge [--key KEY] [-y]` | Supprime toute la mémoire d'un projet |
189
+ | `handoff render` | Régénère `.handoff/context.md` |
190
+ | `handoff where` | Indique où sont stockées les données |
191
+ | `handoff completion [--install\|--uninstall]` | Autocomplétion avec Tab (zsh, bash, PowerShell) |
192
+
193
+ Toutes les commandes agissent sur le dossier courant, ou sur le dossier passé avec `--path`.
194
+
195
+ `handoff save` (comme l'outil `memory_save`) **avertit**, sans refuser, quand le résumé est très court ou ne dit rien, ou quand les prochaines actions manquent. Une passation enregistrée à la main (`handoff save` sans `--agent`) ne dispense pas l'assistant de documenter son propre travail : il sera quand même invité à enregistrer le sien. Les noms d'agents connus sont unifiés (`claude` → `claude-code`, `gemini` → `gemini-cli`…), pour qu'un même outil n'apparaisse pas sous deux noms. `show`, `log`, `history`, `stats` et `list` acceptent `--json` pour les scripts.
196
+
197
+ Chaque passation enregistre la branche git et le commit courants : ils apparaissent dans `show`, `log` et `diff`.
198
+
199
+ ```text
200
+ ● claude-code ● copilot ● gemini-cli
201
+
202
+ ● #8 claude-code hier main @ 116d129 Refacto du middleware
203
+ ╰─╮
204
+ ● #6 copilot 28 sept. main @ 116d129 Fusion de feature/auth
205
+ ╰─╮
206
+ ● #5 gemini-cli 19 sept. feature/auth @ 116d129 Tests d'intégration écrits
207
+ ```
208
+
209
+ ### Couleurs et langue
210
+
211
+ - **Couleurs** : chaque agent a une couleur fixe, toujours accompagnée de son nom. La palette reste lisible par les daltoniens, sur fond clair comme sur fond sombre. Les couleurs sont désactivées quand la sortie n'est pas un terminal ou quand `NO_COLOR` est défini ; `FORCE_COLOR=1` les force. Sans couleur, `diff` marque les changements comme `git diff --word-diff` : `[-supprimé-]{+ajouté+}`.
212
+ - **Consoles anciennes** : sur une console qui ne gère pas l'UTF-8, les symboles sont remplacés par des équivalents ASCII.
213
+ - **Langue** : l'interface est en français ou en anglais selon votre système (`LANGUAGE`, `LC_ALL`, `LC_MESSAGES`, `LANG`, puis la langue de macOS ou de Windows). `HANDOFF_LANG=fr` ou `HANDOFF_LANG=en` impose une langue. Ce que lisent les IA (outils MCP, `.handoff/context.md`) reste en anglais.
214
+
215
+ ### Assistants sans MCP
216
+
217
+ Après chaque enregistrement, Handoff génère `.handoff/context.md` à la racine du projet. Ce dossier contient son propre `.gitignore` : il n'apparaît jamais dans `git status` et votre `.gitignore` n'est pas modifié. Un assistant sans MCP peut lire ce fichier, puis enregistrer avec `handoff save`. Ne modifiez pas ce fichier à la main : il est régénéré.
218
+
219
+ Pour qu'un outil le lise automatiquement, ajoutez une ligne de renvoi dans le fichier d'instructions qu'il lit déjà (`AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `.github/copilot-instructions.md`…), par exemple : « Lis `.handoff/context.md` en début de session. »
220
+
221
+ ## Sécurité
222
+
223
+ - **Local uniquement** : le serveur MCP communique en stdio et n'ouvre aucun port réseau.
224
+ - **Hooks sans risque pour l'outil** : ils ne lancent que `handoff` (chemin absolu de son interpréteur), ne lisent que l'état git du projet, et en cas de problème n'affichent rien et laissent l'outil continuer.
225
+ - **Pas de pré-autorisation** : Handoff ne s'accorde jamais de permissions dans vos outils IA.
226
+ - **Surface réduite** : 3 outils au schéma typé, pas de SQL brut, pas de suppression par l'IA.
227
+ - **Chemins validés** : le chemin doit être absolu et exister. La racine du disque, le dossier personnel et ses parents sont refusés.
228
+ - **Entrées validées** : 16 Kio maximum par champ, caractères de contrôle supprimés, nom d'agent contrôlé.
229
+ - **Secrets masqués avant stockage** : clés AWS, jetons GitHub/GitLab/Slack/Stripe/Google, clés `sk-…`, JWT, clés privées PEM, identifiants dans les URL, affectations `password=…`. La mémoire étant relue par d'autres fournisseurs d'IA, rien de cela ne doit y entrer.
230
+ - **La mémoire est une donnée, pas une consigne** : les assistants sont invités à ne jamais exécuter d'instructions trouvées dans la mémoire.
231
+ - **Fichiers protégés** : base en mode `0600` dans un dossier `0700` (sous Windows, protégée par les droits du profil utilisateur). Écriture atomique, liens symboliques refusés, aucun fichier non généré par Handoff n'est écrasé.
232
+
233
+ > Le masquage repose sur des formats connus : un secret dans un format inédit peut passer. N'enregistrez pas de secrets dans la mémoire.
234
+
235
+ ## Emplacement des données
236
+
237
+ | Système | Dossier |
238
+ |---|---|
239
+ | Windows | `%LOCALAPPDATA%\handoff\` |
240
+ | macOS | `~/Library/Application Support/handoff/` |
241
+ | Linux | `$XDG_DATA_HOME/handoff/` (par défaut `~/.local/share/handoff/`) |
242
+
243
+ La variable d'environnement `HANDOFF_HOME` permet de choisir un autre dossier.
244
+
245
+ ## Limites
246
+
247
+ - La mémoire est locale à la machine. Elle n'est pas synchronisée entre postes ni partagée avec une équipe.
248
+ - Deux clones d'un même dépôt partagent la même mémoire (c'est voulu).
249
+ - Les formats de configuration des outils IA évoluent vite. `handoff doctor` signale ce qui n'est pas en place ; les erreurs des hooks sont consignées dans `hooks.log`, dans le dossier de données, sans jamais bloquer l'outil.
250
+ - L'enregistrement automatique repose sur l'état git du projet : hors dépôt git, seule la consigne demande à l'assistant d'enregistrer.
251
+ - Les messages des scripts d'installation sont en anglais ; ceux de `handoff` suivent la langue du système.
252
+
253
+ ## Développement
254
+
255
+ ```bash
256
+ python -m venv .venv
257
+ .venv/bin/pip install -e ".[dev]" # Windows : .venv\Scripts\pip
258
+ .venv/bin/pytest
259
+ .venv/bin/ruff check . && .venv/bin/ruff format --check .
260
+ ```
261
+
262
+ La CI exécute les tests sous Windows, macOS et Linux avec Python 3.10, 3.12 et 3.14. Une release est publiée sur PyPI (par *trusted publishing*) quand un tag `vX.Y.Z` correspondant à la version du paquet est poussé.
263
+
264
+ ## Licence
265
+
266
+ MIT. Voir [LICENSE](LICENSE).