@cocorograph/hub-agent 0.6.60 → 0.6.61
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/package.json +1 -1
- package/src/profiles.mjs +79 -1
package/package.json
CHANGED
package/src/profiles.mjs
CHANGED
|
@@ -3,10 +3,16 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 1 台のマシンで複数の Claude アカウント (例: 個人 Max / チーム) を `CLAUDE_CONFIG_DIR`
|
|
5
5
|
* で切り替えて使うための仕組み。各プロファイルは独立した config ディレクトリを持ち、
|
|
6
|
-
*
|
|
6
|
+
* 認証 (`.credentials.json` / Keychain) と `.claude.json` をアカウント別に保持する。一方で
|
|
7
7
|
* skills / agents / commands / scripts / hooks / CLAUDE.md は symlink で共有し、
|
|
8
8
|
* settings.json はコピーで共有する (provisionProfile が面倒を見る)。
|
|
9
9
|
*
|
|
10
|
+
* 会話履歴 (`projects/`) は **既定 `~/.claude/projects` に集約して全プロファイルで共有する**
|
|
11
|
+
* (ensureSharedProjects が `<configDir>/projects` を既定への symlink にする)。同じ作業
|
|
12
|
+
* ディレクトリの会話コンテキストがアカウントをまたいで引き継げるようにするため。新規
|
|
13
|
+
* プロファイルは単純に symlink を張るだけ。既存の実体 `projects/` がある場合は無損失で
|
|
14
|
+
* 既定へマージ (no-clobber) してからバックアップ退避し symlink 化する。
|
|
15
|
+
*
|
|
10
16
|
* 設計方針 (重要):
|
|
11
17
|
* - 既定 (プライマリ) プロファイルは **常に `~/.claude`**。リネーム・移動しない。
|
|
12
18
|
* profiles.json が存在しない単一アカウント利用者は、この仕組みに一切触れずに
|
|
@@ -259,6 +265,67 @@ export const SHARED_SYMLINK_ITEMS = [
|
|
|
259
265
|
/** コピーで共有する資産 (アプリが書き換えるため symlink 不可)。 */
|
|
260
266
|
export const SHARED_COPY_ITEMS = ["settings.json"]
|
|
261
267
|
|
|
268
|
+
/**
|
|
269
|
+
* 会話履歴 (`projects/`) を既定 `~/.claude/projects` に集約・共有する。
|
|
270
|
+
*
|
|
271
|
+
* - 既定プロファイル自身 (configDir === ~/.claude) は集約元なので何もしない。
|
|
272
|
+
* - `<configDir>/projects` が既に既定への symlink なら冪等に何もしない。
|
|
273
|
+
* - 実体ディレクトリが存在する場合: 中身を no-clobber で既定へマージ (履歴を 1 件も
|
|
274
|
+
* 失わない)、元ディレクトリを `projects.premigrate-backup[-n]` に退避してから symlink 化。
|
|
275
|
+
* - 何も無ければ素直に既定への symlink を張る。
|
|
276
|
+
*
|
|
277
|
+
* @param {string} configDir - 対象プロファイルの config ディレクトリ絶対パス
|
|
278
|
+
* @returns {Promise<"self"|"already-linked"|"linked"|"merged">}
|
|
279
|
+
*/
|
|
280
|
+
export async function ensureSharedProjects(configDir) {
|
|
281
|
+
const canonical = path.join(defaultConfigDir(), "projects")
|
|
282
|
+
const link = path.join(configDir, "projects")
|
|
283
|
+
|
|
284
|
+
// 既定プロファイル自身は集約元。リンクで自己参照させない。
|
|
285
|
+
if (path.resolve(configDir) === defaultConfigDir()) return "self"
|
|
286
|
+
|
|
287
|
+
// 集約先を必ず用意しておく (空でも symlink 先として有効にするため)。
|
|
288
|
+
await fs.mkdir(canonical, { recursive: true, mode: 0o700 })
|
|
289
|
+
|
|
290
|
+
let st = null
|
|
291
|
+
try {
|
|
292
|
+
st = await fs.lstat(link)
|
|
293
|
+
} catch {
|
|
294
|
+
/* not exists */
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (st && st.isSymbolicLink()) {
|
|
298
|
+
// 既に symlink。既定を指していればそのまま (冪等)。別の場所を指していても
|
|
299
|
+
// 履歴の所在を勝手に変えるのは危険なので触らない。
|
|
300
|
+
return "already-linked"
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (!st) {
|
|
304
|
+
await fs.symlink(canonical, link)
|
|
305
|
+
return "linked"
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// 実体が存在 (通常はディレクトリ)。無損失マージ → バックアップ退避 → symlink 化。
|
|
309
|
+
// force:false + errorOnExist:false で既存ファイルはスキップ (no-clobber)。
|
|
310
|
+
await fs.cp(link, canonical, {
|
|
311
|
+
recursive: true,
|
|
312
|
+
force: false,
|
|
313
|
+
errorOnExist: false,
|
|
314
|
+
})
|
|
315
|
+
let backup = `${link}.premigrate-backup`
|
|
316
|
+
for (let i = 1; ; i++) {
|
|
317
|
+
try {
|
|
318
|
+
await fs.lstat(backup)
|
|
319
|
+
backup = `${link}.premigrate-backup-${i}`
|
|
320
|
+
} catch {
|
|
321
|
+
break
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
await fs.rename(link, backup)
|
|
325
|
+
await fs.symlink(canonical, link)
|
|
326
|
+
return "merged"
|
|
327
|
+
}
|
|
328
|
+
|
|
262
329
|
/**
|
|
263
330
|
* プロファイルディレクトリを整備する。
|
|
264
331
|
* - 共有 symlink 資産: 既定 `~/.claude/<item>` への絶対 symlink を張る (既存・実体があれば触らない)。
|
|
@@ -322,6 +389,17 @@ export async function provisionProfile(configDir) {
|
|
|
322
389
|
}
|
|
323
390
|
}
|
|
324
391
|
|
|
392
|
+
// 会話履歴は既定 ~/.claude/projects へ集約して共有する (アカウント間で会話
|
|
393
|
+
// コンテキストを引き継げるようにするため)。新規は素直に symlink、既存実体は
|
|
394
|
+
// 無損失マージしてから symlink 化する。
|
|
395
|
+
try {
|
|
396
|
+
const r = await ensureSharedProjects(configDir)
|
|
397
|
+
if (r === "linked" || r === "merged") linked.push(`projects(${r})`)
|
|
398
|
+
else skipped.push(`projects(${r})`)
|
|
399
|
+
} catch (err) {
|
|
400
|
+
skipped.push(`projects(失敗:${err?.code || err?.message || "error"})`)
|
|
401
|
+
}
|
|
402
|
+
|
|
325
403
|
return { linked, copied, skipped }
|
|
326
404
|
}
|
|
327
405
|
|