coding-friend-cli 1.35.8 → 1.36.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.
Files changed (40) hide show
  1. package/README.md +5 -3
  2. package/dist/{chunk-RLUNNJWJ.js → chunk-667NMPN4.js} +47 -4
  3. package/dist/{chunk-HA7E7QZ4.js → chunk-7QFJODWB.js} +14 -9
  4. package/dist/{chunk-UCYGDDFS.js → chunk-7SMP5CZ4.js} +6 -6
  5. package/dist/{chunk-5Z5TZUHZ.js → chunk-DUKBBMVM.js} +6 -18
  6. package/dist/{chunk-TAPL6NF3.js → chunk-EFRPDFO7.js} +4 -4
  7. package/dist/{chunk-ASNR6LFD.js → chunk-GHR3TNL6.js} +8 -8
  8. package/dist/{chunk-R6HDMRYL.js → chunk-GZT3YPAP.js} +5 -5
  9. package/dist/{chunk-UIPLDRGI.js → chunk-KIKN5HEH.js} +6 -6
  10. package/dist/{chunk-O27FVQFU.js → chunk-O5ZKLFSL.js} +6 -4
  11. package/dist/{chunk-UXIWEBI2.js → chunk-PQUACN4U.js} +1 -1
  12. package/dist/{chunk-WSUYLIYX.js → chunk-TEC25H6C.js} +3 -3
  13. package/dist/{chunk-TWKNGPBO.js → chunk-X2H7JJMR.js} +15 -10
  14. package/dist/{clean-PAYOM4FV.js → clean-2IRHH4SU.js} +24 -25
  15. package/dist/{config-NPKT6NN3.js → config-36YY3XLM.js} +17 -17
  16. package/dist/{dev-MD5TNAKI.js → dev-JSYPSXEZ.js} +8 -8
  17. package/dist/{disable-5UK4QINT.js → disable-35RSJICU.js} +3 -3
  18. package/dist/{enable-UQZNZRPI.js → enable-RXWDQRIU.js} +3 -3
  19. package/dist/{guide-LQ2BHU5Y.js → guide-ECSMH2AT.js} +4 -4
  20. package/dist/{host-DKGDDAGO.js → host-BYJEZN6T.js} +10 -5
  21. package/dist/index.js +52 -36
  22. package/dist/{init-ZIUTSR4U.js → init-QXCMAPXT.js} +19 -19
  23. package/dist/{install-VFD6C3LZ.js → install-NALHBTGG.js} +8 -8
  24. package/dist/learn-PNG2TI2E.js +111 -0
  25. package/dist/{mcp-T3UG4PS3.js → mcp-6GRHKIQW.js} +9 -9
  26. package/dist/{mcp-serve-learn-OKVC5WV3.js → mcp-serve-learn-36ZQQQTF.js} +3 -3
  27. package/dist/{memory-R57VRQZL.js → memory-A7OUTQ54.js} +6 -6
  28. package/dist/{permission-KLT2TLZY.js → permission-PB3OMKRB.js} +9 -9
  29. package/dist/{permissions-LYADLYYK.js → permissions-J46VP6US.js} +2 -1
  30. package/dist/postinstall.js +1 -1
  31. package/dist/{session-MVH6IYHM.js → session-YJJRGQPX.js} +6 -6
  32. package/dist/{status-YWABL222.js → status-SG5LCXER.js} +16 -16
  33. package/dist/{statusline-EYTWM5X6.js → statusline-3Z4DE24F.js} +2 -2
  34. package/dist/{uninstall-MLSKOCOZ.js → uninstall-JLSEHXS5.js} +11 -11
  35. package/dist/{update-G5YXZRMQ.js → update-MO5BT3C5.js} +5 -5
  36. package/dist/{update-check-BPCQ25AR.js → update-check-I2RSVGFO.js} +3 -3
  37. package/lib/learn-host/README.md +8 -9
  38. package/lib/learn-host/src/components/Breadcrumbs.tsx +30 -19
  39. package/package.json +1 -1
  40. package/lib/learn-host/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,111 @@
