@askalf/claude-sync 0.0.3 → 0.2.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAaxC,MAAM,WAAW,GAAG,GAAW,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,aAAa,CAAC,CAAC;AAElE,MAAM,UAAU,YAAY;IAC1B,OAAO,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,IAAI,GAAG,WAAW,EAAE,CAAC;IAC3B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,sBAAsB,IAAI,6CAA6C,CACxE,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAW,CAAC;IACjE,IAAI,MAAM,CAAC,cAAc,KAAK,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,sCAAsC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,MAAM,IAAI,GAAG,WAAW,EAAE,CAAC;IAC3B,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAAE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9E,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,oEAAoE;IACpE,4CAA4C;IAC5C,OAAO,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAe,EAAE,WAAoB;IACtE,OAAO;QACL,cAAc,EAAE,CAAC;QACjB,OAAO;QACP,WAAW,EAAE,WAAW,IAAI,kBAAkB,EAAE;KACjD,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAqClD;6EAC6E;AAC7E,MAAM,UAAU,sBAAsB,CAAC,GAAW;IAChD,IAAI,GAAG,CAAC,SAAS;QAAE,OAAO,GAAG,CAAC,SAAS,CAAC;IACxC,IAAI,GAAG,CAAC,OAAO;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;IACzD,MAAM,IAAI,KAAK,CACb,0EAA0E;QAC1E,kDAAkD,CACnD,CAAC;AACJ,CAAC;AAED,MAAM,WAAW,GAAG,GAAW,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,aAAa,CAAC,CAAC;AAElE,MAAM,UAAU,YAAY;IAC1B,OAAO,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,IAAI,GAAG,WAAW,EAAE,CAAC;IAC3B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,sBAAsB,IAAI,6CAA6C,CACxE,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAW,CAAC;IAC3E,IAAI,MAAM,CAAC,cAAc,KAAK,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,sCAAsC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,MAAM,IAAI,GAAG,WAAW,EAAE,CAAC;IAC3B,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAAE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9E,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,oEAAoE;IACpE,4CAA4C;IAC5C,OAAO,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAe,EAAE,WAAoB;IACtE,OAAO;QACL,cAAc,EAAE,CAAC;QACjB,OAAO;QACP,WAAW,EAAE,WAAW,IAAI,kBAAkB,EAAE;KACjD,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,MAAM,WAAW,UAAU;IACzB,cAAc,EAAE,CAAC,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB;;gBAEY;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB;uBACmB;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB;2EACuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB;4DACwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,sBAAsB,EAAG,CAAU,CAAC;AAEjD,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC,GAAG,UAAU,CAKhF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAKxD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAwCnD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAEvD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAEpE"}
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAKH,MAAM,WAAW,UAAU;IACzB,cAAc,EAAE,CAAC,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB;;gBAEY;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB;uBACmB;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB;2EACuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB;4DACwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,sBAAsB,EAAG,CAAU,CAAC;AAEjD,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC,GAAG,UAAU,CAKhF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAKxD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAwCnD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAEvD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAEpE"}
package/dist/format.js CHANGED
@@ -23,6 +23,7 @@
23
23
  * rather than silently dropping fields.
24
24
  */
25
25
  import { readFileSync, writeFileSync } from 'node:fs';
26
+ import { stripBom } from './project.js';
26
27
  export const CURRENT_SCHEMA_VERSION = 1;
