claude-session-sync 0.1.1__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 (47) hide show
  1. claude_session_sync-0.1.1/.github/workflows/publish.yml +36 -0
  2. claude_session_sync-0.1.1/.gitignore +6 -0
  3. claude_session_sync-0.1.1/LICENSE +21 -0
  4. claude_session_sync-0.1.1/PKG-INFO +219 -0
  5. claude_session_sync-0.1.1/README.md +196 -0
  6. claude_session_sync-0.1.1/docs/README_ja.md +320 -0
  7. claude_session_sync-0.1.1/pyproject.toml +39 -0
  8. claude_session_sync-0.1.1/src/claude_session_sync/__init__.py +1 -0
  9. claude_session_sync-0.1.1/src/claude_session_sync/__main__.py +4 -0
  10. claude_session_sync-0.1.1/src/claude_session_sync/cli.py +311 -0
  11. claude_session_sync-0.1.1/src/claude_session_sync/commands/__init__.py +1 -0
  12. claude_session_sync-0.1.1/src/claude_session_sync/commands/config_cmd.py +176 -0
  13. claude_session_sync-0.1.1/src/claude_session_sync/commands/daemon.py +336 -0
  14. claude_session_sync-0.1.1/src/claude_session_sync/commands/init.py +313 -0
  15. claude_session_sync-0.1.1/src/claude_session_sync/commands/list.py +182 -0
  16. claude_session_sync-0.1.1/src/claude_session_sync/commands/lock_cmd.py +124 -0
  17. claude_session_sync-0.1.1/src/claude_session_sync/commands/pull.py +50 -0
  18. claude_session_sync-0.1.1/src/claude_session_sync/commands/push.py +47 -0
  19. claude_session_sync-0.1.1/src/claude_session_sync/commands/resume.py +772 -0
  20. claude_session_sync-0.1.1/src/claude_session_sync/commands/setup_hooks.py +78 -0
  21. claude_session_sync-0.1.1/src/claude_session_sync/commands/status.py +57 -0
  22. claude_session_sync-0.1.1/src/claude_session_sync/commands/update.py +85 -0
  23. claude_session_sync-0.1.1/src/claude_session_sync/config.py +125 -0
  24. claude_session_sync-0.1.1/src/claude_session_sync/config_sync.py +314 -0
  25. claude_session_sync-0.1.1/src/claude_session_sync/git_ops.py +162 -0
  26. claude_session_sync-0.1.1/src/claude_session_sync/github_ops.py +55 -0
  27. claude_session_sync-0.1.1/src/claude_session_sync/path_mapper.py +110 -0
  28. claude_session_sync-0.1.1/src/claude_session_sync/session.py +108 -0
  29. claude_session_sync-0.1.1/src/claude_session_sync/session_lock.py +319 -0
  30. claude_session_sync-0.1.1/src/claude_session_sync/shared_placeholders.py +123 -0
  31. claude_session_sync-0.1.1/src/claude_session_sync/sync.py +822 -0
  32. claude_session_sync-0.1.1/tests/fixtures/minimal_session.jsonl +3 -0
  33. claude_session_sync-0.1.1/tests/fixtures/sample_session.jsonl +20 -0
  34. claude_session_sync-0.1.1/tests/fixtures/sample_subagent.meta.json +1 -0
  35. claude_session_sync-0.1.1/tests/test_config.py +159 -0
  36. claude_session_sync-0.1.1/tests/test_config_sync.py +581 -0
  37. claude_session_sync-0.1.1/tests/test_daemon.py +679 -0
  38. claude_session_sync-0.1.1/tests/test_git_ops.py +103 -0
  39. claude_session_sync-0.1.1/tests/test_path_conversion.py +76 -0
  40. claude_session_sync-0.1.1/tests/test_path_mapper.py +268 -0
  41. claude_session_sync-0.1.1/tests/test_resume.py +1176 -0
  42. claude_session_sync-0.1.1/tests/test_session.py +174 -0
  43. claude_session_sync-0.1.1/tests/test_session_lock.py +425 -0
  44. claude_session_sync-0.1.1/tests/test_setup_hooks.py +93 -0
  45. claude_session_sync-0.1.1/tests/test_shared_placeholders.py +660 -0
  46. claude_session_sync-0.1.1/tests/test_sync.py +1146 -0
  47. claude_session_sync-0.1.1/tests/test_update.py +272 -0