1
+ import {
2
+ resolveLearnDir
3
+ } from "./chunk-DUKBBMVM.js";
4
+ import "./chunk-57EGAXYI.js";
5
+ import {
6
+ commandExists,
7
+ run,
8
+ runWithStderr,
9
+ streamExec
10
+ } from "./chunk-EVGXUDX4.js";
11
+ import {
12
+ log,
13
+ printBanner
14
+ } from "./chunk-NREZK463.js";
15
+ import {
16
+ readJson
17
+ } from "./chunk-5UVDWG5L.js";
18
+ import {
19
+ globalConfigPath
20
+ } from "./chunk-X2H7JJMR.js";
21
+
22
+ // src/commands/learn.ts
23
+ import { existsSync } from "fs";
24
+ import { resolve } from "path";
25
+ import { confirm } from "@inquirer/prompts";
26
+ async function learnPushCommand(path) {
27
+ const globalCfg = readJson(globalConfigPath());
28
+ const learnDir = resolveLearnDir(globalCfg, path);
29
+ printBanner("\u2728 Coding Friend Learn Push \u2728");
30
+ if (!existsSync(learnDir)) {
31
+ log.error(`Learn folder not found: ${learnDir}`);
32
+ log.dim("Run /cf-learn first to generate some docs.");
33
+ process.exit(1);
34
+ }
35
+ if (!commandExists("git")) {
36
+ log.error("git is not installed or not on PATH.");
37
+ process.exit(1);
38
+ }
39
+ const top = run("git", ["rev-parse", "--show-toplevel"], { cwd: learnDir });
40
+ if (top === null) {
41
+ log.error(`Learn folder is not inside a git repository: ${learnDir}`);
42
+ log.dim("Initialize a git repo there, or push it manually.");
43
+ process.exit(1);
44
+ }
45
+ const gitRoot = resolve(top);
46
+ const resolvedLearnDir = resolve(learnDir);
47
+ const isGitRoot = gitRoot === resolvedLearnDir;
48
+ log.info(`Learn folder: ${resolvedLearnDir}`);
49
+ log.info(`Git root: ${gitRoot}`);
50
+ console.log();
51
+ if (!isGitRoot) {
52
+ log.warn(
53
+ "The learn folder is NOT the root of its git repository \u2014 it lives inside a larger repo."
54
+ );
55
+ log.warn(
56
+ "Pushing will commit and push EVERYTHING in that repo, not just the learn folder."
57
+ );
58
+ const proceed = await confirm({
59
+ message: "Continue anyway?",
60
+ default: false
61
+ });
62
+ if (!proceed) {
63
+ log.dim("Aborted.");
64
+ return;
65
+ }
66
+ }
67
+ const remotes = run("git", ["remote"], { cwd: gitRoot });
68
+ if (remotes === null || !remotes.split("\n").includes("origin")) {
69
+ log.error("No `origin` remote configured in this repository.");
70
+ log.dim("Add one with: git remote add origin <url>");
71
+ process.exit(1);
72
+ }
73
+ const status = run("git", ["status", "--porcelain"], { cwd: gitRoot });
74
+ if (status === null) {
75
+ log.error("Failed to read git status.");
76
+ process.exit(1);
77
+ }
78
+ if (status === "") {
79
+ log.info("Nothing to commit \u2014 working tree is clean.");
80
+ } else {
81
+ log.step("Staging and committing changes...");
82
+ const stage = runWithStderr("git", ["add", "-A"], { cwd: gitRoot });
83
+ if (stage.exitCode !== 0) {
84
+ log.error(`git add failed: ${stage.stderr}`);
85
+ process.exit(1);
86
+ }
87
+ const commit = runWithStderr(
88
+ "git",
89
+ ["commit", "-m", "docs(learn): update learning notes"],
90
+ { cwd: gitRoot }
91
+ );
92
+ if (commit.exitCode !== 0) {
93
+ log.error(`git commit failed: ${commit.stderr || commit.stdout}`);
94
+ process.exit(1);
95
+ }
96
+ log.success("Committed.");
97
+ }
98
+ console.log();
99
+ log.step("Pushing to origin...");
100
+ const pushCode = await streamExec("git", ["push", "origin", "HEAD"], {
101
+ cwd: gitRoot
102
+ });
103
+ if (pushCode !== 0) {
104
+ log.error("git push failed.");
105
+ process.exit(1);
106
+ }
107
+ log.success("Pushed.");
108
+ }
109
+ export {
110
+ learnPushCommand
111
+ };
@@ -1,40 +1,37 @@
1
1
  import {
2
2
  ensureMemoryBuilt,
3
3
  printMemoryMcpConfig
4
- } from "./chunk-ASNR6LFD.js";
4
+ } from "./chunk-GHR3TNL6.js";
5
5
  import {
6
6
  checkLearnMcpHealth,
7
7
  checkMemoryMcpHealth,
8
8
  detectMemoryMcpState,
9
9
  printHealthSection,
10
10
  warnStaleMcpJson
11
- } from "./chunk-UXIWEBI2.js";
11
+ } from "./chunk-PQUACN4U.js";
12
12
  import {
13
13
  listMdFilesRecursive
14
14
  } from "./chunk-2DTXVMPQ.js";
