@cocorograph/hub-agent 0.7.89 → 0.7.90

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocorograph/hub-agent",
3
- "version": "0.7.89",
3
+ "version": "0.7.90",
4
4
  "description": "Hub Hosted Cockpit のローカル常駐 agent。Hub と outbound WSS で接続し、ローカルの tmux/pty を中継する。",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -26,12 +26,18 @@ import path from "node:path"
26
26
  import crypto from "node:crypto"
27
27
 
28
28
  const DEFAULT_HUB_API = "https://api.hub.cocorograph.com"
29
- const TOKEN_PATH = path.join(os.homedir(), ".claude", ".hub_token.json")
30
29
  const META_DIR = ".cockpit-sync"
31
- const META_FILE = "claude-md.json"
32
- const BASE_FILE = "CLAUDE.md.base"
33
30
  const BAK_KEEP = 3 // 通常 .bak と衝突 .bak それぞれ直近 3 件まで保持
34
31
 
32
+ function configPaths(configFilename = "CLAUDE.md") {
33
+ const filename = configFilename === "AGENTS.md" ? "AGENTS.md" : "CLAUDE.md"
34
+ return {
35
+ filename,
36
+ metaFile: filename === "AGENTS.md" ? "agents-md.json" : "claude-md.json",
37
+ baseFile: `${filename}.base`,
38
+ }
39
+ }
40
+
35
41
  async function readJsonOrNull(p) {
36
42
  try {
37
43
  const text = await fs.readFile(p, "utf-8")
@@ -41,9 +47,13 @@ async function readJsonOrNull(p) {
41
47
  }
42
48
  }
43
49
 
44
- async function loadAccessToken() {
45
- const data = await readJsonOrNull(TOKEN_PATH)
46
- return (data && typeof data.access === "string" && data.access) || null
50
+ async function loadAccessToken(configFilename = "CLAUDE.md") {
51
+ const cliDir = configPaths(configFilename).filename === "AGENTS.md" ? ".codex" : ".claude"
52
+ const primary = await readJsonOrNull(path.join(os.homedir(), cliDir, ".hub_token.json"))
53
+ if (primary && typeof primary.access === "string" && primary.access) return primary.access
54
+ // 既存のhub-agent enrollmentは ~/.claude にtokenを持つため、Codex単独導入前の端末も救済する。
55
+ const legacy = await readJsonOrNull(path.join(os.homedir(), ".claude", ".hub_token.json"))
56
+ return (legacy && typeof legacy.access === "string" && legacy.access) || null
47
57
  }
48
58
 
49
59
  function sha256(s) {
@@ -133,29 +143,29 @@ async function putHubClaudeMd({ hubUrl, accessToken, dirName, body, fetchImpl, l
133
143
  }
134
144
  }
135
145
 
136
- async function readLocalClaudeMd(targetDir) {
146
+ async function readLocalConfigMd(targetDir, configFilename) {
137
147
  try {
138
- return await fs.readFile(path.join(targetDir, "CLAUDE.md"), "utf-8")
148
+ return await fs.readFile(path.join(targetDir, configPaths(configFilename).filename), "utf-8")
139
149
  } catch (err) {
140
150
  if (err?.code === "ENOENT") return null
141
151
  throw err
142
152
  }
143
153
  }
144
154
 
145
- async function writeLocalClaudeMd(targetDir, body) {
146
- await fs.writeFile(path.join(targetDir, "CLAUDE.md"), body, "utf-8")
155
+ async function writeLocalConfigMd(targetDir, body, configFilename) {
156
+ await fs.writeFile(path.join(targetDir, configPaths(configFilename).filename), body, "utf-8")
147
157
  }
148
158
 
149
- async function readMeta(targetDir) {
150
- const metaPath = path.join(targetDir, META_DIR, META_FILE)
159
+ async function readMeta(targetDir, configFilename) {
160
+ const metaPath = path.join(targetDir, META_DIR, configPaths(configFilename).metaFile)
151
161
  return await readJsonOrNull(metaPath)
152
162
  }
153
163
 
154
- async function writeMeta(targetDir, meta) {
164
+ async function writeMeta(targetDir, meta, configFilename) {
155
165
  const metaDir = path.join(targetDir, META_DIR)
156
166
  await fs.mkdir(metaDir, { recursive: true })
157
167
  await fs.writeFile(
158
- path.join(metaDir, META_FILE),
168
+ path.join(metaDir, configPaths(configFilename).metaFile),
159
169
  JSON.stringify(meta, null, 2),
160
170
  "utf-8",
161
171
  )
@@ -171,11 +181,11 @@ async function writeMeta(targetDir, meta) {
171
181
  * meta(claude-md.json) は hash と updated_at しか持たないため、本文そのものが要る
172
182
  * 3-way merge の用途ではこのファイルが必要。
173
183
  */
174
- async function writeBaseBody(targetDir, body) {
184
+ async function writeBaseBody(targetDir, body, configFilename) {
175
185
  if (body == null) return
176
186
  const metaDir = path.join(targetDir, META_DIR)
177
187
  await fs.mkdir(metaDir, { recursive: true })
178
- await fs.writeFile(path.join(metaDir, BASE_FILE), body, "utf-8")
188
+ await fs.writeFile(path.join(metaDir, configPaths(configFilename).baseFile), body, "utf-8")
179
189
  }
180
190
 
181
191
  /**
@@ -184,11 +194,12 @@ async function writeBaseBody(targetDir, body) {
184
194
  *
185
195
  * @param {'normal'|'conflict'} kind バックアップ種別(命名 prefix)
186
196
  */
187
- async function backupLocalClaudeMd(targetDir, body, kind) {
197
+ async function backupLocalConfigMd(targetDir, body, kind, configFilename) {
188
198
  if (body == null) return
189
199
  const metaDir = path.join(targetDir, META_DIR)
190
200
  await fs.mkdir(metaDir, { recursive: true })
191
- const prefix = kind === "conflict" ? "CLAUDE.md.conflict" : "CLAUDE.md"
201
+ const filename = configPaths(configFilename).filename
202
+ const prefix = kind === "conflict" ? `${filename}.conflict` : filename
192
203
  const bakName = makeBakName(prefix)
193
204
  await fs.writeFile(path.join(metaDir, bakName), body, "utf-8")
194
205
  // 同 prefix の .bak を新しい順に BAK_KEEP 件まで残す。
@@ -224,12 +235,13 @@ export async function syncClaudeMdWithHub({
224
235
  accessToken,
225
236
  logger,
226
237
  fetchImpl,
238
+ configFilename = "CLAUDE.md",
227
239
  } = {}) {
228
240
  if (!targetDir) throw new Error("syncClaudeMdWithHub requires targetDir")
229
241
  if (!dirName) throw new Error("syncClaudeMdWithHub requires dirName")
230
242
 
231
243
  const token =
232
- accessToken === undefined ? await loadAccessToken() : accessToken || null
244
+ accessToken === undefined ? await loadAccessToken(configFilename) : accessToken || null
233
245
  if (!token) {
234
246
  logger?.info?.({ dirName }, "syncClaudeMdWithHub: no access token, skip")
235
247
  return { action: "skipped", reason: "no-token" }
@@ -252,11 +264,11 @@ export async function syncClaudeMdWithHub({
252
264
  const hubUpdatedAt = hub.claude_md_updated_at || null
253
265
 
254
266
  // 2) ローカル CLAUDE.md を読み、現在 hash を計算
255
- const localBody = await readLocalClaudeMd(targetDir)
267
+ const localBody = await readLocalConfigMd(targetDir, configFilename)
256
268
  const localCurrentHash = localBody == null ? null : sha256(localBody)
257
269
 
258
270
  // 3) メタファイルを読み、前回 sync の状態を取得
259
- const meta = await readMeta(targetDir)
271
+ const meta = await readMeta(targetDir, configFilename)
260
272
 
261
273
  // Hub が一度も保存されていない(空本文 + updated_at が null)プロジェクトは
262
274
  // 「Hub UI で意図的に未設定にしている」運用(テナント標準 CLAUDE.md に任せる等)の
@@ -276,7 +288,12 @@ export async function syncClaudeMdWithHub({
276
288
  if (!meta) {
277
289
  // 初回 sync。
278
290
  hubChanged = !!hubBody
279
- if (localBody == null) {
291
+ if (configPaths(configFilename).filename === "AGENTS.md") {
292
+ // Codex の AGENTS.md は既存リポジトリにも通常存在し、案件正本とは別の
293
+ // ローカル規約を含む。初回に terminal-wins で Project.claude_md を壊さないよう、
294
+ // Hub 正本を優先して pull(既存 AGENTS.md は .bak に退避)する。
295
+ localChanged = false
296
+ } else if (localBody == null) {
280
297
  localChanged = false
281
298
  } else {
282
299
  localChanged = !!localBody // 非空なら端末側に何かある=衝突候補
@@ -300,15 +317,15 @@ export async function syncClaudeMdWithHub({
300
317
 
301
318
  if (hubChanged && !localChanged) {
302
319
  // pull: ローカルを .bak 退避 → Hub の本文で上書き
303
- await backupLocalClaudeMd(targetDir, localBody, "normal")
304
- await writeLocalClaudeMd(targetDir, hubBody)
320
+ await backupLocalConfigMd(targetDir, localBody, "normal", configFilename)
321
+ await writeLocalConfigMd(targetDir, hubBody, configFilename)
305
322
  await writeMeta(targetDir, {
306
323
  lastSyncedHubUpdatedAt: hubUpdatedAt,
307
324
  lastSyncedHash: hubHash || sha256(hubBody),
308
325
  lastSyncedAt: nowIso(),
309
- })
326
+ }, configFilename)
310
327
  // 3-way merge 用 base: pull 直後はローカル == Hub なので Hub 本文を base に。
311
- await writeBaseBody(targetDir, hubBody)
328
+ await writeBaseBody(targetDir, hubBody, configFilename)
312
329
  logger?.info?.({ dirName }, "syncClaudeMdWithHub: pull")
313
330
  return { action: "pull" }
314
331
  }
@@ -334,17 +351,17 @@ export async function syncClaudeMdWithHub({
334
351
  lastSyncedHubUpdatedAt: nowIso(),
335
352
  lastSyncedHash: localCurrentHash,
336
353
  lastSyncedAt: nowIso(),
337
- })
354
+ }, configFilename)
338
355
  // 3-way merge 用 base: push 直後は Hub の正本がローカルと一致するので、
339
356
  // 次回の base は今 push した本文 (= localBody)。
340
- await writeBaseBody(targetDir, localBody || "")
357
+ await writeBaseBody(targetDir, localBody || "", configFilename)
341
358
  logger?.info?.({ dirName }, "syncClaudeMdWithHub: push")
342
359
  return { action: "push" }
343
360
  }
344
361
 
345
362
  // hubChanged && localChanged → 衝突。端末側を勝者にして Hub に PUT。
346
363
  // Hub の取り込み内容は .bak.conflict に退避(後で人手マージできるよう)。
347
- await backupLocalClaudeMd(targetDir, hubBody, "conflict")
364
+ await backupLocalConfigMd(targetDir, hubBody, "conflict", configFilename)
348
365
  const ok = await putHubClaudeMd({
349
366
  hubUrl: url,
350
367
  accessToken: token,
@@ -361,9 +378,9 @@ export async function syncClaudeMdWithHub({
361
378
  lastSyncedHubUpdatedAt: nowIso(),
362
379
  lastSyncedHash: localCurrentHash,
363
380
  lastSyncedAt: nowIso(),
364
- })
381
+ }, configFilename)
365
382
  // 3-way merge 用 base: conflict push 後の Hub 正本は端末側本文 (= localBody)。
366
- await writeBaseBody(targetDir, localBody || "")
383
+ await writeBaseBody(targetDir, localBody || "", configFilename)
367
384
  logger?.warn?.(
368
385
  { dirName },
369
386
  "syncClaudeMdWithHub: conflict (terminal wins); hub body saved to .bak.conflict",
@@ -374,7 +391,7 @@ export async function syncClaudeMdWithHub({
374
391
  // メタ操作・ハッシュ計算は ensureClaudeMd 側 (Hub pull 初回配信) でも使うため
375
392
  // named export する。同じファイルパス・同じスキーマで管理することで、初回配信と
376
393
  // 以降の sync で食い違いを起こさない。
377
- export { sha256, readMeta, writeMeta, writeBaseBody, nowIso }
394
+ export { sha256, readMeta, writeMeta, writeBaseBody, nowIso, configPaths }
378
395
 
379
396
  // 内部テスト用エクスポート
380
397
  export const _internals = {
@@ -382,7 +399,7 @@ export const _internals = {
382
399
  readMeta,
383
400
  writeMeta,
384
401
  writeBaseBody,
385
- backupLocalClaudeMd,
402
+ backupLocalConfigMd,
386
403
  BAK_KEEP,
387
- BASE_FILE,
404
+ configPaths,
388
405
  }
package/src/claude-md.mjs CHANGED
@@ -27,7 +27,6 @@ import {
27
27
  } from "./claude-md-sync.mjs"
28
28
 
29
29
  const DEFAULT_HUB_API = "https://api.hub.cocorograph.com"
30
- const TOKEN_PATH = path.join(os.homedir(), ".claude", ".hub_token.json")
31
30
 
32
31
  async function readJsonOrNull(p) {
33
32
  try {
@@ -38,9 +37,12 @@ async function readJsonOrNull(p) {
38
37
  }
39
38
  }
40
39
 
41
- async function loadAccessToken() {
42
- const data = await readJsonOrNull(TOKEN_PATH)
43
- return (data && typeof data.access === "string" && data.access) || null
40
+ async function loadAccessToken(configFilename = "CLAUDE.md") {
41
+ const cliDir = configFilename === "AGENTS.md" ? ".codex" : ".claude"
42
+ const primary = await readJsonOrNull(path.join(os.homedir(), cliDir, ".hub_token.json"))
43
+ if (primary && typeof primary.access === "string" && primary.access) return primary.access
44
+ const legacy = await readJsonOrNull(path.join(os.homedir(), ".claude", ".hub_token.json"))
45
+ return (legacy && typeof legacy.access === "string" && legacy.access) || null
44
46
  }
45
47
 
46
48
  /**
@@ -134,7 +136,7 @@ function isGitHubSlug(repoUrl) {
134
136
  return /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(repoUrl)
135
137
  }
136
138
 
137
- function renderRepositorySection(repositories, dirName = "") {
139
+ function renderRepositorySection(repositories, dirName = "", cliKind = "claude") {
138
140
  if (!Array.isArray(repositories) || repositories.length === 0) return ""
139
141
 
140
142
  const lines = ["## Cockpit クローンレス開発フロー", ""]
@@ -211,7 +213,7 @@ function renderRepositorySection(repositories, dirName = "") {
211
213
  "# 秘密鍵を ~/.ssh/hub_deploy/ に書き出し、ssh コマンドだけ受け取る",
212
214
  )
213
215
  lines.push(
214
- `python3 ~/.claude/scripts/hub_helper.py deploy_creds ${dirName || "<dir_name>"} --env ${envExample}`,
216
+ `python3 ~/.${cliKind === "codex" ? "codex" : "claude"}/scripts/hub_helper.py deploy_creds ${dirName || "<dir_name>"} --env ${envExample}`,
215
217
  )
216
218
  lines.push("```")
217
219
  lines.push("")
@@ -235,7 +237,7 @@ function renderRepositorySection(repositories, dirName = "") {
235
237
  return lines.join("\n")
236
238
  }
237
239
 
238
- function renderWithDirector(dirName, director, repositorySection = "") {
240
+ function renderWithDirector(dirName, director, repositorySection = "", configFilename = "CLAUDE.md") {
239
241
  const fm = director?.frontmatter || {}
240
242
  const client = (fm.client || "").trim()
241
243
  const domain = (fm.domain || "").trim()
@@ -245,9 +247,9 @@ function renderWithDirector(dirName, director, repositorySection = "") {
245
247
  const googleDrive = (fm.google_drive || "").trim()
246
248
 
247
249
  const lines = [
248
- "# CLAUDE.md",
250
+ `# ${configFilename}`,
249
251
  "",
250
- "This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.",
252
+ `This file provides guidance to ${configFilename === "AGENTS.md" ? "Codex" : "Claude Code"} when working with code in this repository.`,
251
253
  "",
252
254
  "## プロジェクト概要",
253
255
  "",
@@ -291,17 +293,17 @@ function renderWithDirector(dirName, director, repositorySection = "") {
291
293
  "開発手順・SSH 接続情報・横断ナレッジへのポインタなど、より詳細な内容は",
292
294
  )
293
295
  lines.push(
294
- "このリポジトリで `claude` を起動して `/init-claude-md` スキルを実行してください。",
296
+ `このリポジトリで ${configFilename === "AGENTS.md" ? "`codex` を起動して `/init-Codex-md`" : "`claude` を起動して `/init-claude-md`"} スキルを実行してください。`,
295
297
  )
296
298
  lines.push("")
297
299
  return lines.join("\n")
298
300
  }
299
301
 
300
- function renderPlaceholder(dirName, repositorySection = "") {
302
+ function renderPlaceholder(dirName, repositorySection = "", configFilename = "CLAUDE.md") {
301
303
  const sections = [
302
- "# CLAUDE.md",
304
+ `# ${configFilename}`,
303
305
  "",
304
- "This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.",
306
+ `This file provides guidance to ${configFilename === "AGENTS.md" ? "Codex" : "Claude Code"} when working with code in this repository.`,
305
307
  "",
306
308
  "## 関連",
307
309
  "",
@@ -315,7 +317,7 @@ function renderPlaceholder(dirName, repositorySection = "") {
315
317
  "## 初期化",
316
318
  "",
317
319
  "これは hub-agent の自動生成プレースホルダです。Hub director も未作成です。",
318
- "詳細を生成するには、このリポジトリで `claude` を起動して `/init-claude-md` スキルを実行してください。",
320
+ `詳細を生成するには、このリポジトリで ${configFilename === "AGENTS.md" ? "`codex` を起動して `/init-Codex-md`" : "`claude` を起動して `/init-claude-md`"} スキルを実行してください。`,
319
321
  "",
320
322
  )
321
323
  return sections.join("\n")
@@ -344,12 +346,16 @@ export async function ensureClaudeMd({
344
346
  accessToken,
345
347
  logger,
346
348
  fetchImpl,
349
+ configFilename = "CLAUDE.md",
347
350
  } = {}) {
348
351
  if (!targetDir) throw new Error("ensureClaudeMd requires targetDir")
349
352
  if (!dirName) throw new Error("ensureClaudeMd requires dirName")
350
- const claudeMdPath = path.join(targetDir, "CLAUDE.md")
353
+ const configMdPath = path.join(
354
+ targetDir,
355
+ configFilename === "AGENTS.md" ? "AGENTS.md" : "CLAUDE.md",
356
+ )
351
357
  try {
352
- await fs.access(claudeMdPath)
358
+ await fs.access(configMdPath)
353
359
  return { written: false, source: "existing" }
354
360
  } catch {
355
361
  /* not found → continue */
@@ -358,7 +364,7 @@ export async function ensureClaudeMd({
358
364
  // accessToken は明示 null (テスト用) で「token を読まない」を選べるようにする。
359
365
  // undefined のときだけ ~/.claude/.hub_token.json にフォールバックする。
360
366
  const token =
361
- accessToken === undefined ? await loadAccessToken() : accessToken || null
367
+ accessToken === undefined ? await loadAccessToken(configFilename) : accessToken || null
362
368
  const url = hubUrl || DEFAULT_HUB_API
363
369
 
364
370
  // Stage 3: Hub に正本があればそれを最優先で書き込み、メタも初期化する
@@ -374,17 +380,17 @@ export async function ensureClaudeMd({
374
380
  const hubBody = hub?.claude_md || ""
375
381
  const hubInitialized = !!hub?.claude_md_updated_at
376
382
  if (hubInitialized && hubBody) {
377
- await fs.writeFile(claudeMdPath, hubBody, "utf-8")
383
+ await fs.writeFile(configMdPath, hubBody, "utf-8")
378
384
  await writeMeta(targetDir, {
379
385
  lastSyncedHubUpdatedAt: hub.claude_md_updated_at,
380
386
  lastSyncedHash: hub.claude_md_hash || sha256(hubBody),
381
387
  lastSyncedAt: nowIso(),
382
- })
388
+ }, configFilename)
383
389
  // 初回 pull 直後は base = Hub 本文。以降の session-end 3-way merge の入力。
384
- await writeBaseBody(targetDir, hubBody)
390
+ await writeBaseBody(targetDir, hubBody, configFilename)
385
391
  logger?.info?.(
386
- { dirName, claudeMdPath },
387
- "wrote CLAUDE.md from Hub project claude_md (initial sync)",
392
+ { dirName, configMdPath },
393
+ "wrote project instruction file from Hub project claude_md (initial sync)",
388
394
  )
389
395
  return { written: true, source: "hub" }
390
396
  }
@@ -399,16 +405,17 @@ export async function ensureClaudeMd({
399
405
  ])
400
406
  : [null, []]
401
407
 
402
- const repositorySection = renderRepositorySection(repositories, dirName)
408
+ const cliKind = configFilename === "AGENTS.md" ? "codex" : "claude"
409
+ const repositorySection = renderRepositorySection(repositories, dirName, cliKind)
403
410
  const body = director
404
- ? renderWithDirector(dirName, director, repositorySection)
405
- : renderPlaceholder(dirName, repositorySection)
411
+ ? renderWithDirector(dirName, director, repositorySection, configFilename)
412
+ : renderPlaceholder(dirName, repositorySection, configFilename)
406
413
  const source = director ? "director" : "placeholder"
407
414
 
408
- await fs.writeFile(claudeMdPath, body, "utf-8")
415
+ await fs.writeFile(configMdPath, body, "utf-8")
409
416
  logger?.info?.(
410
- { dirName, claudeMdPath, source },
411
- "wrote CLAUDE.md for new workspace dir",
417
+ { dirName, configMdPath, source },
418
+ "wrote project instruction file for new workspace dir",
412
419
  )
413
420
  return { written: true, source }
414
421
  }
package/src/tmux.mjs CHANGED
@@ -78,6 +78,18 @@ export function isUnderHubProjectsBase(p) {
78
78
  return true
79
79
  }
80
80
 
81
+ /**
82
+ * Hub workspace またはその worktree から、案件指示ファイルを置く親 workspace を返す。
83
+ * worktree 内の AGENTS.md / CLAUDE.md を別管理すると Hub 正本が分岐するため、
84
+ * `<workspace>/.claude/worktrees/<name>` で起動しても常に `<workspace>` を対象にする。
85
+ */
86
+ export function projectInstructionDir(p) {
87
+ if (!isUnderHubProjectsBase(p)) return path.resolve(p)
88
+ const base = path.resolve(hubProjectsBase())
89
+ const [workspace] = path.relative(base, path.resolve(p)).split(path.sep)
90
+ return path.join(base, workspace)
91
+ }
92
+
81
93
  /**
82
94
  * git branch 名から worktree dir 名 (= tmux session 名) を導出する。
83
95
  * 例: "feature/multi-area" -> "feature-multi-area"
@@ -788,15 +800,18 @@ export async function createSession(name, cwd, opts = {}) {
788
800
  // 何もしない(テナント標準 CLAUDE.md の運用を尊重する)。
789
801
  // どちらも失敗しても session 起動自体は止めない (warn のみ)。
790
802
  if (isUnderHubProjectsBase(resolvedCwd)) {
791
- const dirName = path.basename(resolvedCwd)
803
+ const instructionDir = projectInstructionDir(resolvedCwd)
804
+ const dirName = path.basename(instructionDir)
805
+ const configFilename = opts.cliKind === "codex" ? "AGENTS.md" : "CLAUDE.md"
792
806
  try {
793
807
  await ensureClaudeMd({
794
- targetDir: resolvedCwd,
808
+ targetDir: instructionDir,
795
809
  dirName,
796
810
  hubUrl: opts.hubUrl,
797
811
  accessToken: opts.hubAccessToken,
798
812
  logger: opts.logger,
799
813
  fetchImpl: opts.fetchImpl,
814
+ configFilename,
800
815
  })
801
816
  } catch (err) {
802
817
  opts.logger?.warn?.(
@@ -806,12 +821,13 @@ export async function createSession(name, cwd, opts = {}) {
806
821
  }
807
822
  try {
808
823
  const syncResult = await syncClaudeMdWithHub({
809
- targetDir: resolvedCwd,
824
+ targetDir: instructionDir,
810
825
  dirName,
811
826
  hubUrl: opts.hubUrl,
812
827
  accessToken: opts.hubAccessToken,
813
828
  logger: opts.logger,
814
829
  fetchImpl: opts.fetchImpl,
830
+ configFilename,
815
831
  })
816
832
  opts.logger?.debug?.(
817
833
  { session: name, dirName, sync: syncResult },