@@ -0,0 +1,36 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with:
15
+ python-version: "3.12"
16
+ - name: Build package
17
+ run: |
18
+ pip install build
19
+ python -m build
20
+ - uses: actions/upload-artifact@v4
21
+ with:
22
+ name: dist
23
+ path: dist/
24
+
25
+ publish:
26
+ needs: build
27
+ runs-on: ubuntu-latest
28
+ environment: pypi
29
+ permissions:
30
+ id-token: write
31
+ steps:
32
+ - uses: actions/download-artifact@v4
33
+ with:
34
+ name: dist
35
+ path: dist/
36
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,6 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .venv/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 tsubome (Aratech)
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,219 @@
1
+ Metadata-Version: 2.4
2
+ Name: claude-session-sync
3
+ Version: 0.1.1
4
+ Summary: Sync Claude Code sessions across Windows, macOS, and Linux
5
+ Project-URL: Homepage, https://github.com/tsubome/claude-session-sync
6
+ Project-URL: Issues, https://github.com/tsubome/claude-session-sync/issues
7
+ Project-URL: Repository, https://github.com/tsubome/claude-session-sync
8
+ Author: tsubome
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Classifier: Environment :: Console
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development
21
+ Requires-Python: >=3.9
22
+ Description-Content-Type: text/markdown
23
+
24
+ [日本語](docs/README_ja.md) | English
25
+
26
+ # claude-session-sync
27
+
28
+ ![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue)
29
+ ![License: MIT](https://img.shields.io/badge/license-MIT-green)
30
+
31
+ ## What is this?
32
+
33
+ **claude-session-sync** is a CLI tool that syncs [Claude Code](https://docs.anthropic.com/en/docs/claude-code) session history across Windows, macOS, and Linux.
34
+
35
+ - Continue any conversation on any machine — pick up exactly where you left off
36
+ - Uses a **private GitHub repository** as the sync backend (no third-party servers)
37
+ - **Automatic path conversion**: OS-specific paths are replaced with portable placeholders (e.g., `/home/user/projects` → `{{PROJECTS}}` → `C:\projects`)
38
+
39
+ ## How it works
40
+
41
+ ```
42
+ Ubuntu GitHub Mac
43
+ claude-session-sync push → Private Repo → claude-session-sync pull
44
+ /home/user/projects → {{PROJECTS}} → /Users/user/projects
45
+ ```
46
+
47
+ Session files (`.jsonl`) are stored under `~/.claude/projects/` by Claude Code. This tool copies them into a private GitHub repository, translating machine-specific paths to shared placeholders on push, and back to local paths on pull.
48
+
49
+ Memory files stored under `~/.claude/projects/*/memory/` are also synced.
50
+ All machines share a single set of memory files — the last push becomes the source of truth.
51
+ On pull, local memory is completely replaced with the shared version.
52
+ Changes are tracked through git commit history.
53
+
54
+ ## Features
55
+
56
+ - **Cross-machine session resume** — open any session from any registered machine
57
+ - **Automatic path conversion** with user-defined placeholders
58
+ - **Session locking** — prevents two machines from editing the same session simultaneously
59
+ - **Background daemon** — periodic push backup while Claude Code is running
60
+ - **Selective sync** — only sessions under configured directories are shared
61
+ - **Windows / macOS / Linux** support
62
+ - **Memory & CLAUDE.md sync** — project memory files and global CLAUDE.md are synced across machines automatically during push/pull
63
+ - **Shared memory model** — all machines use the same memory files, git tracks change history
64
+ - **git push retry** — automatic pull-and-retry (up to 3 times) when push is rejected due to concurrent updates
65
+ - **Duplicate daemon prevention** — the resume command checks for existing daemons before starting a new one
66
+ - **Last-editing machine display** — the session list shows which machine last edited each session, not just where it was created
67
+
68
+ ## Quick Start
69
+
70
+ ```bash
71
+ # Install
72
+ pip install claude-session-sync
73
+ ```
74
+
75
+ ### Development install
76
+
77
+ ```bash
78
+ # Development install
79
+ git clone https://github.com/tsubome/claude-session-sync.git
80
+ cd claude-session-sync
81
+ pip install -e .
82
+ ```
83
+
84
+ ```bash
85
+ # Setup — first machine (creates a new private GitHub repo)
86
+ claude-session-sync init
87
+
88
+ # Setup — additional machines (connects to the existing repo)
89
+ claude-session-sync init
90
+
91
+ # Daily usage — `ccsync` is a short alias for `claude-session-sync`
92
+ ccsync resume
93
+ # Pulls the latest sessions, lets you pick one interactively,
94
+ # launches Claude Code, then pushes and releases the lock on exit.
95
+ ```
96
+
97
+ ## Commands
98
+
99
+ | Command | Description |
100
+ |---|---|
101
+ | `resume [SESSION_ID]` | **Main command.** Pull → select session interactively → launch Claude Code → push + release lock on exit. Pass `SESSION_ID` to skip the list. |
102
+ | `resume --latest` | Automatically selects the most recently updated session. |
103
+ | `resume --from MACHINE_ID` | Show only sessions from a specific machine. |
104
+ | `resume --all` | Show all sessions, ignoring `sync_directories` filter. |
105
+ | `init` | Register this machine and create or connect to the shared GitHub repository. |
106
+ | `push [--dry-run]` | Manually push local sessions to the remote repository. |
107
+ | `pull [--dry-run] [--force]` | Manually pull sessions from the remote repository. |
108
+ | `update` | Push sessions and release any locks left behind after an abnormal exit. |
109
+ | `status` | Show the current sync status (last push/pull time, machine ID, etc.). |
110
+ | `list [--remote] [--format table\|json]` | List local (or remote) sessions. |
111
+ | `lock show` | Show all current locks. |
112
+ | `lock release [SESSION_ID]` | Release a lock. Omit `SESSION_ID` to release all locks on this machine. |
113
+ | `lock cleanup` | Delete all expired locks. |
114
+ | `config show` | Show the current configuration. |
115
+ | `config add-placeholder NAME=PATH` | Add a new placeholder mapping for this machine. |
116
+ | `config set-path NAME MACHINE_ID PATH` | Set a path for a specific machine in `shared_placeholders.json`. |
117
+ | `daemon [--interval SECONDS] [--push-only] [--stop]` | Run a background sync daemon (default interval: 300 s / 5 min). |
118
+
119
+ ## Configuration
120
+
121
+ The local config file is stored at `~/.claude-session-sync/config.json`.
122
+
123
+ Placeholder mappings shared across all machines are stored in the GitHub repository as `shared_placeholders.json`.
124
+
125
+ ### Example config
126
+
127
+ ```json
128
+ {
129
+ "machine_id": "ubuntu-work",
130
+ "github_owner": "your-username",
131
+ "github_repo": "claude-sessions",
132
+ "sync_directories": [
133
+ "/home/your-username/projects"
134
+ ],
135
+ "custom_placeholders": {
136
+ "PROJECTS": "/home/your-username/projects"
137
+ }
138
+ }
139
+ ```
140
+
141
+ `sync_directories` controls which sessions are visible in `resume`. Only sessions whose working directory falls under one of these paths are shown. Sessions outside them are ignored unless you pass `--all`.
142
+
143
+ ## Custom Placeholders
144
+
145
+ Placeholders let the same session be opened on machines with different filesystem layouts.
146
+
147
+ **Adding during init:**
148
+
149
+ ```bash
150
+ claude-session-sync init --add-placeholder PROJECTS=/home/user/projects
151
+ ```
152
+
153
+ **Adding afterwards:**
154
+
155
+ ```bash
156
+ claude-session-sync config add-placeholder PROJECTS=/home/user/projects
157
+ ```
158
+
159
+ **Setting the path for another machine:**
160
+
161
+ ```bash
162
+ claude-session-sync config set-path PROJECTS macbook /Users/user/projects
163
+ claude-session-sync config set-path PROJECTS windows C:\projects
164
+ ```
165
+
166
+ When the same session is pulled on macOS, `{{PROJECTS}}` is automatically expanded to `/Users/user/projects`. On Windows it becomes `C:\projects`.
167
+
168
+ ## Session Locking
169
+
170
+ When you resume a session, `claude-session-sync` acquires a lock in the shared repository so that no other machine can open the same session at the same time.
171
+
172
+ | Detail | Value |
173
+ |---|---|
174
+ | Lock TTL | 10 minutes (default) |
175
+ | Heartbeat | Background daemon refreshes the lock while Claude Code is running |
176
+ | Crash recovery | Locks auto-expire after TTL — no manual cleanup needed in most cases |
177
+ | Manual release | `claude-session-sync lock release` |
178
+
179
+ If a session is locked by another machine, you are shown a warning and asked whether to take over the lock. This is safe if the other machine crashed or was closed without a proper exit.
180
+
181
+ ## Concurrent Operation
182
+
183
+ Multiple machines can work on **different** sessions simultaneously.
184
+ Each session has its own lock, so editing CrossClip on Linux while editing WhisperApp on Windows is fully supported.
185
+
186
+ If two machines push at the same time, the tool automatically retries with pull-and-push (up to 3 attempts).
187
+
188
+ ## Troubleshooting
189
+
190
+ **"Session is locked by another machine"**
191
+
192
+ The previous Claude Code session likely exited abnormally. You can:
193
+
194
+ 1. Select the locked session → confirm the takeover prompt (`y`)
195
+ 2. Or run `claude-session-sync update` on the machine that holds the lock (if still reachable)
196
+ 3. Or run `claude-session-sync lock release SESSION_ID` to force-release it
197
+
198
+ **"No sessions found"**
199
+
200
+ Run `claude-session-sync pull` first to download sessions from the remote repository, then try `resume` again.
201
+
202
+ **Windows: daemon does not stop**
203
+
204
+ The daemon uses a stop-file mechanism on Windows (instead of signals). Run `claude-session-sync daemon --stop` to request a graceful shutdown.
205
+
206
+ **Sessions from another machine are not visible**
207
+
208
+ Make sure `sync_directories` on both machines point to the same placeholder (e.g., both mapped to `{{PROJECTS}}`). Run `claude-session-sync config show` to verify, and use `config set-path` to add missing machine entries.
209
+
210
+ ## Requirements
211
+
212
+ - Python 3.9+
213
+ - Git
214
+ - [GitHub CLI (`gh`)](https://cli.github.com/) — must be authenticated (`gh auth login`)
215
+ - [Claude Code](https://docs.anthropic.com/en/docs/claude-code)
216
+
217
+ ## License
218
+
219
+ MIT
@@ -0,0 +1,196 @@
1
+ [日本語](docs/README_ja.md) | English
2
+
3
+ # claude-session-sync
4
+
5
+ ![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue)
6
+ ![License: MIT](https://img.shields.io/badge/license-MIT-green)
7
+
8
+ ## What is this?
9
+
10
+ **claude-session-sync** is a CLI tool that syncs [Claude Code](https://docs.anthropic.com/en/docs/claude-code) session history across Windows, macOS, and Linux.
11
+
12
+ - Continue any conversation on any machine — pick up exactly where you left off
13
+ - Uses a **private GitHub repository** as the sync backend (no third-party servers)
14
+ - **Automatic path conversion**: OS-specific paths are replaced with portable placeholders (e.g., `/home/user/projects` → `{{PROJECTS}}` → `C:\projects`)
15
+
16
+ ## How it works
17
+
18
+ ```
19
+ Ubuntu GitHub Mac
20
+ claude-session-sync push → Private Repo → claude-session-sync pull
21
+ /home/user/projects → {{PROJECTS}} → /Users/user/projects
22
+ ```
23
+
24
+ Session files (`.jsonl`) are stored under `~/.claude/projects/` by Claude Code. This tool copies them into a private GitHub repository, translating machine-specific paths to shared placeholders on push, and back to local paths on pull.
25
+
26
+ Memory files stored under `~/.claude/projects/*/memory/` are also synced.
27
+ All machines share a single set of memory files — the last push becomes the source of truth.
28
+ On pull, local memory is completely replaced with the shared version.
29
+ Changes are tracked through git commit history.
30
+
31
+ ## Features
32
+
33
+ - **Cross-machine session resume** — open any session from any registered machine
34
+ - **Automatic path conversion** with user-defined placeholders
35
+ - **Session locking** — prevents two machines from editing the same session simultaneously
36
+ - **Background daemon** — periodic push backup while Claude Code is running
37
+ - **Selective sync** — only sessions under configured directories are shared
38
+ - **Windows / macOS / Linux** support
39
+ - **Memory & CLAUDE.md sync** — project memory files and global CLAUDE.md are synced across machines automatically during push/pull
40
+ - **Shared memory model** — all machines use the same memory files, git tracks change history
41
+ - **git push retry** — automatic pull-and-retry (up to 3 times) when push is rejected due to concurrent updates
42
+ - **Duplicate daemon prevention** — the resume command checks for existing daemons before starting a new one
43
+ - **Last-editing machine display** — the session list shows which machine last edited each session, not just where it was created
44
+
45
+ ## Quick Start
46
+
47
+ ```bash
48
+ # Install
49
+ pip install claude-session-sync
50
+ ```
51
+
52
+ ### Development install
53
+
54
+ ```bash
55
+ # Development install
56
+ git clone https://github.com/tsubome/claude-session-sync.git
57
+ cd claude-session-sync
58
+ pip install -e .
59
+ ```
60
+
61
+ ```bash
62
+ # Setup — first machine (creates a new private GitHub repo)
63
+ claude-session-sync init
64
+
65
+ # Setup — additional machines (connects to the existing repo)
66
+ claude-session-sync init
67
+
68
+ # Daily usage — `ccsync` is a short alias for `claude-session-sync`
69
+ ccsync resume
70
+ # Pulls the latest sessions, lets you pick one interactively,
71
+ # launches Claude Code, then pushes and releases the lock on exit.
72
+ ```
73
+
74
+ ## Commands
75
+
76
+ | Command | Description |
77
+ |---|---|
78
+ | `resume [SESSION_ID]` | **Main command.** Pull → select session interactively → launch Claude Code → push + release lock on exit. Pass `SESSION_ID` to skip the list. |
79
+ | `resume --latest` | Automatically selects the most recently updated session. |
80
+ | `resume --from MACHINE_ID` | Show only sessions from a specific machine. |
81
+ | `resume --all` | Show all sessions, ignoring `sync_directories` filter. |
82
+ | `init` | Register this machine and create or connect to the shared GitHub repository. |
83
+ | `push [--dry-run]` | Manually push local sessions to the remote repository. |
84
+ | `pull [--dry-run] [--force]` | Manually pull sessions from the remote repository. |
85
+ | `update` | Push sessions and release any locks left behind after an abnormal exit. |
86
+ | `status` | Show the current sync status (last push/pull time, machine ID, etc.). |
87
+ | `list [--remote] [--format table\|json]` | List local (or remote) sessions. |
88
+ | `lock show` | Show all current locks. |
89
+ | `lock release [SESSION_ID]` | Release a lock. Omit `SESSION_ID` to release all locks on this machine. |
90
+ | `lock cleanup` | Delete all expired locks. |
91
+ | `config show` | Show the current configuration. |
92
+ | `config add-placeholder NAME=PATH` | Add a new placeholder mapping for this machine. |
93
+ | `config set-path NAME MACHINE_ID PATH` | Set a path for a specific machine in `shared_placeholders.json`. |
94
+ | `daemon [--interval SECONDS] [--push-only] [--stop]` | Run a background sync daemon (default interval: 300 s / 5 min). |
95
+
96
+ ## Configuration
97
+
98
+ The local config file is stored at `~/.claude-session-sync/config.json`.
99
+
100
+ Placeholder mappings shared across all machines are stored in the GitHub repository as `shared_placeholders.json`.
101
+
102
+ ### Example config
103
+
104
+ ```json
105
+ {
106
+ "machine_id": "ubuntu-work",
107
+ "github_owner": "your-username",
108
+ "github_repo": "claude-sessions",
109
+ "sync_directories": [
110
+ "/home/your-username/projects"
111
+ ],
112
+ "custom_placeholders": {
113
+ "PROJECTS": "/home/your-username/projects"
114
+ }
115
+ }
116
+ ```
117
+
118
+ `sync_directories` controls which sessions are visible in `resume`. Only sessions whose working directory falls under one of these paths are shown. Sessions outside them are ignored unless you pass `--all`.
119
+
120
+ ## Custom Placeholders
121
+
122
+ Placeholders let the same session be opened on machines with different filesystem layouts.
123
+
124
+ **Adding during init:**
125
+
126
+ ```bash
127
+ claude-session-sync init --add-placeholder PROJECTS=/home/user/projects
128
+ ```
129
+
130
+ **Adding afterwards:**
131
+
132
+ ```bash
133
+ claude-session-sync config add-placeholder PROJECTS=/home/user/projects
134
+ ```
135
+
136
+ **Setting the path for another machine:**
137
+
138
+ ```bash
139
+ claude-session-sync config set-path PROJECTS macbook /Users/user/projects
140
+ claude-session-sync config set-path PROJECTS windows C:\projects
141
+ ```
142
+
143
+ When the same session is pulled on macOS, `{{PROJECTS}}` is automatically expanded to `/Users/user/projects`. On Windows it becomes `C:\projects`.
144
+
145
+ ## Session Locking
146
+
147
+ When you resume a session, `claude-session-sync` acquires a lock in the shared repository so that no other machine can open the same session at the same time.
148
+
149
+ | Detail | Value |
150
+ |---|---|
151
+ | Lock TTL | 10 minutes (default) |
152
+ | Heartbeat | Background daemon refreshes the lock while Claude Code is running |
153
+ | Crash recovery | Locks auto-expire after TTL — no manual cleanup needed in most cases |
154
+ | Manual release | `claude-session-sync lock release` |
155
+
156
+ If a session is locked by another machine, you are shown a warning and asked whether to take over the lock. This is safe if the other machine crashed or was closed without a proper exit.
157
+
158
+ ## Concurrent Operation
159
+
160
+ Multiple machines can work on **different** sessions simultaneously.
161
+ Each session has its own lock, so editing CrossClip on Linux while editing WhisperApp on Windows is fully supported.
162
+
163
+ If two machines push at the same time, the tool automatically retries with pull-and-push (up to 3 attempts).
164
+
165
+ ## Troubleshooting
166
+
167
+ **"Session is locked by another machine"**
168
+
169
+ The previous Claude Code session likely exited abnormally. You can:
170
+
171
+ 1. Select the locked session → confirm the takeover prompt (`y`)
172
+ 2. Or run `claude-session-sync update` on the machine that holds the lock (if still reachable)
173
+ 3. Or run `claude-session-sync lock release SESSION_ID` to force-release it
174
+
175
+ **"No sessions found"**
176
+
177
+ Run `claude-session-sync pull` first to download sessions from the remote repository, then try `resume` again.
178
+
179
+ **Windows: daemon does not stop**
180
+
181
+ The daemon uses a stop-file mechanism on Windows (instead of signals). Run `claude-session-sync daemon --stop` to request a graceful shutdown.
182
+
183
+ **Sessions from another machine are not visible**
184
+
185
+ Make sure `sync_directories` on both machines point to the same placeholder (e.g., both mapped to `{{PROJECTS}}`). Run `claude-session-sync config show` to verify, and use `config set-path` to add missing machine entries.
186
+
187
+ ## Requirements
188
+
189
+ - Python 3.9+
190
+ - Git
191
+ - [GitHub CLI (`gh`)](https://cli.github.com/) — must be authenticated (`gh auth login`)
192
+ - [Claude Code](https://docs.anthropic.com/en/docs/claude-code)
193
+
194
+ ## License
195
+
196
+ MIT