15
15
  import {
16
16
  isLearnMcpRegistered,
17
17
  registerLearnMcp
18
- } from "./chunk-WSUYLIYX.js";
18
+ } from "./chunk-TEC25H6C.js";
19
19
  import {
20
20
  getMemoryMcpStatus,
21
21
  writeMemoryMcpEntry
22
- } from "./chunk-HA7E7QZ4.js";
22
+ } from "./chunk-7QFJODWB.js";
23
23
  import {
24
24
  resolveLearnDir,
25
25
  resolveMemoryDir
26
- } from "./chunk-5Z5TZUHZ.js";
26
+ } from "./chunk-DUKBBMVM.js";
27
27
  import {
28
28
  getLibPath
29
29
  } from "./chunk-RZRT7NGT.js";
30
30
  import "./chunk-57EGAXYI.js";
31
- import "./chunk-TAPL6NF3.js";
31
+ import "./chunk-EFRPDFO7.js";
32
32
  import {
33
33
  run
34
34
  } from "./chunk-EVGXUDX4.js";
35
- import {
36
- globalConfigPath
37
- } from "./chunk-TWKNGPBO.js";
38
35
  import {
39
36
  log,
40
37
  printBanner
@@ -42,6 +39,9 @@ import {
42
39
  import {
43
40
  readJson
44
41
  } from "./chunk-5UVDWG5L.js";
42
+ import {
43
+ globalConfigPath
44
+ } from "./chunk-X2H7JJMR.js";
45
45
 
46
46
  // src/commands/mcp.ts
47
47
  import { confirm } from "@inquirer/prompts";
@@ -4,15 +4,15 @@ import {
4
4
  import {
5
5
  runWithStderr
6
6
  } from "./chunk-EVGXUDX4.js";
7
- import {
8
- globalConfigPath
9
- } from "./chunk-TWKNGPBO.js";
10
7
  import {
11
8
  log
12
9
  } from "./chunk-NREZK463.js";
13
10
  import {
14
11
  readJson
15
12
  } from "./chunk-5UVDWG5L.js";
13
+ import {
14
+ globalConfigPath
15
+ } from "./chunk-X2H7JJMR.js";
16
16
 
17
17
  // src/commands/mcp-serve-learn.ts
18
18
  import { spawn } from "child_process";
@@ -13,17 +13,17 @@ import {
13
13
  memoryStatusCommand,
14
14
  memoryStopDaemonCommand,
15
15
  printMemoryMcpConfig
16
- } from "./chunk-ASNR6LFD.js";
17
- import "./chunk-UXIWEBI2.js";
18
- import "./chunk-HA7E7QZ4.js";
19
- import "./chunk-5Z5TZUHZ.js";
16
+ } from "./chunk-GHR3TNL6.js";
17
+ import "./chunk-PQUACN4U.js";
18
+ import "./chunk-7QFJODWB.js";
19
+ import "./chunk-DUKBBMVM.js";
20
20
  import "./chunk-RZRT7NGT.js";
21
21
  import "./chunk-57EGAXYI.js";
22
- import "./chunk-TAPL6NF3.js";
22
+ import "./chunk-EFRPDFO7.js";
23
23
  import "./chunk-EVGXUDX4.js";
24
- import "./chunk-TWKNGPBO.js";
25
24
  import "./chunk-NREZK463.js";
26
25
  import "./chunk-5UVDWG5L.js";
26
+ import "./chunk-X2H7JJMR.js";
27
27
  export {
28
28
  ensureMemoryBuilt,
29
29
  isMemoryInitialized,
@@ -3,15 +3,8 @@ import {
3
3
  formatScopeLabel,
4
4
  getMergedValue,
5
5
  getScopeLabel
6
- } from "./chunk-TAPL6NF3.js";
6
+ } from "./chunk-EFRPDFO7.js";
7
7
  import "./chunk-EVGXUDX4.js";
8
- import {
9
- claudeLocalSettingsPath,
10
- claudeProjectSettingsPath,
11
- claudeSettingsPath,
12
- globalConfigPath,
13
- localConfigPath
14
- } from "./chunk-TWKNGPBO.js";
15
8
  import {
16
9
  log,
17
10
  printBanner
@@ -26,11 +19,18 @@ import {
26
19
  groupByCategory,
27
20
  logPluginScriptWarning,
28
21
  runDangerousRulesAudit
29
- } from "./chunk-O27FVQFU.js";
22
+ } from "./chunk-O5ZKLFSL.js";
30
23
  import {
31
24
  mergeJson,
32
25
  readJson
33
26
  } from "./chunk-5UVDWG5L.js";
27
+ import {
28
+ claudeLocalSettingsPath,
29
+ claudeProjectSettingsPath,
30
+ claudeSettingsPath,
31
+ globalConfigPath,
32
+ localConfigPath
33
+ } from "./chunk-X2H7JJMR.js";
34
34
 
35
35
  // src/commands/permission.ts
36
36
  import { checkbox, confirm, select } from "@inquirer/prompts";
@@ -15,8 +15,9 @@ import {
15
15
  logPluginScriptWarning,
16
16
  runDangerousRulesAudit,
17
17
  stripDangerousRules
18
- } from "./chunk-O27FVQFU.js";
18
+ } from "./chunk-O5ZKLFSL.js";
19
19
  import "./chunk-5UVDWG5L.js";
20
+ import "./chunk-X2H7JJMR.js";
20
21
  export {
21
22
  DANGEROUS_RULE_PATTERNS,
22
23
  PERMISSION_RULES,
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ensureShellCompletion
4
- } from "./chunk-RLUNNJWJ.js";
4
+ } from "./chunk-667NMPN4.js";
5
5
  import "./chunk-NREZK463.js";
