@askalf/claude-sync 0.0.1 → 0.0.2
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.
- package/README.md +7 -1
- package/dist/project.d.ts +19 -3
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +24 -6
- package/dist/project.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ npm install -g @askalf/claude-sync
|
|
|
14
14
|
|
|
15
15
|
Claude Code stores sessions locally at `~/.claude/projects/<encoded-cwd>/<session-id>.jsonl`. There's no native cross-machine sync. The naive workaround — rsync `~/.claude/projects/` — has two problems:
|
|
16
16
|
|
|
17
|
-
1. **Path-hash mismatch.** `<encoded-cwd>` is the absolute path with `
|
|
17
|
+
1. **Path-hash mismatch.** `<encoded-cwd>` is the absolute path with every non-alphanumeric character replaced by a single `-` (e.g. `C:\Users\me\my app` → `C--Users-me-my-app`). Same git repo at `/Users/alice/code/myapp` (mac) and `D:\code\myapp` (windows) hashes to different directory names → the synced session is orphaned on arrival.
|
|
18
18
|
2. **No file locking.** Concurrent writes from two machines into the same JSONL corrupt the transcript.
|
|
19
19
|
|
|
20
20
|
`claude-sync` solves both:
|
|
@@ -143,6 +143,12 @@ import {
|
|
|
143
143
|
|
|
144
144
|
See `src/index.ts` for the full surface. Zero runtime dependencies.
|
|
145
145
|
|
|
146
|
+
## Environment
|
|
147
|
+
|
|
148
|
+
| Variable | Effect |
|
|
149
|
+
| --- | --- |
|
|
150
|
+
| `CLAUDE_SYNC_HOME` | Override the home directory under which `.claude/projects` and `.claude-sync/` are found. Defaults to your OS home. Useful when Claude Code lives somewhere non-standard (also used by the test suite to sandbox the filesystem). |
|
|
151
|
+
|
|
146
152
|
## License
|
|
147
153
|
|
|
148
154
|
MIT — see [LICENSE](LICENSE).
|
package/dist/project.d.ts
CHANGED
|
@@ -18,10 +18,26 @@
|
|
|
18
18
|
* - Reverse lookup: given a project key + a registry of local repo
|
|
19
19
|
* locations, pick the right local cwd to install a session into.
|
|
20
20
|
*/
|
|
21
|
-
/** Encode a cwd into Claude Code's project-directory format.
|
|
22
|
-
*
|
|
23
|
-
*
|
|
21
|
+
/** Encode a cwd into Claude Code's project-directory format. CC replaces
|
|
22
|
+
* EACH non-alphanumeric character with a single `-` (no run-collapsing),
|
|
23
|
+
* so `C:\Users\me\my app` → `C--Users-me-my-app` and `/root/.askalf/x`
|
|
24
|
+
* → `-root--askalf-x`. Verified against real CC dirs on Windows + Linux.
|
|
25
|
+
* One-way (lossy): consecutive specials and literal `-` both map to `-`,
|
|
26
|
+
* so it doesn't reverse — CC keys on the directory existing, not decoding.
|
|
27
|
+
*
|
|
28
|
+
* NOTE: a prior version used `/[/\\:.\s]+/g` which was wrong twice over —
|
|
29
|
+
* the `+` collapsed runs (`C:\` → `C-` instead of `C--`) and the narrow
|
|
30
|
+
* class missed `_`, `(`, `~`, etc. that CC also replaces. That silently
|
|
31
|
+
* broke push/pull on Windows (sessions written to / read from the wrong
|
|
32
|
+
* dir). Keep this matching CC's actual `[^a-zA-Z0-9]` behavior. */
|
|
24
33
|
export declare function encodeProjectDir(cwd: string): string;
|
|
34
|
+
/** Resolve the home directory under which `.claude/` and `.claude-sync/`
|
|
35
|
+
* live. Defaults to the OS home, but honors `CLAUDE_SYNC_HOME` for users
|
|
36
|
+
* whose Claude Code install is non-standard — and so the test suite can
|
|
37
|
+
* sandbox the filesystem portably. (`os.homedir()` reads `$HOME` on POSIX
|
|
38
|
+
* but ignores a `%USERPROFILE%` override on Windows, so an env hook is the
|
|
39
|
+
* only cross-platform way to redirect this.) */
|
|
40
|
+
export declare function claudeHome(): string;
|
|
25
41
|
/** Where Claude Code stores its session JSONL files. */
|
|
26
42
|
export declare function claudeProjectsRoot(): string;
|
|
27
43
|
/** `~/.claude-sync/` lives next to `~/.claude/`. We keep our config and
|
package/dist/project.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAOH
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAOH;;;;;;;;;;;oEAWoE;AACpE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;;;iDAKiD;AACjD,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wDAAwD;AACxD,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;uCACuC;AACvC,wBAAgB,QAAQ,IAAI,MAAM,CAEjC;AAED;;;;;;;;;;uEAUuE;AACvE,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAavD;AAED;;;kEAGkE;AAClE,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI9C;AAED;;;yCAGyC;AACzC,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,CAAC,CAAC;IAClB;oEACgE;IAChE,WAAW,EAAE,MAAM,CAAC;IACpB;;;mDAG+C;IAC/C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACpC;AAID,wBAAgB,YAAY,IAAI,eAAe,CAmB9C;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI,CAUvD;AAED;oDACoD;AACpD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,eAAe,CAAA;CAAE,CASvF;AAED;;;;eAIe;AACf,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI,CAQ3E"}
|
package/dist/project.js
CHANGED
|
@@ -22,20 +22,38 @@ import { execSync } from 'node:child_process';
|
|
|
22
22
|
import { existsSync, readFileSync, writeFileSync, mkdirSync, renameSync } from 'node:fs';
|
|
23
23
|
import { dirname, basename, join } from 'node:path';
|
|
24
24
|
import { homedir } from 'node:os';
|
|
25
|
-
/** Encode a cwd into Claude Code's project-directory format.
|
|
26
|
-
*
|
|
27
|
-
*
|
|
25
|
+
/** Encode a cwd into Claude Code's project-directory format. CC replaces
|
|
26
|
+
* EACH non-alphanumeric character with a single `-` (no run-collapsing),
|
|
27
|
+
* so `C:\Users\me\my app` → `C--Users-me-my-app` and `/root/.askalf/x`
|
|
28
|
+
* → `-root--askalf-x`. Verified against real CC dirs on Windows + Linux.
|
|
29
|
+
* One-way (lossy): consecutive specials and literal `-` both map to `-`,
|
|
30
|
+
* so it doesn't reverse — CC keys on the directory existing, not decoding.
|
|
31
|
+
*
|
|
32
|
+
* NOTE: a prior version used `/[/\\:.\s]+/g` which was wrong twice over —
|
|
33
|
+
* the `+` collapsed runs (`C:\` → `C-` instead of `C--`) and the narrow
|
|
34
|
+
* class missed `_`, `(`, `~`, etc. that CC also replaces. That silently
|
|
35
|
+
* broke push/pull on Windows (sessions written to / read from the wrong
|
|
36
|
+
* dir). Keep this matching CC's actual `[^a-zA-Z0-9]` behavior. */
|
|
28
37
|
export function encodeProjectDir(cwd) {
|
|
29
|
-
return cwd.replace(/[
|
|
38
|
+
return cwd.replace(/[^a-zA-Z0-9]/g, '-');
|
|
39
|
+
}
|
|
40
|
+
/** Resolve the home directory under which `.claude/` and `.claude-sync/`
|
|
41
|
+
* live. Defaults to the OS home, but honors `CLAUDE_SYNC_HOME` for users
|
|
42
|
+
* whose Claude Code install is non-standard — and so the test suite can
|
|
43
|
+
* sandbox the filesystem portably. (`os.homedir()` reads `$HOME` on POSIX
|
|
44
|
+
* but ignores a `%USERPROFILE%` override on Windows, so an env hook is the
|
|
45
|
+
* only cross-platform way to redirect this.) */
|
|
46
|
+
export function claudeHome() {
|
|
47
|
+
return process.env.CLAUDE_SYNC_HOME || homedir();
|
|
30
48
|
}
|
|
31
49
|
/** Where Claude Code stores its session JSONL files. */
|
|
32
50
|
export function claudeProjectsRoot() {
|
|
33
|
-
return join(
|
|
51
|
+
return join(claudeHome(), '.claude', 'projects');
|
|
34
52
|
}
|
|
35
53
|
/** `~/.claude-sync/` lives next to `~/.claude/`. We keep our config and
|
|
36
54
|
* the local-project registry here. */
|
|
37
55
|
export function syncRoot() {
|
|
38
|
-
return join(
|
|
56
|
+
return join(claudeHome(), '.claude-sync');
|
|
39
57
|
}
|
|
40
58
|
/** Try to read the git remote URL of the cwd. Returns null when:
|
|
41
59
|
* - cwd isn't a git repo
|
package/dist/project.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACzF,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askalf/claude-sync",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Sync Claude Code sessions across machines. Pack a local CC session into a portable .ccsync file, ship it via Dropbox / iCloud / Syncthing / a USB stick, unpack on the other side. Path-hash mismatches solved via git-remote-url as canonical project key.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|