27
28
  export function buildCcsync(opts) {
28
29
  return {
@@ -39,7 +40,7 @@ export function serializeCcsync(file) {
39
40
  export function parseCcsync(raw) {
40
41
  let parsed;
41
42
  try {
42
- parsed = JSON.parse(raw);
43
+ parsed = JSON.parse(stripBom(raw));
43
44
  }
44
45
  catch (err) {
45
46
  throw new Error(`Not a valid .ccsync file (JSON parse failed): ${err instanceof Error ? err.message : err}`);
@@ -1 +1 @@
1
- {"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAuBtD,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAU,CAAC;AAEjD,MAAM,UAAU,WAAW,CAAC,IAAwC;IAClE,OAAO;QACL,cAAc,EAAE,sBAAsB;QACtC,GAAG,IAAI;KACR,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAgB;IAC9C,iEAAiE;IACjE,mEAAmE;IACnE,kBAAkB;IAClB,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,iDAAiD,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IAC/G,CAAC;IACD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IACD,MAAM,GAAG,GAAG,MAAiC,CAAC;IAC9C,MAAM,GAAG,GAAG,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAClC,IAAI,GAAG,KAAK,sBAAsB,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,uCAAuC,GAAG,IAAI;YAC9C,4CAA4C,sBAAsB,IAAI;YACtE,0CAA0C,CAC3C,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GAAoC;QAChD,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO;KAC5F,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,GAAG,CAAC,CAAC;IAC5F,CAAC;IACD,2EAA2E;IAC3E,yEAAyE;IACzE,gFAAgF;IAChF,2EAA2E;IAC3E,iDAAiD;IACjD,MAAM,UAAU,GAAG;QACjB,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ;QAChE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ;KACzE,CAAC;IACX,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QAChD,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,eAAe,CAAC,SAAS,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/F,CAAC;IACH,CAAC;IACD,OAAO,GAA4B,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,WAAW,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,IAAgB;IAC5D,aAAa,CAAC,IAAI,EAAE,eAAe,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC9D,CAAC"}
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -7,11 +7,12 @@
7
7
  * GitHub Action that snapshots sessions, or an alternative transport
8
8
  * (S3, gist, custom relay).
9
9
  */
10
- export { encodeProjectDir, claudeProjectsRoot, syncRoot, gitRemoteUrl, projectKey, loadRegistry, saveRegistry, registerProject, lookupCwd, type ProjectRegistry, } from './project.js';
11
- export { listSessions, readSession, writeSession, assignFreshId, type SessionMetadata, } from './session.js';
10
+ export { encodeProjectDir, stripBom, claudeProjectsRoot, syncRoot, gitRemoteUrl, normalizeGitRemote, projectKey, loadRegistry, saveRegistry, registerProject, registerProjectKey, lookupCwd, type ProjectRegistry, } from './project.js';
11
+ export { listSessions, listSessionStats, countSessionLines, readSession, writeSession, assignFreshId, type SessionMetadata, type SessionStat, } from './session.js';
12
12
  export { buildCcsync, serializeCcsync, parseCcsync, readCcsyncFile, writeCcsyncFile, CURRENT_SCHEMA_VERSION, type CcsyncFile, } from './format.js';
13
- export { loadConfig, saveConfig, configExists, defaultMachineName, buildDefaultConfig, type Config, } from './config.js';
14
- export { projectSubdir, pushToTransport, listTransport, listProjectKeys, type TransportEntry, } from './transport.js';
13
+ export { loadConfig, saveConfig, configExists, defaultMachineName, buildDefaultConfig, resolveTransportConfig, type Config, type TransportConfig, } from './config.js';
14
+ export { projectSubdir, pushToTransport, listTransport, listTransportMachines, listProjectKeys, createTransport, FsTransport, type Transport, type TransportEntry, type TransportHealth, } from './transport.js';
15
+ export { SshTransport, realSshExecutor, buildSshArgs, shQuote, posixJoin, type SshExecutor, type SshExecResult, type SshConfig, } from './ssh.js';
15
16
  /** Single source of truth: read the version straight from package.json
16
17
  * so the published version can never drift from the runtime/CLI banner.
17
18
  * dist layout is `dist/index.js`, so `../package.json` resolves to the
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,SAAS,EACT,KAAK,eAAe,GACrB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,aAAa,EACb,KAAK,eAAe,GACrB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,WAAW,EACX,eAAe,EACf,WAAW,EACX,cAAc,EACd,eAAe,EACf,sBAAsB,EACtB,KAAK,UAAU,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,UAAU,EACV,UAAU,EACV,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,KAAK,MAAM,GACZ,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,aAAa,EACb,eAAe,EACf,aAAa,EACb,eAAe,EACf,KAAK,cAAc,GACpB,MAAM,gBAAgB,CAAC;AAExB;;;8CAG8C;AAC9C,eAAO,MAAM,OAAO,EAAE,MAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EACL,gBAAgB,EAChB,QAAQ,EACR,kBAAkB,EAClB,QAAQ,EACR,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,SAAS,EACT,KAAK,eAAe,GACrB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,aAAa,EACb,KAAK,eAAe,EACpB,KAAK,WAAW,GACjB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,WAAW,EACX,eAAe,EACf,WAAW,EACX,cAAc,EACd,eAAe,EACf,sBAAsB,EACtB,KAAK,UAAU,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,UAAU,EACV,UAAU,EACV,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,KAAK,MAAM,EACX,KAAK,eAAe,GACrB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,aAAa,EACb,eAAe,EACf,aAAa,EACb,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,WAAW,EACX,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,OAAO,EACP,SAAS,EACT,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,SAAS,GACf,MAAM,UAAU,CAAC;AAElB;;;8CAG8C;AAC9C,eAAO,MAAM,OAAO,EAAE,MAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -8,11 +8,12 @@
8
8
  * (S3, gist, custom relay).
9
9
  */
10
10
  import pkg from '../package.json' with { type: 'json' };
11
- export { encodeProjectDir, claudeProjectsRoot, syncRoot, gitRemoteUrl, projectKey, loadRegistry, saveRegistry, registerProject, lookupCwd, } from './project.js';
12
- export { listSessions, readSession, writeSession, assignFreshId, } from './session.js';
11
+ export { encodeProjectDir, stripBom, claudeProjectsRoot, syncRoot, gitRemoteUrl, normalizeGitRemote, projectKey, loadRegistry, saveRegistry, registerProject, registerProjectKey, lookupCwd, } from './project.js';
12
+ export { listSessions, listSessionStats, countSessionLines, readSession, writeSession, assignFreshId, } from './session.js';
13
13
  export { buildCcsync, serializeCcsync, parseCcsync, readCcsyncFile, writeCcsyncFile, CURRENT_SCHEMA_VERSION, } from './format.js';
14
- export { loadConfig, saveConfig, configExists, defaultMachineName, buildDefaultConfig, } from './config.js';
15
- export { projectSubdir, pushToTransport, listTransport, listProjectKeys, } from './transport.js';
14
+ export { loadConfig, saveConfig, configExists, defaultMachineName, buildDefaultConfig, resolveTransportConfig, } from './config.js';
15
+ export { projectSubdir, pushToTransport, listTransport, listTransportMachines, listProjectKeys, createTransport, FsTransport, } from './transport.js';
16
+ export { SshTransport, realSshExecutor, buildSshArgs, shQuote, posixJoin, } from './ssh.js';
16
17
  /** Single source of truth: read the version straight from package.json
17
18
  * so the published version can never drift from the runtime/CLI banner.
18
19
  * dist layout is `dist/index.js`, so `../package.json` resolves to the
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,GAAG,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAExD,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,SAAS,GAEV,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,aAAa,GAEd,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,WAAW,EACX,eAAe,EACf,WAAW,EACX,cAAc,EACd,eAAe,EACf,sBAAsB,GAEvB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,UAAU,EACV,UAAU,EACV,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,GAEnB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,aAAa,EACb,eAAe,EACf,aAAa,EACb,eAAe,GAEhB,MAAM,gBAAgB,CAAC;AAExB;;;8CAG8C;AAC9C,MAAM,CAAC,MAAM,OAAO,GAAW,GAAG,CAAC,OAAO,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,GAAG,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAExD,OAAO,EACL,gBAAgB,EAChB,QAAQ,EACR,kBAAkB,EAClB,QAAQ,EACR,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,SAAS,GAEV,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,aAAa,GAGd,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,WAAW,EACX,eAAe,EACf,WAAW,EACX,cAAc,EACd,eAAe,EACf,sBAAsB,GAEvB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,UAAU,EACV,UAAU,EACV,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,GAGvB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,aAAa,EACb,eAAe,EACf,aAAa,EACb,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,WAAW,GAIZ,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,OAAO,EACP,SAAS,GAIV,MAAM,UAAU,CAAC;AAElB;;;8CAG8C;AAC9C,MAAM,CAAC,MAAM,OAAO,GAAW,GAAG,CAAC,OAAO,CAAC"}
package/dist/project.d.ts CHANGED
@@ -18,6 +18,12 @@
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
+ /** Strip a leading UTF-8 BOM (``) if present. Windows editors
22
+ * (Notepad, some PowerShell `Set-Content` modes) prepend one, and
23
+ * `JSON.parse` rejects it with a cryptic "Unexpected token" — so a user
24
+ * who hand-edits config.json / projects.json on Windows would otherwise
25
+ * crash every command. We tolerate it on read. */
26
+ export declare function stripBom(s: string): string;
21
27
  /** Encode a cwd into Claude Code's project-directory format. CC replaces
22
28
  * EACH non-alphanumeric character with a single `-` (no run-collapsing),
23
29
  * so `C:\Users\me\my app` → `C--Users-me-my-app` and `/root/.askalf/x`
@@ -49,16 +55,36 @@ export declare function syncRoot(): string;
49
55
  * - the repo has no remote configured (greenfield, not yet pushed)
50
56
  *
51
57
  * Trims trailing whitespace + newlines but otherwise leaves the URL
52
- * exactly as `git` reported. We use it as a key, not a URL — so
53
- * `git@github.com:owner/repo.git` and `https://github.com/owner/repo.git`
54
- * for the same logical repo will NOT match. The user can fix that by
55
- * normalizing one of the two via `git remote set-url`, or by manually
56
- * registering both in the project registry under one canonical key. */
58
+ * exactly as `git` reported. `projectKey` runs the result through
59
+ * `normalizeGitRemote` so the same repo over SSH and HTTPS resolves to a
60
+ * single key. */
57
61
  export declare function gitRemoteUrl(cwd: string): string | null;
62
+ /** Canonicalize a git remote URL so the same repo addressed over
63
+ * different protocols resolves to ONE project key. These all collapse to
64
+ * `github.com/owner/repo`:
65
+ *
66
+ * https://github.com/owner/repo.git
67
+ * https://github.com/owner/repo
68
+ * git@github.com:owner/repo.git (scp-like syntax)
69
+ * ssh://git@github.com/owner/repo.git
70
+ * git://github.com/owner/repo.git
71
+ *
72
+ * The host is lowercased (DNS is case-insensitive); the repo path keeps
73
+ * its case (some forges are case-sensitive). A `git@`/`user@` prefix and
74
+ * any explicit port are dropped — they don't change repo identity — and a
75
+ * single trailing `.git` plus surrounding slashes are trimmed.
76
+ *
77
+ * Anything that doesn't parse as one of these shapes (a bare local path,
78
+ * `file://`, an exotic transport) is returned trimmed-but-otherwise
79
+ * unchanged, so we only ever *canonicalize* the common cases — never lose
80
+ * a key by mangling one we don't recognize. */
81
+ export declare function normalizeGitRemote(url: string): string;
58
82
  /** Compute a stable, machine-portable project key for a cwd. Prefers the
59
- * git remote URL; falls back to the directory basename when no remote
60
- * is configured. The basename fallback is best-effort collisions
61
- * between unrelated projects with the same name are possible. */
83
+ * git remote URL (canonicalized via `normalizeGitRemote`, so SSH and
84
+ * HTTPS clones of the same repo share a key); falls back to the directory
85
+ * basename when no remote is configured. The basename fallback is
86
+ * best-effort — collisions between unrelated projects with the same name
87
+ * are possible. */
62
88
  export declare function projectKey(cwd: string): string;
63
89
  /** Local-project registry. Maps a project key to the local cwd on this
64
90
  * machine. Built up as the user runs `claude-sync export` (which
@@ -77,6 +103,11 @@ export interface ProjectRegistry {
77
103
  }
78
104
  export declare function loadRegistry(): ProjectRegistry;
79
105
  export declare function saveRegistry(reg: ProjectRegistry): void;
106
+ /** Register a cwd under an explicit project key. Idempotent. Used by
107
+ * `import` to bind a *peer's* project key to a local directory so later
108
+ * `pull`s resolve it — even when this machine isn't a git repo for that
109
+ * path, or computes the key slightly differently. */
110
+ export declare function registerProjectKey(key: string, cwd: string): ProjectRegistry;
80
111
  /** Register a cwd under its computed project key. Idempotent; pushing
81
112
  * the same cwd twice doesn't create duplicates. */
82
113
  export declare function registerProject(cwd: string): {
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAOH;;;;mDAImD;AACnD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1C;AAED;;;;;;;;;;;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;;;;;;;;iBAQiB;AACjB,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAavD;AAED;;;;;;;;;;;;;;;;;;gDAkBgD;AAChD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA0CtD;AAED;;;;;oBAKoB;AACpB,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;;;sDAGsD;AACtD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,eAAe,CAQ5E;AAED;oDACoD;AACpD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,eAAe,CAAA;CAAE,CAIvF;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,6 +22,14 @@ 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
+ /** Strip a leading UTF-8 BOM (``) if present. Windows editors
26
+ * (Notepad, some PowerShell `Set-Content` modes) prepend one, and
27
+ * `JSON.parse` rejects it with a cryptic "Unexpected token" — so a user
28
+ * who hand-edits config.json / projects.json on Windows would otherwise
29
+ * crash every command. We tolerate it on read. */
30
+ export function stripBom(s) {
31
+ return s.charCodeAt(0) === 0xfeff ? s.slice(1) : s;
32
+ }
25
33
  /** Encode a cwd into Claude Code's project-directory format. CC replaces
26
34
  * EACH non-alphanumeric character with a single `-` (no run-collapsing),
27
35
  * so `C:\Users\me\my app` → `C--Users-me-my-app` and `/root/.askalf/x`
@@ -61,11 +69,9 @@ export function syncRoot() {
61
69
  * - the repo has no remote configured (greenfield, not yet pushed)
62
70
  *
63
71
  * Trims trailing whitespace + newlines but otherwise leaves the URL
64
- * exactly as `git` reported. We use it as a key, not a URL — so
65
- * `git@github.com:owner/repo.git` and `https://github.com/owner/repo.git`
66
- * for the same logical repo will NOT match. The user can fix that by
67
- * normalizing one of the two via `git remote set-url`, or by manually
68
- * registering both in the project registry under one canonical key. */
72
+ * exactly as `git` reported. `projectKey` runs the result through
73
+ * `normalizeGitRemote` so the same repo over SSH and HTTPS resolves to a
74
+ * single key. */
69
75
  export function gitRemoteUrl(cwd) {
70
76
  if (!existsSync(join(cwd, '.git')))
71
77
  return null;
@@ -82,14 +88,83 @@ export function gitRemoteUrl(cwd) {
82
88
  return null;
83
89
  }
84
90
  }
91
+ /** Canonicalize a git remote URL so the same repo addressed over
92
+ * different protocols resolves to ONE project key. These all collapse to
93
+ * `github.com/owner/repo`:
94
+ *
95
+ * https://github.com/owner/repo.git
96
+ * https://github.com/owner/repo
97
+ * git@github.com:owner/repo.git (scp-like syntax)
98
+ * ssh://git@github.com/owner/repo.git
99
+ * git://github.com/owner/repo.git
100
+ *
101
+ * The host is lowercased (DNS is case-insensitive); the repo path keeps
102
+ * its case (some forges are case-sensitive). A `git@`/`user@` prefix and
103
+ * any explicit port are dropped — they don't change repo identity — and a
104
+ * single trailing `.git` plus surrounding slashes are trimmed.
105
+ *
106
+ * Anything that doesn't parse as one of these shapes (a bare local path,
107
+ * `file://`, an exotic transport) is returned trimmed-but-otherwise
108
+ * unchanged, so we only ever *canonicalize* the common cases — never lose
109
+ * a key by mangling one we don't recognize. */
110
+ export function normalizeGitRemote(url) {
111
+ const raw = url.trim();
112
+ let host;
113
+ let path;
114
+ if (/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(raw)) {
115
+ // scheme://[user@]host[:port]/path
116
+ try {
117
+ const u = new URL(raw);
118
+ host = u.hostname;
119
+ path = u.pathname;
120
+ }
121
+ catch {
122
+ return raw;
123
+ }
124
+ }
125
+ else {
126
+ // scp-like: [user@]host:path (e.g. git@github.com:owner/repo.git).
127
+ // Requires a colon and a path with no leading slash — a bare local
128
+ // path like /srv/git/repo.git has no colon and falls through.
129
+ const m = /^(?:[^@/]+@)?([^/:]+):(.+)$/.exec(raw);
130
+ if (m) {
131
+ host = m[1];
132
+ path = m[2];
133
+ }
134
+ else {
135
+ return raw;
136
+ }
137
+ }
138
+ if (!host || !path)
139
+ return raw;
140
+ // Trim surrounding slashes and a single trailing `.git`, WITHOUT a
141
+ // backtracking regex: `/\/+$/` on a remote URL we don't control is a
142
+ // polynomial-ReDoS vector (flagged by CodeQL). A linear two-pointer
143
+ // trim + an endsWith check is both safe and clearer.
144
+ let lo = 0;
145
+ let hi = path.length;
146
+ while (lo < hi && path[lo] === '/')
147
+ lo++;
148
+ while (hi > lo && path[hi - 1] === '/')
149
+ hi--;
150
+ let cleanPath = path.slice(lo, hi);
151
+ if (cleanPath.toLowerCase().endsWith('.git')) {
152
+ cleanPath = cleanPath.slice(0, -4);
153
+ }
154
+ if (!cleanPath)
155
+ return raw;
156
+ return `${host.toLowerCase()}/${cleanPath}`;
157
+ }
85
158
  /** Compute a stable, machine-portable project key for a cwd. Prefers the
86
- * git remote URL; falls back to the directory basename when no remote
87
- * is configured. The basename fallback is best-effort collisions
88
- * between unrelated projects with the same name are possible. */
159
+ * git remote URL (canonicalized via `normalizeGitRemote`, so SSH and
160
+ * HTTPS clones of the same repo share a key); falls back to the directory
161
+ * basename when no remote is configured. The basename fallback is
162
+ * best-effort — collisions between unrelated projects with the same name
163
+ * are possible. */
89
164
  export function projectKey(cwd) {
90
165
  const remote = gitRemoteUrl(cwd);
91
166
  if (remote)
92
- return `git:${remote}`;
167
+ return `git:${normalizeGitRemote(remote)}`;
93
168
  return `name:${basename(cwd)}`;
94
169
  }
95
170
  const REGISTRY_PATH = () => join(syncRoot(), 'projects.json');
@@ -103,7 +178,7 @@ export function loadRegistry() {
103
178
  };
104
179
  }
105
180
  try {
106
- const raw = readFileSync(path, 'utf-8');
181
+ const raw = stripBom(readFileSync(path, 'utf-8'));
107
182
  const parsed = JSON.parse(raw);
108
183
  if (parsed._schemaVersion !== 1) {
109
184
  throw new Error(`Unsupported registry schema version: ${parsed._schemaVersion}`);
@@ -126,17 +201,25 @@ export function saveRegistry(reg) {
126
201
  // close enough for our uses (no concurrent registry writers).
127
202
  renameSync(tmp, path);
128
203
  }
129
- /** Register a cwd under its computed project key. Idempotent; pushing
130
- * the same cwd twice doesn't create duplicates. */
131
- export function registerProject(cwd) {
204
+ /** Register a cwd under an explicit project key. Idempotent. Used by
205
+ * `import` to bind a *peer's* project key to a local directory so later
206
+ * `pull`s resolve it — even when this machine isn't a git repo for that
207
+ * path, or computes the key slightly differently. */
208
+ export function registerProjectKey(key, cwd) {
132
209
  const reg = loadRegistry();
133
- const key = projectKey(cwd);
134
210
  const existing = reg.projects[key] ?? [];
135
211
  if (!existing.includes(cwd)) {
136
212
  reg.projects[key] = [...existing, cwd];
137
213
  saveRegistry(reg);
138
214
  }
139
- return { key, registry: reg };
215
+ return reg;
216
+ }
217
+ /** Register a cwd under its computed project key. Idempotent; pushing
218
+ * the same cwd twice doesn't create duplicates. */
219
+ export function registerProject(cwd) {
220
+ const key = projectKey(cwd);
221
+ const registry = registerProjectKey(key, cwd);
222
+ return { key, registry };
140
223
  }
141
224
  /** Look up a local cwd for a given project key. Returns the first
142
225
  * registered match (registries are user-edited; they can reorder if
@@ -1 +1 @@
1
- {"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
package/dist/session.d.ts CHANGED
@@ -8,7 +8,7 @@
8
8
  * needing claude-sync changes.
9
9
  */
10
10
  import { basename } from 'node:path';
11
- export interface SessionMetadata {
11
+ export interface SessionStat {
12
12
  id: string;
13
13
  /** Local file path. Useful for the CLI to print where it found / put
14
14
  * a session, but not part of the wire format — paths don't transfer
@@ -17,15 +17,23 @@ export interface SessionMetadata {
17
17
  /** Bytes on disk. */
18
18
  size: number;
19
19
  /** Wall-clock mtime. Used to break ties when picking "the most recent
20
- * session" for a project. */
20
+ * session" for a project — and to detect change cheaply in watch mode. */
21
21
  modifiedAt: number;
22
+ }
23
+ export interface SessionMetadata extends SessionStat {
22
24
  /** Number of newline-terminated JSONL records. Cheap proxy for
23
25
  * message count — the CC schema means roughly one event per line. */
24
26
  lineCount: number;
25
27
  }
26
- /** List sessions for a given local cwd. Returns [] if the project dir
27
- * doesn't exist (no sessions yet). Sorted by mtime descending so the
28
- * caller can grab `[0]` for "the most recent session". */
28
+ /** Stat-only listing for a cwd id, path, size, mtime, no line count.
29
+ * Returns [] if the project dir doesn't exist. Sorted by mtime
30
+ * descending. This is the cheap path: watch mode polls it every tick to
31
+ * spot changed sessions WITHOUT reading every file's contents to count
32
+ * lines (which `listSessions` does). */
33
+ export declare function listSessionStats(cwd: string): SessionStat[];
34
+ /** List sessions for a given local cwd, including line counts. Returns []
35
+ * if the project dir doesn't exist (no sessions yet). Sorted by mtime
36
+ * descending so the caller can grab `[0]` for "the most recent session". */
29
37
  export declare function listSessions(cwd: string): SessionMetadata[];
30
38
  /** Read a session's JSONL content. Returned as the raw bytes (no parse)
31
39
  * so we don't have to know about CC's evolving message schema. */
@@ -50,5 +58,9 @@ export declare function writeSession(targetCwd: string, sessionId: string, jsonl
50
58
  * practice; we mint a new one in the same shape so resume-by-id works
51
59
  * consistently. */
52
60
  export declare function assignFreshId(targetCwd: string, baseId: string): string;
61
+ /** Count newline-terminated records in a session file. Exported for watch
62
+ * mode, which counts lines only for the handful of sessions that changed
63
+ * since the last tick (the bulk listing stays on `listSessionStats`). */
64
+ export declare function countSessionLines(path: string): number;
53
65
  export { basename as fileBasename };
54
66
  //# sourceMappingURL=session.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EAAQ,QAAQ,EAAE,MAAM,WAAW,CAAC;AAG3C,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX;;2BAEuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb;kCAC8B;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB;0EACsE;IACtE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;2DAE2D;AAC3D,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,EAAE,CAsB3D;AAED;mEACmE;AACnE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAWD;;qDAEqD;AACrD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAgB3D;AAED;;;;;;;0BAO0B;AAC1B,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,MAAM,CAqBR;AAED;;;oBAGoB;AACpB,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CASvE;AAsBD,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EAAQ,QAAQ,EAAE,MAAM,WAAW,CAAC;AAG3C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX;;2BAEuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb;+EAC2E;IAC3E,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAgB,SAAQ,WAAW;IAClD;0EACsE;IACtE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;yCAIyC;AACzC,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,EAAE,CAqB3D;AAED;;6EAE6E;AAC7E,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,EAAE,CAE3D;AAED;mEACmE;AACnE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAWD;;qDAEqD;AACrD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAgB3D;AAED;;;;;;;0BAO0B;AAC1B,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,MAAM,CAqBR;AAED;;;oBAGoB;AACpB,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CASvE;AAED;;0EAE0E;AAC1E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAsBD,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,CAAC"}
package/dist/session.js CHANGED
@@ -10,30 +10,37 @@
10
10
  import { existsSync, readdirSync, readFileSync, writeFileSync, mkdirSync, statSync, openSync, readSync, closeSync, renameSync, } from 'node:fs';
11
11
  import { join, basename } from 'node:path';
12
12
  import { claudeProjectsRoot, encodeProjectDir } from './project.js';
13
- /** List sessions for a given local cwd. Returns [] if the project dir
14
- * doesn't exist (no sessions yet). Sorted by mtime descending so the
15
- * caller can grab `[0]` for "the most recent session". */
16
- export function listSessions(cwd) {
13
+ /** Stat-only listing for a cwd id, path, size, mtime, no line count.
14
+ * Returns [] if the project dir doesn't exist. Sorted by mtime
15
+ * descending. This is the cheap path: watch mode polls it every tick to
16
+ * spot changed sessions WITHOUT reading every file's contents to count
17
+ * lines (which `listSessions` does). */
18
+ export function listSessionStats(cwd) {
17
19
  const projDir = join(claudeProjectsRoot(), encodeProjectDir(cwd));
18
20
  if (!existsSync(projDir))
19
21
  return [];
20
22
  const entries = readdirSync(projDir, { withFileTypes: true });
21
- const sessions = [];
23
+ const stats = [];
22
24
  for (const entry of entries) {
23
25
  if (!entry.isFile() || !entry.name.endsWith('.jsonl'))
24
26
  continue;
25
27
  const path = join(projDir, entry.name);
26
- const stats = statSync(path);
27
- sessions.push({
28
+ const st = statSync(path);
29
+ stats.push({
28
30
  id: entry.name.replace(/\.jsonl$/, ''),
29
31
  path,
30
- size: stats.size,
31
- modifiedAt: stats.mtimeMs,
32
- lineCount: countLines(path),
32
+ size: st.size,
33
+ modifiedAt: st.mtimeMs,
33
34
  });
34
35
  }
35
- sessions.sort((a, b) => b.modifiedAt - a.modifiedAt);
36
- return sessions;
36
+ stats.sort((a, b) => b.modifiedAt - a.modifiedAt);
37
+ return stats;
38
+ }
39
+ /** List sessions for a given local cwd, including line counts. Returns []
40
+ * if the project dir doesn't exist (no sessions yet). Sorted by mtime
41
+ * descending so the caller can grab `[0]` for "the most recent session". */
42
+ export function listSessions(cwd) {
43
+ return listSessionStats(cwd).map((s) => ({ ...s, lineCount: countLines(s.path) }));
37
44
  }
38
45
  /** Read a session's JSONL content. Returned as the raw bytes (no parse)
39
46
  * so we don't have to know about CC's evolving message schema. */
@@ -108,6 +115,12 @@ export function assignFreshId(targetCwd, baseId) {
108
115
  n++;
109
116
  return `${baseId}-copy${n === 1 ? '' : `-${n}`}`;
110
117
  }
118
+ /** Count newline-terminated records in a session file. Exported for watch
119
+ * mode, which counts lines only for the handful of sessions that changed
120
+ * since the last tick (the bulk listing stays on `listSessionStats`). */
121
+ export function countSessionLines(path) {
122
+ return countLines(path);
123
+ }
111
124
  function countLines(path) {
112
125
  // Fast newline count without buffering the whole file as a string —
113
126
  // sessions can be large.
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
package/dist/ssh.d.ts ADDED
@@ -0,0 +1,66 @@
1
+ /**
2
+ * SSH transport — `.ccsync` files live in a directory on a remote host,
3
+ * reached over SSH. The target audience is "I run Claude Code on a dev
4
+ * server AND on my laptop"; the round-trip validation showed manual `scp`
5
+ * shuttling was the real friction, so this makes the remote box a
6
+ * first-class transport.
7
+ *
8
+ * Mechanics: every operation is one (or a few) `ssh host <command>` calls,
9
+ * where <command> is a small POSIX shell pipeline (mkdir / cat / mv /
10
+ * find). The remote layout is identical to the filesystem transport —
11
+ * `<dir>/<encoded-project-key>/<sessionId>-<machine>.ccsync` — so the two
12
+ * backends are wire-compatible (a server on `fs` and a laptop on `ssh`
13
+ * pointed at the same dir sync cleanly).
14
+ *
15
+ * Quoting: ssh concatenates its command args with spaces and hands the
16
+ * result to the remote login shell, which re-parses it. So every
17
+ * interpolated value is POSIX single-quoted via `shQuote`; file *lists*
18
+ * are never interpolated (we `find` them remotely and read by path).
19
+ *
20
+ * Testability: the actual `ssh` invocation sits behind `SshExecutor`.
21
+ * Tests inject a fake executor (to assert command construction) or a
22
+ * local-shell executor (to run the real pipelines against a temp dir
23
+ * without an sshd). `realSshExecutor` is the production one.
24
+ */
25
+ import { type CcsyncFile } from './format.js';
26
+ import type { Transport, TransportEntry, TransportHealth } from './transport.js';
27
+ import type { TransportConfig } from './config.js';
28
+ /** The `ssh` member of the transport-config union. */
29
+ export type SshConfig = Extract<TransportConfig, {
30
+ type: 'ssh';
31
+ }>;
32
+ export interface SshExecResult {
33
+ status: number;
34
+ stdout: string;
35
+ stderr: string;
36
+ }
37
+ /** Runs a single command on the remote host, optionally piping `input` to
38
+ * its stdin, and returns the captured result. The production impl shells
39
+ * out to `ssh`; tests inject fakes. */
40
+ export interface SshExecutor {
41
+ run(remoteCommand: string, input?: string): SshExecResult;
42
+ }
43
+ /** POSIX single-quote `s` for safe interpolation into a remote shell
44
+ * command: wrap in '…' and rewrite each embedded ' as '\'' . */
45
+ export declare function shQuote(s: string): string;
46
+ /** Join remote (POSIX) path segments with `/`, trimming stray slashes but
47
+ * preserving a leading `/` on the first segment (absolute remote dirs). */
48
+ export declare function posixJoin(...parts: string[]): string;
49
+ /** Build the `ssh` argv (everything before the remote command). Pure +
50
+ * exported so it can be unit-tested without spawning. */
51
+ export declare function buildSshArgs(cfg: SshConfig, controlPath?: string): string[];
52
+ /** Production executor: shells out to the system `ssh`. */
53
+ export declare function realSshExecutor(cfg: SshConfig): SshExecutor;
54
+ export declare class SshTransport implements Transport {
55
+ private readonly cfg;
56
+ private readonly exec;
57
+ constructor(cfg: SshConfig, exec?: SshExecutor);
58
+ describe(): string;
59
+ push(file: CcsyncFile): string;
60
+ listProjectKeys(): string[];
61
+ listEntries(projectKey: string, selfMachineName: string): TransportEntry[];
62
+ listMachines(): Map<string, number>;
63
+ health(): TransportHealth;
64
+ private readFile;
65
+ }
66
+ //# sourceMappingURL=ssh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh.d.ts","sourceRoot":"","sources":["../src/ssh.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAOH,OAAO,EAAgC,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,sDAAsD;AACtD,MAAM,MAAM,SAAS,GAAG,OAAO,CAAC,eAAe,EAAE;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAElE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;wCAEwC;AACxC,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;CAC3D;AAED;iEACiE;AACjE,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzC;AAaD;4EAC4E;AAC5E,wBAAgB,SAAS,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAKpD;AAMD;0DAC0D;AAC1D,wBAAgB,YAAY,CAAC,GAAG,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAkB3E;AAcD,2DAA2D;AAC3D,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,GAAG,WAAW,CAa3D;AAiBD,qBAAa,YAAa,YAAW,SAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAY;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;gBAEvB,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,WAAW;IAK9C,QAAQ,IAAI,MAAM;IAMlB,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM;IAgB9B,eAAe,IAAI,MAAM,EAAE;IAO3B,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,cAAc,EAAE;IAyB1E,YAAY,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAmBnC,MAAM,IAAI,eAAe;IAYzB,OAAO,CAAC,QAAQ;CAIjB"}