6
6
 
7
7
  // src/postinstall.ts
@@ -1,12 +1,7 @@
1
1
  import {
2
2
  loadConfig
3
- } from "./chunk-5Z5TZUHZ.js";
3
+ } from "./chunk-DUKBBMVM.js";
4
4
  import "./chunk-57EGAXYI.js";
5
- import {
6
- claudeSessionDir,
7
- encodeProjectPath,
8
- resolvePath
9
- } from "./chunk-TWKNGPBO.js";
10
5
  import {
11
6
  log
12
7
  } from "./chunk-NREZK463.js";
@@ -14,6 +9,11 @@ import {
14
9
  readJson,
15
10
  writeJson
16
11
  } from "./chunk-5UVDWG5L.js";
12
+ import {
13
+ claudeSessionDir,
14
+ encodeProjectPath,
15
+ resolvePath
16
+ } from "./chunk-X2H7JJMR.js";
17
17
 
18
18
  // src/commands/session.ts
19
19
  import { input, select } from "@inquirer/prompts";
@@ -1,19 +1,19 @@
1
1
  import {
2
2
  checkLearnMcpHealth,
3
3
  checkMemoryMcpHealth
4
- } from "./chunk-UXIWEBI2.js";
4
+ } from "./chunk-PQUACN4U.js";
5
5
  import {
6
6
  listMdFilesRecursive
7
7
  } from "./chunk-2DTXVMPQ.js";
