@intent-systems/nexus 2026.1.5-5 → 2026.1.5-9

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 (245) hide show
  1. package/dist/agents/identity-state.js +45 -23
  2. package/dist/agents/skill-runner.js +11 -4
  3. package/dist/agents/skill-usage.js +4 -7
  4. package/dist/agents/skills-status.js +0 -3
  5. package/dist/agents/skills.js +18 -25
  6. package/dist/agents/workspace.js +32 -19
  7. package/dist/capabilities/detector.js +2 -2
  8. package/dist/cli/cloud-cli.js +58 -0
  9. package/dist/cli/credential-cli.js +77 -8
  10. package/dist/cli/program.js +24 -2
  11. package/dist/cli/skills-cli.js +27 -18
  12. package/dist/cli/skills-hub-cli.js +76 -45
  13. package/dist/commands/bootstrap-preset.js +16 -6
  14. package/dist/commands/config.js +85 -0
  15. package/dist/commands/cursor-hooks.js +240 -0
  16. package/dist/commands/cursor-rules.js +13 -207
  17. package/dist/commands/identity.js +3 -3
  18. package/dist/commands/init.js +292 -6
  19. package/dist/commands/onboard-eve-identity.js +1 -1
  20. package/dist/commands/skills-manifest.js +88 -48
  21. package/dist/commands/status.js +52 -50
  22. package/dist/daemon/launchd.js +14 -0
  23. package/dist/entry.js +0 -0
  24. package/dist/native/nexus-cloud/darwin-arm64/nexus-cloud +0 -0
  25. package/dist/native/nexus-cloud/darwin-arm64/nexus-cloud-rs +0 -0
  26. package/dist/utils.js +6 -2
  27. package/docs/AGENTS.default.md +1 -1
  28. package/docs/configuration.md +1 -1
  29. package/docs/feature-inventory/overview.md +2 -2
  30. package/docs/reference/templates/AGENTS.md +171 -109
  31. package/docs/templates/AGENTS.md +139 -199
  32. package/docs/templates/BOOTSTRAP.md +40 -20
  33. package/docs/templates/IDENTITY.md +6 -0
  34. package/docs/templates/USER.md +22 -2
  35. package/package.json +3 -1
  36. package/skills/{notion → connectors/notion}/SKILL.md +1 -1
  37. package/skills/{filesystem → guides/filesystem}/SKILL.md +1 -1
  38. package/skills/{onboarding → guides/onboarding}/SKILL.md +1 -1
  39. package/skills/{onboarding → guides/onboarding}/docs/CAPABILITY_TAXONOMY.md +5 -5
  40. package/skills/{onboarding → guides/onboarding}/docs/CLI_GRAMMAR.md +8 -8
  41. package/skills/{onboarding → guides/onboarding}/docs/CLI_GRAMMAR_ONBOARDING.md +2 -2
  42. package/skills/{onboarding → guides/onboarding}/docs/CLI_GRAMMAR_SKILLS.md +26 -20
  43. package/skills/{onboarding → guides/onboarding}/docs/GOAL_STATE_ARCHITECTURE.md +38 -43
  44. package/skills/{onboarding → guides/onboarding}/docs/NEXUS_SYSTEM_OVERVIEW.md +4 -4
  45. package/skills/{onboarding → guides/onboarding}/docs/SKILLS_HUB_SPEC.md +1 -1
  46. package/skills/{onboarding → guides/onboarding}/docs/SKILLS_SPECIFICATION.md +8 -7
  47. package/skills/{onboarding → guides/onboarding}/docs/SKILL_GATEWAY_DESIGN.md +16 -16
  48. package/skills/{onboarding → guides/onboarding}/docs/SKILL_GATEWAY_PRD.md +10 -12
  49. package/skills/guides/onboarding/docs/canonical/00_CONFLICT_ANALYSIS.md +463 -0
  50. package/skills/guides/onboarding/docs/canonical/01_NEXUS_OVERVIEW.md +167 -0
  51. package/skills/guides/onboarding/docs/canonical/02_CLI_REFERENCE.md +404 -0
  52. package/skills/guides/onboarding/docs/canonical/03_STATE_ARCHITECTURE.md +357 -0
  53. package/skills/guides/onboarding/docs/canonical/04_SKILL_SPECIFICATION.md +393 -0
  54. package/skills/guides/onboarding/docs/canonical/05_CAPABILITY_TAXONOMY.md +298 -0
  55. package/skills/guides/onboarding/docs/canonical/06_CAPABILITIES_REFERENCE.md +207 -0
  56. package/skills/guides/onboarding/docs/canonical/07_AGENT_BINDINGS.md +85 -0
  57. package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/nexus-cloud.md +2 -2
  58. package/skills/{onboarding → guides/onboarding}/scripts/ralph/progress.txt +1 -1
  59. package/skills/{nexus-cloud → tools/nexus-cloud}/SKILL.md +2 -1
  60. package/skills/{nexus-cloud → tools/nexus-cloud}/docs/setup.md +1 -1
  61. package/docs/templates/PROFILE.md +0 -14
  62. /package/skills/{brave-search → connectors/brave-search}/SKILL.md +0 -0
  63. /package/skills/{brave-search → connectors/brave-search}/docs/setup.md +0 -0
  64. /package/skills/{brave-search → connectors/brave-search}/docs/troubleshooting.md +0 -0
  65. /package/skills/{brave-search → connectors/brave-search}/docs/usage.md +0 -0
  66. /package/skills/{brave-search → connectors/brave-search}/scripts/content.mjs +0 -0
  67. /package/skills/{brave-search → connectors/brave-search}/scripts/search.mjs +0 -0
  68. /package/skills/{discord → connectors/discord}/SKILL.md +0 -0
  69. /package/skills/{gemini → connectors/gemini}/SKILL.md +0 -0
  70. /package/skills/{github → connectors/github}/SKILL.md +0 -0
  71. /package/skills/{github → connectors/github}/docs/setup.md +0 -0
  72. /package/skills/{github → connectors/github}/docs/troubleshooting.md +0 -0
  73. /package/skills/{google-oauth → connectors/google-oauth}/SKILL.md +0 -0
  74. /package/skills/{slack → connectors/slack}/SKILL.md +0 -0
  75. /package/skills/{telegram → connectors/telegram}/SKILL.md +0 -0
  76. /package/skills/{telegram → connectors/telegram}/docs/pairing.md +0 -0
  77. /package/skills/{telegram → connectors/telegram}/docs/setup.md +0 -0
  78. /package/skills/{telegram → connectors/telegram}/docs/webhook.md +0 -0
  79. /package/skills/{wacli → connectors/wacli}/SKILL.md +0 -0
  80. /package/skills/{wacli → connectors/wacli}/docs/auth.md +0 -0
  81. /package/skills/{wacli → connectors/wacli}/docs/backup.md +0 -0
  82. /package/skills/{wacli → connectors/wacli}/docs/troubleshooting.md +0 -0
  83. /package/skills/{browser-use-agent-sdk → guides/browser-use-agent-sdk}/SKILL.md +0 -0
  84. /package/skills/{json-render → guides/json-render}/SKILL.md +0 -0
  85. /package/skills/{json-render → guides/json-render}/assets/components/README.md +0 -0
  86. /package/skills/{json-render → guides/json-render}/assets/components/catalog.ts +0 -0
  87. /package/skills/{json-render → guides/json-render}/assets/components/registry.tsx +0 -0
  88. /package/skills/{json-render → guides/json-render}/assets/demo/App.css +0 -0
  89. /package/skills/{json-render → guides/json-render}/assets/demo/App.tsx +0 -0
  90. /package/skills/{json-render → guides/json-render}/assets/demo/README.md +0 -0
  91. /package/skills/{json-render → guides/json-render}/assets/demo/catalog.ts +0 -0
  92. /package/skills/{json-render → guides/json-render}/assets/demo/data/nexus-core.json +0 -0
  93. /package/skills/{json-render → guides/json-render}/assets/demo/index.css +0 -0
  94. /package/skills/{json-render → guides/json-render}/assets/demo/registry.tsx +0 -0
  95. /package/skills/{json-render → guides/json-render}/docs/nexus-state-demo.md +0 -0
  96. /package/skills/{json-render → guides/json-render}/docs/shadcn-preset.md +0 -0
  97. /package/skills/{json-render → guides/json-render}/scripts/create-vite-demo.sh +0 -0
  98. /package/skills/{json-render → guides/json-render}/scripts/llm-server/README.md +0 -0
  99. /package/skills/{json-render → guides/json-render}/scripts/llm-server/catalog.ts +0 -0
  100. /package/skills/{json-render → guides/json-render}/scripts/llm-server/package-lock.json +0 -0
  101. /package/skills/{json-render → guides/json-render}/scripts/llm-server/package.json +0 -0
  102. /package/skills/{json-render → guides/json-render}/scripts/llm-server/server.ts +0 -0
  103. /package/skills/{onboarding → guides/onboarding}/docs/CAPABILITIES.md +0 -0
  104. /package/skills/{onboarding → guides/onboarding}/docs/CLI_GRAMMAR_CREDENTIALS.md +0 -0
  105. /package/skills/{onboarding → guides/onboarding}/docs/DOCUMENTATION_OVERVIEW.md +0 -0
  106. /package/skills/{onboarding → guides/onboarding}/docs/ENTITY_MODEL.md +0 -0
  107. /package/skills/{onboarding → guides/onboarding}/docs/SKILL_INVENTORY.md +0 -0
  108. /package/skills/{onboarding → guides/onboarding}/docs/STATE_ARCHITECTURE.md +0 -0
  109. /package/skills/{onboarding → guides/onboarding}/docs/TROUBLESHOOTING.md +0 -0
  110. /package/skills/{onboarding → guides/onboarding}/docs/USER_JOURNEY.md +0 -0
  111. /package/skills/{onboarding → guides/onboarding}/docs/WOW_MOMENTS.md +0 -0
  112. /package/skills/{onboarding → guides/onboarding}/docs/agent-apple-id.md +0 -0
  113. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/1password.md +0 -0
  114. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/TEMPLATE.md +0 -0
  115. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/aix.md +0 -0
  116. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/bird.md +0 -0
  117. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/brave-search.md +0 -0
  118. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/comms.md +0 -0
  119. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/computer-use.md +0 -0
  120. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/cron-and-heartbeat.md +0 -0
  121. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/eve.md +0 -0
  122. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/github.md +0 -0
  123. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/gog.md +0 -0
  124. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/homebrew-prereqs.md +0 -0
  125. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/qmd.md +0 -0
  126. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/telegram.md +0 -0
  127. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/wacli.md +0 -0
  128. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/weather.md +0 -0
  129. /package/skills/{onboarding → guides/onboarding}/scripts/ralph/prd.json +0 -0
  130. /package/skills/{onboarding → guides/onboarding}/scripts/ralph/prompt.md +0 -0
  131. /package/skills/{onboarding → guides/onboarding}/scripts/ralph/ralph.log +0 -0
  132. /package/skills/{onboarding → guides/onboarding}/scripts/ralph/ralph.sh +0 -0
  133. /package/skills/{onboarding → guides/onboarding}/scripts/setup-cursor-skills.sh +0 -0
  134. /package/skills/{1password → tools/1password}/SKILL.md +0 -0
  135. /package/skills/{1password → tools/1password}/docs/setup.md +0 -0
  136. /package/skills/{1password → tools/1password}/docs/troubleshooting.md +0 -0
  137. /package/skills/{1password → tools/1password}/references/cli-examples.md +0 -0
  138. /package/skills/{1password → tools/1password}/references/get-started.md +0 -0
  139. /package/skills/{agent-browser → tools/agent-browser}/SKILL.md +0 -0
  140. /package/skills/{agent-browser → tools/agent-browser}/docs/browser-use-eval.md +0 -0
  141. /package/skills/{agent-browser → tools/agent-browser}/docs/first-tests.md +0 -0
  142. /package/skills/{agent-browser → tools/agent-browser}/docs/wordle-nyt-eval.js +0 -0
  143. /package/skills/{aix → tools/aix}/SKILL.md +0 -0
  144. /package/skills/{aix → tools/aix}/docs/embeddings.md +0 -0
  145. /package/skills/{aix → tools/aix}/docs/setup.md +0 -0
  146. /package/skills/{aix → tools/aix}/docs/troubleshooting.md +0 -0
  147. /package/skills/{aix → tools/aix}/references/sql.md +0 -0
  148. /package/skills/{apple-notes → tools/apple-notes}/SKILL.md +0 -0
  149. /package/skills/{apple-reminders → tools/apple-reminders}/SKILL.md +0 -0
  150. /package/skills/{bear-notes → tools/bear-notes}/SKILL.md +0 -0
  151. /package/skills/{bird → tools/bird}/SKILL.md +0 -0
  152. /package/skills/{bird → tools/bird}/docs/auth.md +0 -0
  153. /package/skills/{bird → tools/bird}/docs/troubleshooting.md +0 -0
  154. /package/skills/{blogwatcher → tools/blogwatcher}/SKILL.md +0 -0
  155. /package/skills/{blucli → tools/blucli}/SKILL.md +0 -0
  156. /package/skills/{camsnap → tools/camsnap}/SKILL.md +0 -0
  157. /package/skills/{clawdhub → tools/clawdhub}/SKILL.md +0 -0
  158. /package/skills/{coding-agent → tools/coding-agent}/SKILL.md +0 -0
  159. /package/skills/{comms → tools/comms}/SKILL.md +0 -0
  160. /package/skills/{comms → tools/comms}/docs/adapters.md +0 -0
  161. /package/skills/{comms → tools/comms}/docs/setup.md +0 -0
  162. /package/skills/{comms → tools/comms}/docs/troubleshooting.md +0 -0
  163. /package/skills/{comms → tools/comms}/references/schema.md +0 -0
  164. /package/skills/{computer-use → tools/computer-use}/SKILL.md +0 -0
  165. /package/skills/{computer-use → tools/computer-use}/docs/open-interpreter.md +0 -0
  166. /package/skills/{computer-use → tools/computer-use}/docs/peekaboo.md +0 -0
  167. /package/skills/{computer-use → tools/computer-use}/docs/setup.md +0 -0
  168. /package/skills/{computer-use → tools/computer-use}/docs/troubleshooting.md +0 -0
  169. /package/skills/{eightctl → tools/eightctl}/SKILL.md +0 -0
  170. /package/skills/{eve → tools/eve}/SKILL.md +0 -0
  171. /package/skills/{eve → tools/eve}/docs/dual-account.md +0 -0
  172. /package/skills/{eve → tools/eve}/docs/intelligence.md +0 -0
  173. /package/skills/{eve → tools/eve}/docs/setup.md +0 -0
  174. /package/skills/{eve → tools/eve}/docs/troubleshooting.md +0 -0
  175. /package/skills/{eve → tools/eve}/scripts/setup-dual-account.sh +0 -0
  176. /package/skills/{food-order → tools/food-order}/SKILL.md +0 -0
  177. /package/skills/{gh → tools/gh}/SKILL.md +0 -0
  178. /package/skills/{gh → tools/gh}/docs/usage.md +0 -0
  179. /package/skills/{gifgrep → tools/gifgrep}/SKILL.md +0 -0
  180. /package/skills/{gog → tools/gog}/SKILL.md +0 -0
  181. /package/skills/{gog → tools/gog}/docs/portability.md +0 -0
  182. /package/skills/{gog → tools/gog}/docs/setup.md +0 -0
  183. /package/skills/{gog → tools/gog}/docs/troubleshooting.md +0 -0
  184. /package/skills/{gog → tools/gog}/scripts/cdp/README.md +0 -0
  185. /package/skills/{gog → tools/gog}/scripts/cdp/add_test_users.py +0 -0
  186. /package/skills/{gog → tools/gog}/scripts/cdp/auth_add_accounts.py +0 -0
  187. /package/skills/{gog → tools/gog}/scripts/cdp/auth_add_accounts_manual.py +0 -0
  188. /package/skills/{gog → tools/gog}/scripts/cdp/create_oauth_client.py +0 -0
  189. /package/skills/{gog → tools/gog}/scripts/cdp/launch_cdp_chrome.sh +0 -0
  190. /package/skills/{goplaces → tools/goplaces}/SKILL.md +0 -0
  191. /package/skills/{imsg → tools/imsg}/SKILL.md +0 -0
  192. /package/skills/{local-places → tools/local-places}/SERVER_README.md +0 -0
  193. /package/skills/{local-places → tools/local-places}/SKILL.md +0 -0
  194. /package/skills/{local-places → tools/local-places}/pyproject.toml +0 -0
  195. /package/skills/{local-places → tools/local-places}/src/local_places/__init__.py +0 -0
  196. /package/skills/{local-places → tools/local-places}/src/local_places/__pycache__/__init__.cpython-314.pyc +0 -0
  197. /package/skills/{local-places → tools/local-places}/src/local_places/__pycache__/google_places.cpython-314.pyc +0 -0
  198. /package/skills/{local-places → tools/local-places}/src/local_places/__pycache__/main.cpython-314.pyc +0 -0
  199. /package/skills/{local-places → tools/local-places}/src/local_places/__pycache__/schemas.cpython-314.pyc +0 -0
  200. /package/skills/{local-places → tools/local-places}/src/local_places/google_places.py +0 -0
  201. /package/skills/{local-places → tools/local-places}/src/local_places/main.py +0 -0
  202. /package/skills/{local-places → tools/local-places}/src/local_places/schemas.py +0 -0
  203. /package/skills/{mcporter → tools/mcporter}/SKILL.md +0 -0
  204. /package/skills/{model-usage → tools/model-usage}/SKILL.md +0 -0
  205. /package/skills/{model-usage → tools/model-usage}/references/codexbar-cli.md +0 -0
  206. /package/skills/{model-usage → tools/model-usage}/scripts/model_usage.py +0 -0
  207. /package/skills/{nano-banana-pro → tools/nano-banana-pro}/SKILL.md +0 -0
  208. /package/skills/{nano-banana-pro → tools/nano-banana-pro}/scripts/generate_image.py +0 -0
  209. /package/skills/{nano-pdf → tools/nano-pdf}/SKILL.md +0 -0
  210. /package/skills/{nexus-cloud → tools/nexus-cloud}/docs/security.md +0 -0
  211. /package/skills/{nexus-cloud → tools/nexus-cloud}/docs/troubleshooting.md +0 -0
  212. /package/skills/{obsidian → tools/obsidian}/SKILL.md +0 -0
  213. /package/skills/{openai-image-gen → tools/openai-image-gen}/SKILL.md +0 -0
  214. /package/skills/{openai-image-gen → tools/openai-image-gen}/scripts/gen.py +0 -0
  215. /package/skills/{openai-whisper → tools/openai-whisper}/SKILL.md +0 -0
  216. /package/skills/{openai-whisper-api → tools/openai-whisper-api}/SKILL.md +0 -0
  217. /package/skills/{openai-whisper-api → tools/openai-whisper-api}/scripts/transcribe.sh +0 -0
  218. /package/skills/{openhue → tools/openhue}/SKILL.md +0 -0
  219. /package/skills/{oracle → tools/oracle}/SKILL.md +0 -0
  220. /package/skills/{ordercli → tools/ordercli}/SKILL.md +0 -0
  221. /package/skills/{peekaboo → tools/peekaboo}/SKILL.md +0 -0
  222. /package/skills/{qmd → tools/qmd}/SKILL.md +0 -0
  223. /package/skills/{qmd → tools/qmd}/docs/mcp.md +0 -0
  224. /package/skills/{qmd → tools/qmd}/docs/ollama.md +0 -0
  225. /package/skills/{qmd → tools/qmd}/docs/setup.md +0 -0
  226. /package/skills/{sag → tools/sag}/SKILL.md +0 -0
  227. /package/skills/{skill-cli-template → tools/skill-cli-template}/SKILL.md +0 -0
  228. /package/skills/{songsee → tools/songsee}/SKILL.md +0 -0
  229. /package/skills/{sonoscli → tools/sonoscli}/SKILL.md +0 -0
  230. /package/skills/{spotify-player → tools/spotify-player}/SKILL.md +0 -0
  231. /package/skills/{summarize → tools/summarize}/SKILL.md +0 -0
  232. /package/skills/{things-mac → tools/things-mac}/SKILL.md +0 -0
  233. /package/skills/{tmux → tools/tmux}/SKILL.md +0 -0
  234. /package/skills/{tmux → tools/tmux}/scripts/find-sessions.sh +0 -0
  235. /package/skills/{tmux → tools/tmux}/scripts/wait-for-text.sh +0 -0
  236. /package/skills/{trello → tools/trello}/SKILL.md +0 -0
  237. /package/skills/{upstream-sync → tools/upstream-sync}/SKILL.md +0 -0
  238. /package/skills/{upstream-sync → tools/upstream-sync}/scripts/auto-port.sh +0 -0
  239. /package/skills/{upstream-sync → tools/upstream-sync}/scripts/check-all.sh +0 -0
  240. /package/skills/{upstream-sync → tools/upstream-sync}/scripts/check-nexus.sh +0 -0
  241. /package/skills/{upstream-sync → tools/upstream-sync}/scripts/check-pi-ai.sh +0 -0
  242. /package/skills/{video-frames → tools/video-frames}/SKILL.md +0 -0
  243. /package/skills/{video-frames → tools/video-frames}/scripts/frame.sh +0 -0
  244. /package/skills/{weather → tools/weather}/SKILL.md +0 -0
  245. /package/skills/{weather → tools/weather}/docs/usage.md +0 -0