8
8
  import {
9
9
  isLearnMcpRegistered
10
- } from "./chunk-WSUYLIYX.js";
11
- import "./chunk-HA7E7QZ4.js";
10
+ } from "./chunk-TEC25H6C.js";
11
+ import "./chunk-7QFJODWB.js";
12
12
  import {
13
13
  resolveLearnDir,
14
14
  resolveMemoryDir,
15
15
  sanitizeRawConfig
16
- } from "./chunk-5Z5TZUHZ.js";
16
+ } from "./chunk-DUKBBMVM.js";
17
17
  import {
18
18
  getLibPath
19
19
  } from "./chunk-RZRT7NGT.js";
@@ -22,31 +22,31 @@ import {
22
22
  getLatestCliVersion,
23
23
  getLatestVersion,
24
24
  semverCompare
25
- } from "./chunk-UIPLDRGI.js";
25
+ } from "./chunk-KIKN5HEH.js";
26
26
  import {
27
27
  getInstalledVersion
28
- } from "./chunk-UCYGDDFS.js";
28
+ } from "./chunk-7SMP5CZ4.js";
29
29
  import "./chunk-57EGAXYI.js";
30
- import "./chunk-RLUNNJWJ.js";
30
+ import "./chunk-667NMPN4.js";
31
31
  import {
32
32
  detectPluginScope,
33
33
  isPluginDisabled
34
- } from "./chunk-R6HDMRYL.js";
35
- import "./chunk-TAPL6NF3.js";
34
+ } from "./chunk-GZT3YPAP.js";
35
+ import "./chunk-EFRPDFO7.js";
36
36
  import "./chunk-EVGXUDX4.js";
37
- import {
38
- claudeSettingsPath,
39
- devStatePath,
40
- globalConfigPath,
41
- localConfigPath
42
- } from "./chunk-TWKNGPBO.js";
43
37
  import "./chunk-NREZK463.js";
44
38
  import {
45
39
  getExistingRules
46
- } from "./chunk-O27FVQFU.js";
40
+ } from "./chunk-O5ZKLFSL.js";
47
41
  import {
48
42
  readJson
49
43
  } from "./chunk-5UVDWG5L.js";
44
+ import {
45
+ claudeSettingsPath,
46
+ devStatePath,
47
+ globalConfigPath,
48
+ localConfigPath
49
+ } from "./chunk-X2H7JJMR.js";
50
50
 
51
51
  // src/commands/status.ts
52
52
  import { existsSync, readdirSync } from "fs";
@@ -8,19 +8,19 @@ import {
8
8
  saveStatuslineConfig,
9
9
  selectStatuslineComponents,
10
10
  writeStatuslineSettings
11
- } from "./chunk-UCYGDDFS.js";
11
+ } from "./chunk-7SMP5CZ4.js";
12
12
  import {
13
13
  ALL_COMPONENT_IDS
14
14
  } from "./chunk-57EGAXYI.js";
15
15
  import {
16
16
  commandExists
17
17
  } from "./chunk-EVGXUDX4.js";
18
- import "./chunk-TWKNGPBO.js";
19
18
  import {
20
19
  log,
21
20
  printBanner
22
21
  } from "./chunk-NREZK463.js";
23
22
  import "./chunk-5UVDWG5L.js";
23
+ import "./chunk-X2H7JJMR.js";
24
24
 
25
25
  // src/commands/statusline.ts
26
26
  import { confirm } from "@inquirer/prompts";
@@ -1,26 +1,18 @@
1
1
  import {
2
2
  hasShellCompletion,
3
3
  removeShellCompletion
4
- } from "./chunk-RLUNNJWJ.js";
4
+ } from "./chunk-667NMPN4.js";
5
5
  import {
6
6
  isMarketplaceRegistered,
7
7
  isPluginInstalled
8
- } from "./chunk-R6HDMRYL.js";
8
+ } from "./chunk-GZT3YPAP.js";
9
9
  import {
10
10
  resolveScope
11
- } from "./chunk-TAPL6NF3.js";
11
+ } from "./chunk-EFRPDFO7.js";
12
12
  import {
13
13
  commandExists,
14
14
  run
15
15
  } from "./chunk-EVGXUDX4.js";
16
- import {
17
- claudeSettingsPath,
18
- devStatePath,
19
- globalConfigDir,
20
- marketplaceCachePath,
21
- marketplaceClonePath,
22
- memoryDepsDir
23
- } from "./chunk-TWKNGPBO.js";
24
16
  import {
25
17
  log,
26
18
  printBanner
@@ -29,6 +21,14 @@ import {
29
21
  readJson,
30
22
  writeJson
31
23
  } from "./chunk-5UVDWG5L.js";
24
+ import {
25
+ claudeSettingsPath,
26
+ devStatePath,
27
+ globalConfigDir,
28
+ marketplaceCachePath,
29
+ marketplaceClonePath,
30
+ memoryDepsDir
31
+ } from "./chunk-X2H7JJMR.js";
32
32
 
33
33
  // src/commands/uninstall.ts
34
34
  import { existsSync, rmSync } from "fs";
@@ -4,15 +4,15 @@ import {
4
4
  getLatestVersion,
5
5
  semverCompare,
6
6
  updateCommand
7
- } from "./chunk-UIPLDRGI.js";
8
- import "./chunk-UCYGDDFS.js";
7
+ } from "./chunk-KIKN5HEH.js";
8
+ import "./chunk-7SMP5CZ4.js";
9
9
  import "./chunk-57EGAXYI.js";
10
- import "./chunk-RLUNNJWJ.js";
11
- import "./chunk-TAPL6NF3.js";
10
+ import "./chunk-667NMPN4.js";
11
+ import "./chunk-EFRPDFO7.js";
12
12
  import "./chunk-EVGXUDX4.js";
13
- import "./chunk-TWKNGPBO.js";
14
13
  import "./chunk-NREZK463.js";
15
14
  import "./chunk-5UVDWG5L.js";
15
+ import "./chunk-X2H7JJMR.js";
16
16
  export {
17
17
  getCliVersion,
18
18
  getLatestCliVersion,
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  run
3
3
  } from "./chunk-EVGXUDX4.js";
4
- import {
5
- globalConfigDir
6
- } from "./chunk-TWKNGPBO.js";
7
4
  import {
8
5
  log
9
6
  } from "./chunk-NREZK463.js";
7
+ import {
8
+ globalConfigDir
9
+ } from "./chunk-X2H7JJMR.js";
10
10
 
11
11
  // src/lib/update-check.ts
12
12
  import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
@@ -5,9 +5,9 @@ Next.js app that renders your `/cf-learn` docs as a browsable website with searc
5
5
  ## Usage (via CLI)
6
6
 
7
7
  ```bash
8
- cf host # serves docs/learn/ on port 3333
9
- cf host ./my-docs # serves a custom directory
10
- cf host -p 4000 # custom port
8
+ cf learn host # serves docs/learn/ on port 3333
9
+ cf learn host ./my-docs # serves a custom directory
10
+ cf learn host -p 4000 # custom port
11
11
  ```