@@ -1,12 +1,12 @@
1
1
  import path from "node:path";
2
2
  import chalk from "chalk";
3
- import { getSkillInfo, runSkill, verifySkill } from "../agents/skill-runner.js";
3
+ import { getSkillInfo, verifySkill } from "../agents/skill-runner.js";
4
4
  import { getAggregateStats, getSkillStats, hasSkillUsage, recordSkillUsage, } from "../agents/skill-usage.js";
5
5
  import { getSkillMetadata, loadWorkspaceSkillEntries } from "../agents/skills.js";
6
6
  import { buildWorkspaceSkillStatus } from "../agents/skills-status.js";
7
7
  import { DEFAULT_AGENT_WORKSPACE_DIR } from "../agents/workspace.js";
8
8
  import { loadConfig } from "../config/config.js";
9
- import { MANAGED_SKILLS_DIR, NEXUS_ROOT, resolveUserPath } from "../utils.js";
9
+ import { NEXUS_ROOT, SKILLS_STATE_DIR, resolveUserPath } from "../utils.js";
10
10
  const STATUS_ICON = {
11
11
  active: "✅",
12
12
  ready: "⭐",
@@ -47,6 +47,7 @@ export function registerSkillsCommand(program) {
47
47
  .description("List all available skills")
48
48
  .option("--json", "Output as JSON")
49
49
  .option("--type <type>", "Filter by type (guide|tool|connector)")
50
+ .option("--status <status>", "Filter by status (active|ready|needs-setup|needs-install|unavailable)")
50
51
  .option("--active", "Only show active skills")
51
52
  .option("--ready", "Only show ready skills")
52
53
  .option("--needs-setup", "Only show skills needing setup")
@@ -58,11 +59,9 @@ export function registerSkillsCommand(program) {
58
59
  const workspaceDir = resolveUserPath(config.agent?.workspace ?? DEFAULT_AGENT_WORKSPACE_DIR);
59
60
  const entries = loadWorkspaceSkillEntries(workspaceDir, {
60
61
  config,
61
- managedSkillsDir: MANAGED_SKILLS_DIR,
62
62
  });
63
63
  const status = buildWorkspaceSkillStatus(workspaceDir, {
64
64
  config,
65
- managedSkillsDir: MANAGED_SKILLS_DIR,
66
65
  entries,
67
66
  });
68
67
  const statusMap = new Map(status.skills.map((item) => [item.name.toLowerCase(), item]));
@@ -84,6 +83,25 @@ export function registerSkillsCommand(program) {
84
83
  ? String(opts.type).toLowerCase()
85
84
  : undefined;
86
85
  const statusFilters = new Set();
86
+ if (opts.status) {
87
+ const raw = String(opts.status)
88
+ .split(",")
89
+ .map((entry) => entry.trim().toLowerCase())
90
+ .filter(Boolean);
91
+ for (const entry of raw) {
92
+ const normalized = entry.replace(/_/g, "-");
93
+ if (normalized === "needs-setup")
94
+ statusFilters.add("needs_setup");
95
+ else if (normalized === "needs-install")
96
+ statusFilters.add("needs_install");
97
+ else if (normalized === "active")
98
+ statusFilters.add("active");
99
+ else if (normalized === "ready")
100
+ statusFilters.add("ready");
101
+ else if (normalized === "unavailable")
102
+ statusFilters.add("unavailable");
103
+ }
104
+ }
87
105
  if (opts.active)
88
106
  statusFilters.add("active");
89
107
  if (opts.ready)
@@ -125,8 +143,11 @@ export function registerSkillsCommand(program) {
125
143
  const icon = STATUS_ICON[item.status] ?? "•";
126
144
  console.log(` ${icon} ${item.name}${desc}`);
127
145
  }
128
- console.log(`\nSkills directory: ${MANAGED_SKILLS_DIR}`);
129
- console.log(`User skills: ${path.join(NEXUS_ROOT, "home", "skills")}\n`);
146
+ const skillsRoot = path.join(NEXUS_ROOT, "skills");
147
+ console.log(`\nSkills directory: ${skillsRoot}`);
148
+ console.log(`Skill types: ${path.join(skillsRoot, "tools")}, ${path.join(skillsRoot, "connectors")}, ${path.join(skillsRoot, "guides")}`);
149
+ console.log(`Skill state: ${SKILLS_STATE_DIR}`);
150
+ console.log(`User skills: ${path.join(workspaceDir, "skills")}\n`);
130
151
  });
131
152
  skill
132
153
  .command("info <name>")
@@ -190,18 +211,6 @@ export function registerSkillsCommand(program) {
190
211
  console.log(info.prompt.trimEnd());
191
212
  recordSkillUsage(name, { ts: Date.now(), event: "use", ok: true });
192
213
  });
193
- skill
194
- .command("run <name>")
195
- .description("Run a skill command with arguments")
196
- .allowUnknownOption()
197
- .action(async (name, _opts, command) => {
198
- const args = command.args.slice(1);
199
- const result = await runSkill(name, args);
200
- if (!result.ok) {
201
- console.error(result.error);
202
- process.exit(1);
203
- }
204
- });
205
214
  skill
206
215
  .command("verify <name>")
207
216
  .description("Verify skill setup and dependencies")
@@ -12,7 +12,7 @@ import { generateSkillManifest, writeSkillManifest, } from "../commands/skills-m
12
12
  import { loadConfig } from "../config/config.js";
13
13
  import { listCredentialEntries, resolveCredentialValue, } from "../credentials/store.js";
14
14
  import { runCommandWithTimeout } from "../process/exec.js";
15
- import { MANAGED_SKILLS_DIR, resolveUserPath } from "../utils.js";
15
+ import { NEXUS_ROOT, resolveUserPath } from "../utils.js";
16
16
  function getHubBaseUrl() {
17
17
  return (process.env.NEXUS_HUB_URL ||
18
18
  process.env.NEXUS_WEBSITE_URL ||
@@ -284,23 +284,27 @@ function dirNameToSlug(dirName) {
284
284
  async function ensureDir(dir) {
285
285
  await fs.mkdir(dir, { recursive: true });
286
286
  }
287
- async function loadManagedSkillSlugs(managedSkillsDir) {
287
+ async function loadInstalledSkillSlugs(skillsRoot) {
288
288
  const slugs = new Set();
289
- const managedDir = path.join(managedSkillsDir, "managed");
290
- let entries = [];
291
- try {
292
- entries = await fs.readdir(managedDir, { withFileTypes: true });
293
- }
294
- catch {
295
- return slugs;
296
- }
297
- for (const entry of entries) {
298
- if (!entry.isDirectory())
299
- continue;
300
- const slug = dirNameToSlug(entry.name);
301
- if (!slug)
289
+ const roots = ["tools", "connectors", "guides"].map((segment) => path.join(skillsRoot, segment));
290
+ for (const root of roots) {
291
+ let entries = [];
292
+ try {
293
+ entries = await fs.readdir(root, { withFileTypes: true });
294
+ }
295
+ catch {
302
296
  continue;
303
- slugs.add(normalizeSkillKey(slug));
297
+ }
298
+ for (const entry of entries) {
299
+ if (!entry.isDirectory())
300
+ continue;
301
+ if (entry.name.startsWith("."))
302
+ continue;
303
+ const slug = dirNameToSlug(entry.name);
304
+ if (!slug)
305
+ continue;
306
+ slugs.add(normalizeSkillKey(slug));
307
+ }
304
308
  }
305
309
  return slugs;
306
310
  }
@@ -383,6 +387,32 @@ async function normalizeSkillRoot(destDir) {
383
387
  }
384
388
  await fs.rm(nested, { recursive: true, force: true });
385
389
  }
390
+ async function resolveInstalledSkillType(skillDir) {
391
+ const skillFile = path.join(skillDir, "SKILL.md");
392
+ let content = "";
393
+ try {
394
+ content = await fs.readFile(skillFile, "utf-8");
395
+ }
396
+ catch {
397
+ return "guide";
398
+ }
399
+ const { frontmatter } = parseFrontmatter(content);
400
+ const rawType = typeof frontmatter.type === "string" ? frontmatter.type.trim().toLowerCase() : "";
401
+ if (rawType === "tool" || rawType === "connector" || rawType === "guide") {
402
+ return rawType;
403
+ }
404
+ const metadata = normalizeMetadata(frontmatter.metadata);
405
+ const metaType = metadata.nexus && typeof metadata.nexus === "object"
406
+ ? metadata.nexus.type
407
+ : undefined;
408
+ if (typeof metaType === "string") {
409
+ const normalized = metaType.trim().toLowerCase();
410
+ if (normalized === "tool" || normalized === "connector" || normalized === "guide") {
411
+ return normalized;
412
+ }
413
+ }
414
+ return "guide";
415
+ }
386
416
  async function resolveHubDependencyPlan(slug, installed, getDetails, onMissing) {
387
417
  const plan = [];
388
418
  const visiting = new Set();
@@ -562,28 +592,13 @@ function buildManifestPayload(input) {
562
592
  }
563
593
  async function installHubSkill(params) {
564
594
  const dirName = slugToDirName(params.slug);
565
- const destDir = path.join(params.managedDir, dirName);
566
- try {
567
- if (!params.force) {
568
- await fs.access(destDir);
569
- if (params.allowSkip) {
570
- return { installed: false, destDir };
571
- }
572
- throw new Error(`Skill already installed at ${destDir}. Use --force to overwrite.`);
573
- }
574
- await fs.rm(destDir, { recursive: true, force: true });
575
- }
576
- catch (err) {
577
- if (err.code !== "ENOENT") {
578
- throw err;
579
- }
580
- }
581
595
  const download = await downloadSkillArtifact(params.slug);
582
596
  if (!download.downloadUrl || !download.artifactSha256) {
583
597
  throw new Error("Download URL missing from hub response");
584
598
  }
585
599
  const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "nexus-skill-"));
586
600
  const artifactPath = path.join(tmpDir, "artifact.bin");
601
+ const extractDir = path.join(tmpDir, "skill");
587
602
  const downloadHeaders = {};
588
603
  if (download.cloudToken) {
589
604
  downloadHeaders.authorization = `Bearer ${download.cloudToken}`;
@@ -598,9 +613,29 @@ async function installHubSkill(params) {
598
613
  if (hash !== download.artifactSha256) {
599
614
  throw new Error(`Checksum mismatch (expected ${download.artifactSha256}, got ${hash})`);
600
615
  }
601
- await extractArchive(artifactPath, destDir);
602
- await normalizeSkillRoot(destDir);
603
- const manifest = await generateSkillManifest(MANAGED_SKILLS_DIR, params.userSkillsDir);
616
+ await extractArchive(artifactPath, extractDir);
617
+ await normalizeSkillRoot(extractDir);
618
+ const skillType = await resolveInstalledSkillType(extractDir);
619
+ const targetBase = path.join(params.skillsRoot, `${skillType}s`);
620
+ const destDir = path.join(targetBase, dirName);
621
+ try {
622
+ if (!params.force) {
623
+ await fs.access(destDir);
624
+ if (params.allowSkip) {
625
+ return { installed: false, destDir };
626
+ }
627
+ throw new Error(`Skill already installed at ${destDir}. Use --force to overwrite.`);
628
+ }
629
+ await fs.rm(destDir, { recursive: true, force: true });
630
+ }
631
+ catch (err) {
632
+ if (err.code !== "ENOENT") {
633
+ throw err;
634
+ }
635
+ }
636
+ await ensureDir(targetBase);
637
+ await fs.rename(extractDir, destDir);
638
+ const manifest = await generateSkillManifest(params.skillsRoot, params.userSkillsDir);
604
639
  await writeSkillManifest(manifest);
605
640
  return { installed: true, destDir };
606
641
  }
@@ -628,21 +663,19 @@ export function registerSkillsHubCommand(program) {
628
663
  : 10;
629
664
  const cfg = loadConfig();
630
665
  const workspaceDir = resolveUserPath(cfg.agent?.workspace ?? DEFAULT_AGENT_WORKSPACE_DIR);
631
- const managedSkillsDir = MANAGED_SKILLS_DIR;
666
+ const skillsRoot = path.join(NEXUS_ROOT, "skills");
632
667
  const status = buildWorkspaceSkillStatus(workspaceDir, {
633
668
  config: cfg,
634
- managedSkillsDir,
635
669
  });
636
670
  const metadataEntries = loadWorkspaceSkillEntries(workspaceDir, {
637
671
  config: cfg,
638
- managedSkillsDir,
639
672
  });
640
673
  const metadataByName = new Map(metadataEntries.map((entry) => [
641
674
  entry.skill.name,
642
675
  getSkillMetadata(entry),
643
676
  ]));
644
677
  const installedNames = new Set(metadataEntries.map((entry) => normalizeSkillKey(entry.skill.name)));
645
- const installedSlugs = await loadManagedSkillSlugs(managedSkillsDir);
678
+ const installedSlugs = await loadInstalledSkillSlugs(skillsRoot);
646
679
  const installedIndex = {
647
680
  names: installedNames,
648
681
  slugs: installedSlugs,
@@ -1049,14 +1082,12 @@ export function registerSkillsHubCommand(program) {
1049
1082
  const cfg = loadConfig();
1050
1083
  const workspaceDir = resolveUserPath(cfg.agent?.workspace ?? DEFAULT_AGENT_WORKSPACE_DIR);
1051
1084
  const userSkillsDir = path.join(workspaceDir, "skills");
1052
- const managedSkillsDir = MANAGED_SKILLS_DIR;
1053
- const managedDir = path.join(managedSkillsDir, "managed");
1085
+ const skillsRoot = path.join(NEXUS_ROOT, "skills");
1054
1086
  const metadataEntries = loadWorkspaceSkillEntries(workspaceDir, {
1055
1087
  config: cfg,
1056
- managedSkillsDir,
1057
1088
  });
1058
1089
  const installedNames = new Set(metadataEntries.map((entry) => normalizeSkillKey(entry.skill.name)));
1059
- const installedSlugs = await loadManagedSkillSlugs(managedSkillsDir);
1090
+ const installedSlugs = await loadInstalledSkillSlugs(skillsRoot);
1060
1091
  const installedIndex = {
1061
1092
  names: installedNames,
1062
1093
  slugs: installedSlugs,
@@ -1082,7 +1113,7 @@ export function registerSkillsHubCommand(program) {
1082
1113
  for (const dep of plan) {
1083
1114
  const result = await installHubSkill({
1084
1115
  slug: dep,
1085
- managedDir,
1116
+ skillsRoot,
1086
1117
  userSkillsDir,
1087
1118
  allowSkip: true,
1088
1119
  });
@@ -1107,7 +1138,7 @@ export function registerSkillsHubCommand(program) {
1107
1138
  }
1108
1139
  const result = await installHubSkill({
1109
1140
  slug,
1110
- managedDir,
1141
+ skillsRoot,
1111
1142
  userSkillsDir,
1112
1143
  force: Boolean(opts.force),
1113
1144
  });
@@ -107,15 +107,15 @@ export async function applyBootstrapPreset(params) {
107
107
  const { workspaceDir, runtime } = params;
108
108
  const stateDir = resolveStateDir();
109
109
  const agentId = process.env.NEXUS_AGENT_ID?.trim() || "default";
110
- const agentIdentityDir = path.join(stateDir, "agents", agentId, "identity");
111
- const userIdentityDir = path.join(stateDir, "user", "identity");
110
+ const agentIdentityDir = path.join(stateDir, "agents", agentId);
111
+ const userIdentityDir = path.join(stateDir, "user");
112
112
  const bootstrapPath = resolveBootstrapPath(undefined, stateDir);
113
113
  if (!(await fileExists(bootstrapPath)))
114
114
  return;
115
115
  await fs.mkdir(agentIdentityDir, { recursive: true });
116
116
  await fs.mkdir(userIdentityDir, { recursive: true });
117
117
  const identityPath = path.join(agentIdentityDir, "IDENTITY.md");
118
- const userPath = path.join(userIdentityDir, "PROFILE.md");
118
+ const userPath = path.join(userIdentityDir, "IDENTITY.md");
119
119
  const soulPath = path.join(agentIdentityDir, "SOUL.md");
120
120
  const agentsPath = path.join(NEXUS_ROOT, "AGENTS.md");
121
121
  const preset = resolvePreset(params.preset);
@@ -173,17 +173,27 @@ export async function applyBootstrapPreset(params) {
173
173
  userName = "Test User";
174
174
  if (!preferredAddress)
175
175
  preferredAddress = firstName(userName) || "friend";
176
- const identityMd = `# IDENTITY.md - Agent Identity
176
+ const identityMd = `---
177
+ name: ${agentName}
178
+ emoji: ${preset.emoji}
179
+ creature: ${preset.creature}
180
+ vibe: ${preset.vibe}
181
+ ---
182
+ # IDENTITY.md - Agent Identity
177
183
 
178
184
  - Name: ${agentName}
179
185
  - Creature: ${preset.creature}
180
186
  - Vibe: ${preset.vibe}
181
187
  - Emoji: ${preset.emoji}
182
188
  `;
183
- const userMd = `# PROFILE.md - User Profile
189
+ const userMd = `---
190
+ name: ${userName}
191
+ call: ${preferredAddress}
192
+ ---
193
+ # IDENTITY.md - User Identity
184
194
 
185
195
  - Name: ${userName}
186
- - Preferred address: ${preferredAddress}
196
+ - What to call them: ${preferredAddress}
187
197
  - Pronouns (optional):
188
198
  - Timezone (optional):
189
199
  - Notes:
@@ -0,0 +1,85 @@
1
+ import { loadConfig, readConfigFileSnapshot, writeConfigFile } from "../config/config.js";
2
+ import { defaultRuntime } from "../runtime.js";
3
+ function getByPath(obj, key) {
4
+ const parts = key.split(".").filter(Boolean);
5
+ let current = obj;
6
+ for (const part of parts) {
7
+ if (!current || typeof current !== "object")
8
+ return undefined;
9
+ current = current[part];
10
+ }
11
+ return current;
12
+ }
13
+ function setByPath(obj, key, value) {
14
+ const parts = key.split(".").filter(Boolean);
15
+ let current = obj;
16
+ for (let i = 0; i < parts.length; i += 1) {
17
+ const part = parts[i];
18
+ if (i === parts.length - 1) {
19
+ current[part] = value;
20
+ break;
21
+ }
22
+ const next = current[part];
23
+ if (!next || typeof next !== "object") {
24
+ current[part] = {};
25
+ }
26
+ current = current[part];
27
+ }
28
+ return obj;
29
+ }
30
+ function parseValue(raw) {
31
+ const trimmed = raw.trim();
32
+ if (!trimmed)
33
+ return "";
34
+ if (trimmed === "true")
35
+ return true;
36
+ if (trimmed === "false")
37
+ return false;
38
+ if (!Number.isNaN(Number(trimmed)))
39
+ return Number(trimmed);
40
+ if ((trimmed.startsWith("{") && trimmed.endsWith("}")) ||
41
+ (trimmed.startsWith("[") && trimmed.endsWith("]"))) {
42
+ try {
43
+ return JSON.parse(trimmed);
44
+ }
45
+ catch {
46
+ return trimmed;
47
+ }
48
+ }
49
+ return trimmed;
50
+ }
51
+ export async function configListCommand(opts, runtime = defaultRuntime) {
52
+ const snapshot = await readConfigFileSnapshot();
53
+ const payload = snapshot.valid ? snapshot.parsed : {};
54
+ if (opts?.json) {
55
+ runtime.log(JSON.stringify(payload, null, 2));
56
+ return;
57
+ }
58
+ runtime.log(JSON.stringify(payload, null, 2));
59
+ }
60
+ export async function configGetCommand(opts, runtime = defaultRuntime) {
61
+ const config = loadConfig();
62
+ const value = getByPath(config, opts.key);
63
+ if (opts.json) {
64
+ runtime.log(JSON.stringify({ key: opts.key, value }, null, 2));
65
+ return;
66
+ }
67
+ if (typeof value === "string") {
68
+ runtime.log(value);
69
+ return;
70
+ }
71
+ runtime.log(JSON.stringify(value ?? null, null, 2));
72
+ }
73
+ export async function configSetCommand(opts, runtime = defaultRuntime) {
74
+ const snapshot = await readConfigFileSnapshot();
75
+ const base = snapshot.valid && snapshot.parsed && typeof snapshot.parsed === "object"
76
+ ? snapshot.parsed
77
+ : {};
78
+ const next = setByPath({ ...base }, opts.key, parseValue(opts.value));
79
+ await writeConfigFile(next);
80
+ if (opts.json) {
81
+ runtime.log(JSON.stringify({ key: opts.key, value: getByPath(next, opts.key) }, null, 2));
82
+ return;
83
+ }
84
+ runtime.log(`Updated ${opts.key}`);
85
+ }
@@ -0,0 +1,240 @@
1
+ import fsp from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { resolveUserPath } from "../utils.js";
4
+ const DEFAULT_SCRIPT_NAME = "nexus-session-start.js";
5
+ const HOOK_SCRIPT = `#!/usr/bin/env node
6
+ const { execFile } = require("child_process");
7
+ const fs = require("fs");
8
+ const fsp = require("fs/promises");
9
+ const os = require("os");
10
+ const path = require("path");
11
+
12
+ const MAX_IDENTITY_CHARS = 120000;
13
+ const MAX_MEMORY_CHARS = 120000;
14
+ const MAX_DAILY_CHARS = 40000;
15
+ const MAX_BOOTSTRAP_CHARS = 80000;
16
+
17
+ function readStdin() {
18
+ return new Promise((resolve) => {
19
+ let data = "";
20
+ process.stdin.setEncoding("utf8");
21
+ process.stdin.on("data", (chunk) => {
22
+ data += chunk;
23
+ });
24
+ process.stdin.on("end", () => resolve(data));
25
+ });
26
+ }
27
+
28
+ function safeJsonParse(raw) {
29
+ if (!raw || !raw.trim()) return null;
30
+ try {
31
+ return JSON.parse(raw);
32
+ } catch {
33
+ return null;
34
+ }
35
+ }
36
+
37
+ function formatDate(date) {
38
+ const year = date.getFullYear();
39
+ const month = String(date.getMonth() + 1).padStart(2, "0");
40
+ const day = String(date.getDate()).padStart(2, "0");
41
+ return \`\${year}-\${month}-\${day}\`;
42
+ }
43
+
44
+ function resolveWorkspaceRoot(payload) {
45
+ const roots = payload?.workspace_roots;
46
+ if (Array.isArray(roots) && roots.length > 0 && roots[0]) {
47
+ return roots[0];
48
+ }
49
+ if (process.env.NEXUS_ROOT?.trim()) return process.env.NEXUS_ROOT.trim();
50
+ const home = os.homedir();
51
+ if (home) return path.join(home, "nexus");
52
+ return process.cwd();
53
+ }
54
+
55
+ function resolveStateDir(workspaceRoot) {
56
+ if (process.env.NEXUS_STATE_DIR?.trim()) {
57
+ return process.env.NEXUS_STATE_DIR.trim();
58
+ }
59
+ return path.join(workspaceRoot, "state");
60
+ }
61
+
62
+ function execFileAsync(command, args, options) {
63
+ return new Promise((resolve) => {
64
+ execFile(command, args, options, (error, stdout, stderr) => {
65
+ resolve({ error, stdout, stderr });
66
+ });
67
+ });
68
+ }
69
+
70
+ async function runStatus(env, cwd) {
71
+ const result = await execFileAsync("nexus", ["status", "--json"], {
72
+ env,
73
+ cwd,
74
+ });
75
+ const parsed = safeJsonParse(result.stdout);
76
+ if (parsed) return parsed;
77
+ if (result.error && result.error.stdout) {
78
+ const fallback = safeJsonParse(result.error.stdout.toString());
79
+ if (fallback) return fallback;
80
+ }
81
+ return null;
82
+ }
83
+
84
+ async function readFileSnippet(filePath, limit) {
85
+ if (!filePath) return null;
86
+ try {
87
+ const content = await fsp.readFile(filePath, "utf8");
88
+ if (!content.trim()) return null;
89
+ if (content.length <= limit) return content.trim();
90
+ const slice = content.slice(-limit).trimStart();
91
+ return \`\${slice}\\n\\n[truncated]\`;
92
+ } catch {
93
+ return null;
94
+ }
95
+ }
96
+
97
+ function addSection(sections, title, body) {
98
+ if (!body) return;
99
+ sections.push(\`## \${title}\\n\${body}\`);
100
+ }
101
+
102
+ async function main() {
103
+ const input = await readStdin();
104
+ const payload = safeJsonParse(input) || {};
105
+ const workspaceRoot = resolveWorkspaceRoot(payload);
106
+ const stateDir = resolveStateDir(workspaceRoot);
107
+ const env = {
108
+ ...process.env,
109
+ NEXUS_ROOT: workspaceRoot,
110
+ NEXUS_STATE_DIR: stateDir,
111
+ };
112
+ const status = await runStatus(env, workspaceRoot);
113
+ const identity = status?.identity || null;
114
+ const agentId = identity?.agentId || process.env.NEXUS_AGENT_ID || "default";
115
+ const agentIdentityPath =
116
+ identity?.agentIdentityPath ||
117
+ path.join(stateDir, "agents", agentId, "IDENTITY.md");
118
+ const agentSoulPath =
119
+ identity?.agentSoulPath || path.join(stateDir, "agents", agentId, "SOUL.md");
120
+ const agentMemoryPath =
121
+ identity?.agentMemoryPath ||
122
+ path.join(stateDir, "agents", agentId, "MEMORY.md");
123
+ const userIdentityPath =
124
+ identity?.userIdentityPath || path.join(stateDir, "user", "IDENTITY.md");
125
+ const userProfilePath = path.join(stateDir, "user", "PROFILE.md");
126
+ const resolvedUserPath = fs.existsSync(userIdentityPath)
127
+ ? userIdentityPath
128
+ : fs.existsSync(userProfilePath)
129
+ ? userProfilePath
130
+ : userIdentityPath;
131
+
132
+ const sections = ["# Nexus Session Bootstrap"];
133
+ if (identity) {
134
+ const summary = [
135
+ \`Agent: \${identity.agentName || "(unknown)"} (\${identity.agentId})\`,
136
+ \`User: \${identity.userName || "(unknown)"}\`,
137
+ \`Agent ID: \${identity.agentId}\`,
138
+ ];
139
+ addSection(sections, "Status", summary.join("\\n"));
140
+ }
141
+
142
+ const bootstrapPath =
143
+ status?.identity?.bootstrapPath ||
144
+ path.join(stateDir, "agents", "BOOTSTRAP.md");
145
+ const hasIdentity =
146
+ typeof identity?.hasIdentity === "boolean"
147
+ ? identity.hasIdentity
148
+ : fs.existsSync(agentIdentityPath) && fs.existsSync(resolvedUserPath);
149
+ let bootstrapPrompt = status?.bootstrap?.prompt || null;
150
+ if (!bootstrapPrompt && !hasIdentity) {
151
+ bootstrapPrompt = await readFileSnippet(
152
+ bootstrapPath,
153
+ MAX_BOOTSTRAP_CHARS,
154
+ );
155
+ }
156
+ if (bootstrapPrompt) {
157
+ addSection(sections, "Bootstrap Prompt", bootstrapPrompt.trim());
158
+ }
159
+
160
+ const agentIdentity = await readFileSnippet(
161
+ agentIdentityPath,
162
+ MAX_IDENTITY_CHARS,
163
+ );
164
+ const agentSoul = await readFileSnippet(agentSoulPath, MAX_IDENTITY_CHARS);
165
+ const agentMemory = await readFileSnippet(agentMemoryPath, MAX_MEMORY_CHARS);
166
+ const userIdentity = await readFileSnippet(
167
+ resolvedUserPath,
168
+ MAX_IDENTITY_CHARS,
169
+ );
170
+
171
+ addSection(sections, "Agent Identity", agentIdentity);
172
+ addSection(sections, "Agent Soul", agentSoul);
173
+ addSection(sections, "Agent Memory", agentMemory);
174
+ addSection(sections, "User Identity", userIdentity);
175
+
176
+ const memoryDir = path.join(workspaceRoot, "home", "memory");
177
+ const today = formatDate(new Date());
178
+ const yesterday = formatDate(new Date(Date.now() - 86400000));
179
+ const todayLog = await readFileSnippet(
180
+ path.join(memoryDir, \`\${today}.md\`),
181
+ MAX_DAILY_CHARS,
182
+ );
183
+ const yesterdayLog = await readFileSnippet(
184
+ path.join(memoryDir, \`\${yesterday}.md\`),
185
+ MAX_DAILY_CHARS,
186
+ );
187
+
188
+ addSection(sections, \`Daily Memory (\${today})\`, todayLog);
189
+ addSection(sections, \`Daily Memory (\${yesterday})\`, yesterdayLog);
190
+
191
+ const additional = sections.join("\\n\\n").trim();
192
+ const output = { continue: true, additional_context: additional };
193
+ const envOut = {};
194
+ if (!process.env.NEXUS_ROOT?.trim() && workspaceRoot) {
195
+ envOut.NEXUS_ROOT = workspaceRoot;
196
+ }
197
+ if (!process.env.NEXUS_STATE_DIR?.trim() && stateDir) {
198
+ envOut.NEXUS_STATE_DIR = stateDir;
199
+ }
200
+ if (Object.keys(envOut).length > 0) {
201
+ output.env = envOut;
202
+ }
203
+ process.stdout.write(JSON.stringify(output) + "\\n");
204
+ }
205
+
206
+ main().catch(() => {
207
+ process.stdout.write(JSON.stringify({ continue: true }) + "\\n");
208
+ });
209
+ `;
210
+ async function writeFileIfMissing(filePath, content) {
211
+ try {
212
+ await fsp.writeFile(filePath, content, { encoding: "utf-8", flag: "wx" });
213
+ return true;
214
+ }
215
+ catch (err) {
216
+ const anyErr = err;
217
+ if (anyErr.code === "EEXIST")
218
+ return false;
219
+ throw err;
220
+ }
221
+ }
222
+ export async function writeCursorHooks(options = {}) {
223
+ const workspaceDir = resolveUserPath(options.workspaceDir ?? process.cwd());
224
+ const hooksPath = options.hooksPath ?? path.join(workspaceDir, ".cursor", "hooks.json");
225
+ const scriptPath = options.scriptPath ??
226
+ path.join(workspaceDir, ".cursor", "hooks", DEFAULT_SCRIPT_NAME);
227
+ await fsp.mkdir(path.dirname(hooksPath), { recursive: true });
228
+ await fsp.mkdir(path.dirname(scriptPath), { recursive: true });
229
+ const hooksConfig = JSON.stringify({
230
+ version: 1,
231
+ hooks: {
232
+ sessionStart: [
233
+ { command: `node .cursor/hooks/${DEFAULT_SCRIPT_NAME}` },
234
+ ],
235
+ },
236
+ }, null, 2);
237
+ const hooksCreated = await writeFileIfMissing(hooksPath, `${hooksConfig}\n`);
238
+ const scriptCreated = await writeFileIfMissing(scriptPath, HOOK_SCRIPT);
239
+ return { hooksPath, scriptPath, hooksCreated, scriptCreated };
240
+ }