12
12
 
13
13
  The CLI handles deps install, build, and serving automatically.
@@ -25,12 +25,11 @@ npm install
25
25
 
26
26
  ### 2. Point to a docs directory
27
27
 
28
- The app resolves docs via (in order):
28
+ The app reads the docs directory from the `DOCS_DIR` env var, which the CLI sets by resolving (in order):
29
29
 
30
- 1. `DOCS_DIR` env var
31
- 2. Local `.coding-friend/config.json` → `learn.outputDir`
32
- 3. Global `~/.coding-friend/config.json` → `learn.outputDir`
33
- 4. Default: `docs/learn/` relative to project root
30
+ 1. Explicit path argument (`cf learn host <path>`)
31
+ 2. Global `~/.coding-friend/config.json` → `learn.outputDir`
32
+ 3. Default: `~/.coding-friend/learn`
34
33
 
35
34
  For local dev, set `DOCS_DIR` to any directory with the expected structure:
36
35
 
@@ -104,7 +103,7 @@ src/
104
103
  ## How It Fits Together
105
104
 
106
105
  ```
107
- cf host [path]
106
+ cf learn host [path]
108
107
  └─ resolves docs dir
109
108
  └─ npm install (one-time)
110
109
  └─ npm run build (with DOCS_DIR env)
@@ -7,27 +7,38 @@ interface Crumb {
7
7
 
8
8
  export default function Breadcrumbs({ crumbs }: { crumbs: Crumb[] }) {
9
9
  return (
10
- <nav className="mb-4 flex items-center gap-2 text-sm text-slate-500 dark:text-slate-400">
11
- <Link href="/" className="hover:text-amber-600 dark:hover:text-amber-400">
10
+ <nav className="mb-4 flex min-w-0 items-center gap-2 whitespace-nowrap text-sm text-slate-500 dark:text-slate-400">
11
+ <Link
12
+ href="/"
13
+ className="shrink-0 hover:text-amber-600 dark:hover:text-amber-400"
14
+ >
12
15
  Home
13
16
  </Link>
14
- {crumbs.map((crumb, i) => (
15
- <span key={i} className="flex items-center gap-2">
16
- <span>/</span>
17
- {crumb.href ? (
18
- <Link
19
- href={crumb.href}
20
- className="capitalize hover:text-amber-600 dark:hover:text-amber-400"
21
- >
22
- {crumb.label}
23
- </Link>
24
- ) : (
25
- <span className="text-slate-800 dark:text-slate-200">
26
- {crumb.label}
27
- </span>
28
- )}
29
- </span>
30
- ))}
17
+ {crumbs.map((crumb, i) => {
18
+ const isLast = i === crumbs.length - 1;
19
+ return (
20
+ <span
21
+ key={i}
22
+ className={`flex items-center gap-2 ${isLast ? "min-w-0" : "shrink-0"}`}
23
+ >
24
+ <span className="shrink-0">/</span>
25
+ {crumb.href ? (
26
+ <Link
27
+ href={crumb.href}
28
+ className="capitalize hover:text-amber-600 dark:hover:text-amber-400"
29
+ >
30
+ {crumb.label}
31
+ </Link>
32
+ ) : (
33
+ <span
34
+ className={`text-slate-800 dark:text-slate-200 ${isLast ? "truncate" : ""}`}
35
+ >
36
+ {crumb.label}
37
+ </span>
38
+ )}
39
+ </span>
40
+ );
41
+ })}
31
42
  </nav>
32
43
  );
33
44
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coding-friend-cli",
3
- "version": "1.35.8",
3
+ "version": "1.36.0",
4
4
  "description": "CLI for coding-friend — host learning docs, setup MCP server, initialize projects",
5
5
  "type": "module",
6
6
  "bin": {