trybeacon 0.1.63 → 0.1.64

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 (113) hide show
  1. package/.claude-plugin/plugin.json +19 -0
  2. package/.next/BUILD_ID +1 -1
  3. package/.next/app-path-routes-manifest.json +13 -13
  4. package/.next/build-manifest.json +2 -2
  5. package/.next/prerender-manifest.json +3 -3
  6. package/.next/required-server-files.js +1 -1
  7. package/.next/required-server-files.json +1 -1
  8. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  9. package/.next/server/app/_global-error.html +1 -1
  10. package/.next/server/app/_global-error.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  14. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  15. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  16. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  17. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  18. package/.next/server/app/_not-found.html +1 -1
  19. package/.next/server/app/_not-found.rsc +2 -2
  20. package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  21. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  22. package/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  23. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  24. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  25. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  26. package/.next/server/app/api/share/create/route.js +1 -1
  27. package/.next/server/app/api/share/route.js +1 -1
  28. package/.next/server/app/docs/page_client-reference-manifest.js +1 -1
  29. package/.next/server/app/docs.html +1 -1
  30. package/.next/server/app/docs.rsc +3 -3
  31. package/.next/server/app/docs.segments/_full.segment.rsc +3 -3
  32. package/.next/server/app/docs.segments/_head.segment.rsc +1 -1
  33. package/.next/server/app/docs.segments/_index.segment.rsc +2 -2
  34. package/.next/server/app/docs.segments/_tree.segment.rsc +3 -3
  35. package/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +2 -2
  36. package/.next/server/app/docs.segments/docs.segment.rsc +1 -1
  37. package/.next/server/app/feedback/page_client-reference-manifest.js +1 -1
  38. package/.next/server/app/feedback.html +1 -1
  39. package/.next/server/app/feedback.rsc +2 -2
  40. package/.next/server/app/feedback.segments/_full.segment.rsc +2 -2
  41. package/.next/server/app/feedback.segments/_head.segment.rsc +1 -1
  42. package/.next/server/app/feedback.segments/_index.segment.rsc +2 -2
  43. package/.next/server/app/feedback.segments/_tree.segment.rsc +2 -2
  44. package/.next/server/app/feedback.segments/feedback/__PAGE__.segment.rsc +1 -1
  45. package/.next/server/app/feedback.segments/feedback.segment.rsc +1 -1
  46. package/.next/server/app/help/page_client-reference-manifest.js +1 -1
  47. package/.next/server/app/help.html +1 -1
  48. package/.next/server/app/help.rsc +2 -2
  49. package/.next/server/app/help.segments/_full.segment.rsc +2 -2
  50. package/.next/server/app/help.segments/_head.segment.rsc +1 -1
  51. package/.next/server/app/help.segments/_index.segment.rsc +2 -2
  52. package/.next/server/app/help.segments/_tree.segment.rsc +2 -2
  53. package/.next/server/app/help.segments/help/__PAGE__.segment.rsc +1 -1
  54. package/.next/server/app/help.segments/help.segment.rsc +1 -1
  55. package/.next/server/app/index.html +1 -1
  56. package/.next/server/app/index.rsc +4 -4
  57. package/.next/server/app/index.segments/__PAGE__.segment.rsc +3 -3
  58. package/.next/server/app/index.segments/_full.segment.rsc +4 -4
  59. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  60. package/.next/server/app/index.segments/_index.segment.rsc +2 -2
  61. package/.next/server/app/index.segments/_tree.segment.rsc +3 -3
  62. package/.next/server/app/map/page.js +1 -1
  63. package/.next/server/app/map/page.js.nft.json +1 -1
  64. package/.next/server/app/map/page_client-reference-manifest.js +1 -1
  65. package/.next/server/app/page.js +1 -1
  66. package/.next/server/app/page_client-reference-manifest.js +1 -1
  67. package/.next/server/app/plan/page.js +2 -2
  68. package/.next/server/app/plan/page.js.nft.json +1 -1
  69. package/.next/server/app/plan/page_client-reference-manifest.js +1 -1
  70. package/.next/server/app/s/[token]/page.js +1 -1
  71. package/.next/server/app/s/[token]/page.js.nft.json +1 -1
  72. package/.next/server/app/s/[token]/page_client-reference-manifest.js +1 -1
  73. package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  74. package/.next/server/app-paths-manifest.json +13 -13
  75. package/.next/server/chunks/{2343.js → 4384.js} +1 -1
  76. package/.next/server/middleware-build-manifest.js +1 -1
  77. package/.next/server/pages/404.html +1 -1
  78. package/.next/server/pages/500.html +1 -1
  79. package/.next/server/server-reference-manifest.js +1 -1
  80. package/.next/server/server-reference-manifest.json +1 -1
  81. package/.next/static/chunks/3415-05007c2bd98125c7.js +1 -0
  82. package/.next/static/chunks/app/map/{page-af4a5a1f12413f4d.js → page-491d4767dbc4e954.js} +1 -1
  83. package/.next/static/chunks/app/{page-6f46e6682942af3a.js → page-d08947a671077569.js} +1 -1
  84. package/.next/static/chunks/app/plan/{page-6213cdfdbee97ad6.js → page-a90e0981499546e3.js} +1 -1
  85. package/.next/static/chunks/app/s/[token]/{page-5c21314106b5ae91.js → page-5c8f260e75758b02.js} +1 -1
  86. package/.next/static/css/490566ec68a48e1a.css +1 -0
  87. package/.next/static/css/53e84df868515cf7.css +1 -0
  88. package/.next/trace +42 -42
  89. package/.next/trace-build +1 -1
  90. package/LICENSE +201 -0
  91. package/README.md +39 -8
  92. package/bun.lock +2274 -0
  93. package/dist/bin/beacon.js +14 -14
  94. package/dist/bin/boot.js +4 -0
  95. package/dist/bin/doctor.js +28 -28
  96. package/dist/bin/hook.js +24 -24
  97. package/dist/bin/mcp.js +30 -30
  98. package/dist/bin/plan.js +25 -25
  99. package/dist/bin/uninstall.js +27 -27
  100. package/dist/lib/codex-install.js +25 -25
  101. package/dist/lib/global-install.js +24 -24
  102. package/package.json +16 -3
  103. package/plugin/commands/beacon.md +11 -0
  104. package/plugin/hooks.json +70 -0
  105. package/plugin/mcp.json +10 -0
  106. package/plugin/skills/beacon-init/SKILL.md +47 -0
  107. package/plugin/skills/beacon-plan/SKILL.md +48 -0
  108. package/plugin/skills/beacon-refresh/SKILL.md +47 -0
  109. package/.next/static/chunks/5780-fd253c7329871c77.js +0 -1
  110. package/.next/static/css/e63457bec0b3ee27.css +0 -1
  111. package/.next/static/css/f86b3e50f4e93bc8.css +0 -1
  112. /package/.next/static/{kt65bLHd8wfwQxMb3ivew → qoq7TibU72duRZATxeVnT}/_buildManifest.js +0 -0
  113. /package/.next/static/{kt65bLHd8wfwQxMb3ivew → qoq7TibU72duRZATxeVnT}/_ssgManifest.js +0 -0
@@ -1,21 +1,21 @@
1
1
  // @bun
2
- var bq=Object.defineProperty;var uq=(q)=>q;function wq(q,z){this[q]=uq.bind(null,z)}var d=(q,z)=>{for(var J in z)bq(q,J,{get:z[J],enumerable:!0,configurable:!0,set:wq.bind(z,J)})};var X=(q,z)=>()=>(q&&(z=q(q=0)),z);var lq=1500,dq=480000,sq=1800000,w=3600000,cq=3000;var s=()=>{};var n={};d(n,{removeRepoAssets:()=>Dq,installRefreshSkill:()=>gq,installPlanSkill:()=>Kq,installInitSkill:()=>jq,installCodexRepoSkills:()=>Nq,ensureWorkflowDoc:()=>Mq,ensureMcp:()=>fq,auditRepo:()=>Rq,REFRESH_SKILL:()=>L,PLAN_SKILL:()=>t,INIT_SKILL:()=>E});import{existsSync as v,mkdirSync as g,readFileSync as H,rmSync as j,writeFileSync as W}from"fs";import{join as $}from"path";function jq(q){let z=$(q,".claude","skills","beacon-init");g(z,{recursive:!0});let J=$(z,"SKILL.md");return W(J,E),J}function gq(q){let z=$(q,".claude","skills","beacon-refresh");g(z,{recursive:!0});let J=$(z,"SKILL.md");return W(J,L),J}function Kq(q){let z=$(q,".claude","skills","beacon-plan");g(z,{recursive:!0});let J=$(z,"SKILL.md");return W(J,t),J}function Nq(q){let z=[];for(let J of Cq){let Q=$(q,".agents","skills",J.name);g(Q,{recursive:!0});let V=$(Q,"SKILL.md");W(V,J.body()),z.push(V)}return z}function Mq(q){let z=$(q,"AGENTS.md"),J="";try{J=H(z,"utf8")}catch{}let Q=new RegExp(`${K}[\\s\\S]*?${y}`);J=Q.test(J)?J.replace(Q,c):`${J.trim()}
2
+ var uq=Object.defineProperty;var wq=(q)=>q;function bq(q,z){this[q]=wq.bind(null,z)}var d=(q,z)=>{for(var J in z)uq(q,J,{get:z[J],enumerable:!0,configurable:!0,set:bq.bind(z,J)})};var x=(q,z)=>()=>(q&&(z=q(q=0)),z);var dq=1500,cq=480000,tq=1800000,g=3600000,nq=3000;var c=()=>{};var r={};d(r,{removeRepoAssets:()=>Iq,installRefreshSkill:()=>gq,installPlanSkill:()=>Kq,installInitSkill:()=>jq,installCodexRepoSkills:()=>Nq,ensureWorkflowDoc:()=>Mq,ensureMcp:()=>Rq,auditRepo:()=>fq,REFRESH_SKILL:()=>O,PLAN_SKILL:()=>n,INIT_SKILL:()=>L});import{existsSync as X,mkdirSync as C,readFileSync as B,rmSync as K,writeFileSync as W}from"fs";import{join as $}from"path";function jq(q){let z=$(q,".claude","skills","beacon-init");C(z,{recursive:!0});let J=$(z,"SKILL.md");return W(J,L),J}function gq(q){let z=$(q,".claude","skills","beacon-refresh");C(z,{recursive:!0});let J=$(z,"SKILL.md");return W(J,O),J}function Kq(q){let z=$(q,".claude","skills","beacon-plan");C(z,{recursive:!0});let J=$(z,"SKILL.md");return W(J,n),J}function Nq(q){let z=[];for(let J of Cq){let Q=$(q,".agents","skills",J.name);C(Q,{recursive:!0});let V=$(Q,"SKILL.md");W(V,J.body()),z.push(V)}return z}function Mq(q){let z=$(q,"AGENTS.md"),J="";try{J=B(z,"utf8")}catch{}let Q=new RegExp(`${N}[\\s\\S]*?${y}`);J=Q.test(J)?J.replace(Q,t):`${J.trim()}
3
3
 
4
- ${c}
4
+ ${t}
5
5
  `.trimStart(),W(z,J.endsWith(`
6
6
  `)?J:`${J}
7
- `);let V=$(q,"CLAUDE.md"),Y="";try{Y=H(V,"utf8")}catch{}if(!/@AGENTS\.md/.test(Y))W(V,`${Y?`${Y.trim()}
7
+ `);let V=$(q,"CLAUDE.md"),Y="";try{Y=B(V,"utf8")}catch{}if(!/@AGENTS\.md/.test(Y))W(V,`${Y?`${Y.trim()}
8
8
 
9
9
  `:""}@AGENTS.md
10
- `)}function fq(q){let z=$(q,".mcp.json"),J={};try{J=JSON.parse(H(z,"utf8"))}catch{}J.mcpServers=J.mcpServers??{};let Q=J.mcpServers.beacon;if(Q){if(!Q.timeout||Q.timeout<w)return Q.timeout=w,W(z,JSON.stringify(J,null,2)+`
11
- `),{path:z,added:!1,updated:!0};return{path:z,added:!1,updated:!1}}return J.mcpServers.beacon={command:"beacon",args:["mcp"],timeout:w},W(z,JSON.stringify(J,null,2)+`
12
- `),{path:z,added:!0,updated:!1}}function Rq(q){let z=$(q,".mcp.json"),J=!1;try{J=!!JSON.parse(H(z,"utf8")).mcpServers?.beacon}catch{}let Q=!1;try{Q=H($(q,"AGENTS.md"),"utf8").includes(K)}catch{}let V=!1;try{V=/@AGENTS\.md/.test(H($(q,"CLAUDE.md"),"utf8"))}catch{}return{repo:q,mcpRegistered:J,agentsMdBlock:Q,claudeMdImport:V,skills:{"beacon-init":v($(q,".claude","skills","beacon-init","SKILL.md")),"beacon-refresh":v($(q,".claude","skills","beacon-refresh","SKILL.md"))},codexSkills:{"beacon-init":v($(q,".agents","skills","beacon-init","SKILL.md")),"beacon-refresh":v($(q,".agents","skills","beacon-refresh","SKILL.md"))}}}function Dq(q){let z=[];for(let Z of["beacon-init","beacon-refresh","beacon-db-design"]){let P=$(q,".claude","skills",Z);if(v(P))j(P,{recursive:!0,force:!0}),z.push(Z)}for(let Z of["beacon-init","beacon-refresh"]){let P=$(q,".agents","skills",Z);if(v(P))j(P,{recursive:!0,force:!0}),z.push(`codex:${Z}`)}let J=!1,Q=$(q,".mcp.json");try{let Z=JSON.parse(H(Q,"utf8"));if(Z.mcpServers?.beacon){if(delete Z.mcpServers.beacon,J=!0,Z.mcpServers&&Object.keys(Z.mcpServers).length===0)delete Z.mcpServers;if(Object.keys(Z).length===0)j(Q,{force:!0});else W(Q,JSON.stringify(Z,null,2)+`
13
- `)}}catch{}let V=!1,Y=$(q,"AGENTS.md");try{let Z=H(Y,"utf8"),P=new RegExp(`\\n?${K}[\\s\\S]*?${y}\\n?`);if(P.test(Z)){let k=Z.replace(P,`
10
+ `)}function Rq(q){let z=$(q,".mcp.json"),J={};try{J=JSON.parse(B(z,"utf8"))}catch{}J.mcpServers=J.mcpServers??{};let Q=J.mcpServers.beacon;if(Q){if(!Q.timeout||Q.timeout<g)return Q.timeout=g,W(z,JSON.stringify(J,null,2)+`
11
+ `),{path:z,added:!1,updated:!0};return{path:z,added:!1,updated:!1}}return J.mcpServers.beacon={command:"beacon",args:["mcp"],timeout:g},W(z,JSON.stringify(J,null,2)+`
12
+ `),{path:z,added:!0,updated:!1}}function fq(q){let z=$(q,".mcp.json"),J=!1;try{J=!!JSON.parse(B(z,"utf8")).mcpServers?.beacon}catch{}let Q=!1;try{Q=B($(q,"AGENTS.md"),"utf8").includes(N)}catch{}let V=!1;try{V=/@AGENTS\.md/.test(B($(q,"CLAUDE.md"),"utf8"))}catch{}return{repo:q,mcpRegistered:J,agentsMdBlock:Q,claudeMdImport:V,skills:{"beacon-init":X($(q,".claude","skills","beacon-init","SKILL.md")),"beacon-refresh":X($(q,".claude","skills","beacon-refresh","SKILL.md"))},codexSkills:{"beacon-init":X($(q,".agents","skills","beacon-init","SKILL.md")),"beacon-refresh":X($(q,".agents","skills","beacon-refresh","SKILL.md"))}}}function Iq(q){let z=[];for(let Z of["beacon-init","beacon-refresh","beacon-db-design"]){let P=$(q,".claude","skills",Z);if(X(P))K(P,{recursive:!0,force:!0}),z.push(Z)}for(let Z of["beacon-init","beacon-refresh"]){let P=$(q,".agents","skills",Z);if(X(P))K(P,{recursive:!0,force:!0}),z.push(`codex:${Z}`)}let J=!1,Q=$(q,".mcp.json");try{let Z=JSON.parse(B(Q,"utf8"));if(Z.mcpServers?.beacon){if(delete Z.mcpServers.beacon,J=!0,Z.mcpServers&&Object.keys(Z.mcpServers).length===0)delete Z.mcpServers;if(Object.keys(Z).length===0)K(Q,{force:!0});else W(Q,JSON.stringify(Z,null,2)+`
13
+ `)}}catch{}let V=!1,Y=$(q,"AGENTS.md");try{let Z=B(Y,"utf8"),P=new RegExp(`\\n?${N}[\\s\\S]*?${y}\\n?`);if(P.test(Z)){let E=Z.replace(P,`
14
14
  `).replace(/\n{3,}/g,`
15
15
 
16
- `).trimStart();W(Y,k.endsWith(`
17
- `)?k:`${k}
18
- `),V=!0}}catch{}let U=!1,B=$(q,"CLAUDE.md");try{let Z=H(B,"utf8"),P=Z.replace(/^[ \t]*@AGENTS\.md[ \t]*\n?/m,"");if(P!==Z){if(!P.trim())j(B,{force:!0});else W(B,P);U=!0}}catch{}return{skillsRemoved:z,mcpUnregistered:J,agentsBlockRemoved:V,claudeImportRemoved:U}}var E=`---
16
+ `).trimStart();W(Y,E.endsWith(`
17
+ `)?E:`${E}
18
+ `),V=!0}}catch{}let U=!1,H=$(q,"CLAUDE.md");try{let Z=B(H,"utf8"),P=Z.replace(/^[ \t]*@AGENTS\.md[ \t]*\n?/m,"");if(P!==Z){if(!P.trim())K(H,{force:!0});else W(H,P);U=!0}}catch{}return{skillsRemoved:z,mcpUnregistered:J,agentsBlockRemoved:V,claudeImportRemoved:U}}var L=`---
19
19
  name: beacon-init
20
20
  description: Read this repository and map its architecture, schema, and roadmap into Beacon (the local visual planning panel). Use when the user runs /beacon-init, asks to "set up Beacon for this repo", or asks to initialize/bootstrap Beacon's map of this codebase.
21
21
  ---
@@ -62,7 +62,7 @@ beacon init-persist /tmp/beacon-init.json # or: beacon init-persist < /tmp/bea
62
62
  That one command wires the repo (writes \`.mcp.json\` + skills so your NEXT session gets the \`beacon_*\` tools natively, heals the global install), starts the Beacon daemon if it isn't running, registers + provisions this workspace, and POSTs your analysis to the same \`/api/init\` endpoint the MCP tool uses \u2014 so init completes in THIS session. Read the counts it prints and report them.
63
63
 
64
64
  After the tool (or \`beacon init-persist\`) returns, tell the user the counts (components / roadmap / tables / endpoints) and point them at the running Beacon panel.
65
- `,L=`---
65
+ `,O=`---
66
66
  name: beacon-refresh
67
67
  description: Re-survey the repo and update Beacon's architecture / schema / endpoints map after /beacon-init was already run \u2014 picks up new components, removed ones, schema changes, and new routes. Use when the user runs /beacon-refresh or asks to "refresh", "update", "re-sync", or "bring Beacon up to date" with the current code.
68
68
  ---
@@ -109,7 +109,7 @@ The one caveat: if the user manually edited an INIT-source node on the canvas (e
109
109
  If \`beacon_entities\` or \`beacon_init_persist\` isn't available, the Beacon panel isn't running in this repo. Tell the user to run \`beacon\` here first, then re-invoke /beacon-refresh.
110
110
 
111
111
  After the tool returns, report the final counts plus a one-line summary of the diff you surfaced.
112
- `,t=`---
112
+ `,n=`---
113
113
  name: beacon-plan
114
114
  description: Present your current plan or approach to the user on Beacon's /plan canvas for review \u2014 instead of asking for approval in prose. Use when the user says "present the plan", "show me the plan", "let me see it / the plan", or whenever you are about to end a turn asking whether to proceed with a plan, design, or approach.
115
115
  ---
@@ -157,7 +157,7 @@ If it returns feedback, revise and call it again.
157
157
  If \`beacon_present_plan\` isn't available, the panel isn't wired here \u2014 fall back to ExitPlanMode
158
158
  with the same \`\`\`beacon block (Claude Code only; Codex has no ExitPlanMode), or tell the user to
159
159
  run \`beacon\` in this repo once.
160
- `,Cq,K="<!-- beacon:workflow:start -->",y="<!-- beacon:workflow:end -->",c;var r=X(()=>{s();Cq=[{name:"beacon-init",body:()=>E},{name:"beacon-refresh",body:()=>L}];c=`${K}
160
+ `,Cq,N="<!-- beacon:workflow:start -->",y="<!-- beacon:workflow:end -->",t;var o=x(()=>{c();Cq=[{name:"beacon-init",body:()=>L},{name:"beacon-refresh",body:()=>O}];t=`${N}
161
161
  ## Beacon \u2014 feature workflow
162
162
 
163
163
  This project uses Beacon (a local planning/visualization panel; run \`beacon\` to open it). When you start work on a FEATURE \u2014 whether referenced via an \`@beacon:feature://\u2026\` mention, an \`@beacon:note://\u2026\` note the user wrote in the Notes panel (treat its checkbox \`- [ ]\` todos as subtasks and order features by their dependencies), or just described in chat \u2014 follow these steps in order:
@@ -225,18 +225,18 @@ Register them all in that single batched call. If a plan added five features, th
225
225
  If the feature added or materially changed a REAL architectural component (a subsystem \u2014 NOT a file), also pass \`architecture: [{ title, domain, role, \u2026 }]\` so the Architecture map stays accurate. It upserts curated components by title; never list files as components. If you found a bug or something worth investigating in a component's code, add \`bugs: [{ note }]\` to its architecture entry \u2014 it renders as a bug flag on the node (attributed to the agent); identical open flags are not duplicated. Only flag what you actually saw in the code.
226
226
 
227
227
  Pull raw planning data anytime with \`beacon_entities\` (features / architecture / tables / endpoints).
228
- ${y}`});import{existsSync as i,mkdirSync as O,readFileSync as N,rmSync as Iq,writeFileSync as M}from"fs";import{dirname as o,join as C}from"path";function h(q){try{return JSON.parse(N(q,"utf8"))}catch{return{}}}function qq(q,z){O(o(q),{recursive:!0}),M(q,JSON.stringify(z,null,2)+`
229
- `)}function zq(q,z){let J=h(q);J.hooks=J.hooks??{},J.hooks[z.event]=J.hooks[z.event]??[];let Q=J.hooks[z.event];if(Q.some((Y)=>Y.matcher===z.matcher&&Y.hooks?.some((U)=>U.command===z.command)))return!1;return Q.push({matcher:z.matcher,hooks:[{type:"command",command:z.command}]}),qq(q,J),!0}function Jq(q,z){return(h(q).hooks?.[z.event]??[]).some((V)=>V.hooks?.some((Y)=>Y.command===z.command))}function Qq(q,z){let J=h(q),Q=J.hooks?.[z.event];if(!Q)return!1;let V=!1,Y=Q.map((U)=>{let B=U.hooks?.length??0,Z=(U.hooks??[]).filter((P)=>P.command!==z.command);if(Z.length!==B)V=!0;return{...U,hooks:Z}}).filter((U)=>(U.hooks??[]).length>0);if(!V)return!1;if(Y.length)J.hooks[z.event]=Y;else delete J.hooks[z.event];if(J.hooks&&Object.keys(J.hooks).length===0)delete J.hooks;return qq(q,J),!0}function Vq(q,z,J,Q){let V=`${z}
228
+ ${y}`});import{existsSync as M,mkdirSync as h,readdirSync as Aq,readFileSync as u,rmSync as Dq,writeFileSync as R}from"fs";import{dirname as i,join as v}from"path";function Jz(){return!!process.env.CLAUDE_PLUGIN_ROOT}function Tq(q=process.env.HOME||process.env.USERPROFILE||""){if(!q)return null;let z=v(q,".claude","plugins");if(!M(z))return null;let J=[z];for(let Q=0;Q<3&&J.length;Q++){let V=[];for(let Y of J){let U=v(Y,".claude-plugin","plugin.json");try{if(M(U)&&JSON.parse(u(U,"utf8")).name==="beacon")return Y}catch{}try{for(let H of Aq(Y,{withFileTypes:!0}))if(H.isDirectory())V.push(v(Y,H.name))}catch{}}J=V}return null}function Qz(q){return Tq(q)!==null}function _(q){try{return JSON.parse(u(q,"utf8"))}catch{return{}}}function qq(q,z){h(i(q),{recursive:!0}),R(q,JSON.stringify(z,null,2)+`
229
+ `)}function zq(q,z){let J=_(q);J.hooks=J.hooks??{},J.hooks[z.event]=J.hooks[z.event]??[];let Q=J.hooks[z.event];if(Q.some((Y)=>Y.matcher===z.matcher&&Y.hooks?.some((U)=>U.command===z.command)))return!1;return Q.push({matcher:z.matcher,hooks:[{type:"command",command:z.command}]}),qq(q,J),!0}function Jq(q,z){return(_(q).hooks?.[z.event]??[]).some((V)=>V.hooks?.some((Y)=>Y.command===z.command))}function Qq(q,z){let J=_(q),Q=J.hooks?.[z.event];if(!Q)return!1;let V=!1,Y=Q.map((U)=>{let H=U.hooks?.length??0,Z=(U.hooks??[]).filter((P)=>P.command!==z.command);if(Z.length!==H)V=!0;return{...U,hooks:Z}}).filter((U)=>(U.hooks??[]).length>0);if(!V)return!1;if(Y.length)J.hooks[z.event]=Y;else delete J.hooks[z.event];if(J.hooks&&Object.keys(J.hooks).length===0)delete J.hooks;return qq(q,J),!0}function Vq(q,z,J,Q){let V=`${z}
230
230
  ${Q.trim()}
231
- ${J}`,Y="";try{Y=N(q,"utf8")}catch{}let U=new RegExp(`${z}[\\s\\S]*?${J}`);Y=U.test(Y)?Y.replace(U,V):Y.trim()?`${Y.trim()}
231
+ ${J}`,Y="";try{Y=u(q,"utf8")}catch{}let U=new RegExp(`${z}[\\s\\S]*?${J}`);Y=U.test(Y)?Y.replace(U,V):Y.trim()?`${Y.trim()}
232
232
 
233
233
  ${V}
234
234
  `:`${V}
235
- `,O(o(q),{recursive:!0}),M(q,Y.endsWith(`
235
+ `,h(i(q),{recursive:!0}),R(q,Y.endsWith(`
236
236
  `)?Y:`${Y}
237
- `)}function _(q,z){try{return N(q,"utf8").includes(z)}catch{return!1}}function Yq(q,z,J){let Q="";try{Q=N(q,"utf8")}catch{return!1}let V=new RegExp(`${z}[\\s\\S]*?${J}\\n?`);if(!V.test(Q))return!1;let Y=Q.replace(V,"").replace(/\n{3,}/g,`
237
+ `)}function m(q,z){try{return u(q,"utf8").includes(z)}catch{return!1}}function Yq(q,z,J){let Q="";try{Q=u(q,"utf8")}catch{return!1}let V=new RegExp(`${z}[\\s\\S]*?${J}\\n?`);if(!V.test(Q))return!1;let Y=Q.replace(V,"").replace(/\n{3,}/g,`
238
238
 
239
- `).trimStart();return M(q,Y),!0}function Zq(q,z,J){let Q=C(q,z);O(Q,{recursive:!0});let V=C(Q,"SKILL.md");return M(V,J),V}function m(q,z){return i(C(q,z,"SKILL.md"))}function $q(q,z){let J=C(q,z);if(!i(J))return!1;return Iq(J,{recursive:!0,force:!0}),!0}var f,e=`## Beacon (visual planning panel)
239
+ `).trimStart();return R(q,Y),!0}function Zq(q,z,J){let Q=v(q,z);h(Q,{recursive:!0});let V=v(Q,"SKILL.md");return R(V,J),V}function S(q,z){return M(v(q,z,"SKILL.md"))}function $q(q,z){let J=v(q,z);if(!M(J))return!1;return Dq(J,{recursive:!0,force:!0}),!0}var f,e=`## Beacon (visual planning panel)
240
240
 
241
241
  This machine has Beacon installed \u2014 a local visual planning surface for the terminal-side
242
242
  agent. Beacon proposes feature plans (roadmap features + DB schema + endpoints) via MCP,
@@ -257,17 +257,17 @@ the user reviews on a canvas at /plan, and feedback flows back as the next round
257
257
  Feedback bundles inline annotations on the markdown PLUS any edits the user made directly
258
258
  on the /map and /db boards (added features, attached subtasks, edited columns, new
259
259
  endpoints). Treat board edits as the user's revision intent \u2014 re-propose matching them
260
- verbatim. Do NOT implement until the tool returns approval.`;var Uq=X(()=>{f=["beacon-init","beacon-refresh","beacon-plan"]});import{mkdirSync as Aq,renameSync as Tq,rmSync as Fq,writeFileSync as kq}from"fs";import{dirname as Eq}from"path";function R(q,z){Aq(Eq(q),{recursive:!0});let J=`${q}.tmp`;try{kq(J,z),Tq(J,q)}catch(Q){throw Fq(J,{force:!0}),Q}}function Qz(q,z,J=!1){R(q,JSON.stringify(z,null,J?2:void 0))}var Pq=()=>{};var Sq={};d(Sq,{setupCodexAssets:()=>hq,removeCodexMcp:()=>Gq,removeCodexArtifacts:()=>mq,hasCodexMcp:()=>l,ensureCodexMcp:()=>Xq,codexMcpProblem:()=>Oq,codexDetected:()=>Bq,auditCodex:()=>_q,CODEX_HOOKS:()=>F});import{readFileSync as T}from"fs";import{homedir as Lq}from"os";import{join as u}from"path";function Wq(){return process.env.HOME||process.env.USERPROFILE||Lq()}function Bq(){if(process.env.BEACON_CODEX==="1")return!0;if(process.env.BEACON_CODEX==="0")return!1;if(S===void 0)S=Bun.which("codex")!==null;return S}function b(q){try{return Bun.TOML.parse(q)}catch{return null}}function l(){try{return Boolean(b(T(x(),"utf8"))?.mcp_servers?.beacon)}catch{return!1}}function Oq(){let q="";try{q=T(x(),"utf8")}catch{return null}let z=b(q);if(!z)return`~/.codex/config.toml does not parse \u2014 ${G}`;if(z.mcp_servers?.beacon)return null;if(/^\s*mcp_servers\s*=/m.test(q))return`mcp_servers is an inline table \u2014 ${G}`;return null}function Xq(){let q="",z=!1;try{q=T(x(),"utf8"),z=!0}catch{}if(z){let Y=b(q);if(!Y)return{added:!1,error:`~/.codex/config.toml does not parse \u2014 ${G}`};if(Y.mcp_servers?.beacon)return{added:!1};if(/^\s*mcp_servers\s*=/m.test(q))return{added:!1,error:`mcp_servers is an inline table \u2014 ${G}`}}let J=!q?"":q.endsWith(`
260
+ verbatim. Do NOT implement until the tool returns approval.`;var Uq=x(()=>{f=["beacon-init","beacon-refresh","beacon-plan"]});import{mkdirSync as kq,renameSync as Fq,rmSync as Eq,writeFileSync as Lq}from"fs";import{dirname as Oq}from"path";function I(q,z){kq(Oq(q),{recursive:!0});let J=`${q}.tmp`;try{Lq(J,z),Fq(J,q)}catch(Q){throw Eq(J,{force:!0}),Q}}function $z(q,z,J=!1){I(q,JSON.stringify(z,null,J?2:void 0))}var Pq=()=>{};var aq={};d(aq,{setupCodexAssets:()=>mq,removeCodexMcp:()=>xq,removeCodexArtifacts:()=>pq,hasCodexMcp:()=>s,ensureCodexMcp:()=>Gq,codexMcpProblem:()=>_q,codexDetected:()=>Bq,auditCodex:()=>Sq,CODEX_HOOKS:()=>F});import{readFileSync as k}from"fs";import{homedir as yq}from"os";import{join as j}from"path";function Wq(){return process.env.HOME||process.env.USERPROFILE||yq()}function Bq(){if(process.env.BEACON_CODEX==="1")return!0;if(process.env.BEACON_CODEX==="0")return!1;if(p===void 0)p=Bun.which("codex")!==null;return p}function b(q){try{return Bun.TOML.parse(q)}catch{return null}}function s(){try{return Boolean(b(k(G(),"utf8"))?.mcp_servers?.beacon)}catch{return!1}}function _q(){let q="";try{q=k(G(),"utf8")}catch{return null}let z=b(q);if(!z)return`~/.codex/config.toml does not parse \u2014 ${w}`;if(z.mcp_servers?.beacon)return null;if(/^\s*mcp_servers\s*=/m.test(q))return`mcp_servers is an inline table \u2014 ${w}`;return null}function Gq(){let q="",z=!1;try{q=k(G(),"utf8"),z=!0}catch{}if(z){let Y=b(q);if(!Y)return{added:!1,error:`~/.codex/config.toml does not parse \u2014 ${w}`};if(Y.mcp_servers?.beacon)return{added:!1};if(/^\s*mcp_servers\s*=/m.test(q))return{added:!1,error:`mcp_servers is an inline table \u2014 ${w}`}}let J=!q?"":q.endsWith(`
261
261
  `)?`
262
262
  `:`
263
263
 
264
- `,Q=q+J+yq;if(b(Q)?.mcp_servers?.beacon?.command!=="beacon")return{added:!1,error:`could not safely append [mcp_servers.beacon] \u2014 ${G}`};return R(x(),Q),{added:!0}}function Gq(){let q="";try{q=T(x(),"utf8")}catch{return{removed:!1}}let z=q.split(`
265
- `),J=z.indexOf(vq);if(J===-1)return{removed:!1,skipped:l()};let Q=z.indexOf(xq,J);if(Q===-1)return{removed:!1,skipped:!0};z.splice(J,Q-J+1);let V=z.join(`
264
+ `,Q=q+J+hq;if(b(Q)?.mcp_servers?.beacon?.command!=="beacon")return{added:!1,error:`could not safely append [mcp_servers.beacon] \u2014 ${w}`};return I(G(),Q),{added:!0}}function xq(){let q="";try{q=k(G(),"utf8")}catch{return{removed:!1}}let z=q.split(`
265
+ `),J=z.indexOf(vq);if(J===-1)return{removed:!1,skipped:s()};let Q=z.indexOf(Xq,J);if(Q===-1)return{removed:!1,skipped:!0};z.splice(J,Q-J+1);let V=z.join(`
266
266
  `).replace(/\n{3,}/g,`
267
267
 
268
- `).replace(/^\n+/,"");if(b(V)===null)return{removed:!1,skipped:!0};return R(x(),V),{removed:!0}}async function hq(){let{INIT_SKILL:q,REFRESH_SKILL:z,PLAN_SKILL:J}=await Promise.resolve().then(() => (r(),n)),Q={"beacon-init":q,"beacon-refresh":z,"beacon-plan":J},V=[];for(let Z of f){if(!m(I(),Z))V.push(Z);Zq(I(),Z,Q[Z])}let Y=0;for(let Z of F)if(zq(a(),{event:Z.event,matcher:Z.matcher,command:Z.command}))Y++;let U=_(D(),A);Vq(D(),A,Hq,e);let B=Xq();return{skillsAdded:V,hooksAdded:Y,agentsMdBlockTouched:!U,mcp:B}}function _q(){let q={};for(let J of f)q[J]=m(I(),J);let z={};for(let J of F)z[J.event]=Jq(a(),{event:J.event,command:J.command});return{detected:Bq(),skills:q,hooks:z,agentsMdBlock:_(D(),A),mcp:l()}}function mq(){let q=[];for(let V of f)if($q(I(),V))q.push(V);let z=0;for(let V of F)if(Qq(a(),{event:V.event,command:V.command}))z++;let J=Yq(D(),A,Hq),Q=Gq();return{skillsRemoved:q,hooksRemoved:z,agentsMdBlockRemoved:J,mcpRemoved:Q.removed,mcpSkipped:Q.skipped}}var p=()=>u(Wq(),".codex"),a=()=>u(p(),"hooks.json"),x=()=>u(p(),"config.toml"),D=()=>u(p(),"AGENTS.md"),I=()=>u(Wq(),".agents","skills"),A="<!-- beacon:global:start -->",Hq="<!-- beacon:global:end -->",F,S,vq="# beacon:start (managed by Beacon \u2014 `beacon uninstall` removes this block)",xq="# beacon:end",yq,G="add it manually: codex mcp add beacon -- beacon mcp";var pq=X(()=>{Uq();Pq();F=[{event:"PostToolUse",matcher:"apply_patch",command:"beacon hook",description:"Report file edits to Beacon's active feature so the map stays fresh."},{event:"UserPromptSubmit",matcher:"*",command:"beacon prompt",description:"On feature-y prompts in a Beacon-wired repo, remind the agent to run the context\u2192propose\u2192describe loop (no-op otherwise)."},{event:"Stop",matcher:"*",command:"beacon stop-hook",description:"When the agent ends a turn asking for plan approval in prose, nudge it to present the plan on Beacon's /plan canvas."}];yq=`${vq}
268
+ `).replace(/^\n+/,"");if(b(V)===null)return{removed:!1,skipped:!0};return I(G(),V),{removed:!0}}async function mq(){let{INIT_SKILL:q,REFRESH_SKILL:z,PLAN_SKILL:J}=await Promise.resolve().then(() => (o(),r)),Q={"beacon-init":q,"beacon-refresh":z,"beacon-plan":J},V=[];for(let Z of f){if(!S(D(),Z))V.push(Z);Zq(D(),Z,Q[Z])}let Y=0;for(let Z of F)if(zq(l(),{event:Z.event,matcher:Z.matcher,command:Z.command}))Y++;let U=m(A(),T);Vq(A(),T,Hq,e);let H=Gq();return{skillsAdded:V,hooksAdded:Y,agentsMdBlockTouched:!U,mcp:H}}function Sq(){let q={};for(let J of f)q[J]=S(D(),J);let z={};for(let J of F)z[J.event]=Jq(l(),{event:J.event,command:J.command});return{detected:Bq(),skills:q,hooks:z,agentsMdBlock:m(A(),T),mcp:s()}}function pq(){let q=[];for(let V of f)if($q(D(),V))q.push(V);let z=0;for(let V of F)if(Qq(l(),{event:V.event,command:V.command}))z++;let J=Yq(A(),T,Hq),Q=xq();return{skillsRemoved:q,hooksRemoved:z,agentsMdBlockRemoved:J,mcpRemoved:Q.removed,mcpSkipped:Q.skipped}}var a=()=>j(Wq(),".codex"),l=()=>j(a(),"hooks.json"),G=()=>j(a(),"config.toml"),A=()=>j(a(),"AGENTS.md"),D=()=>j(Wq(),".agents","skills"),T="<!-- beacon:global:start -->",Hq="<!-- beacon:global:end -->",F,p,vq="# beacon:start (managed by Beacon \u2014 `beacon uninstall` removes this block)",Xq="# beacon:end",hq,w="add it manually: codex mcp add beacon -- beacon mcp";var lq=x(()=>{Uq();Pq();F=[{event:"PostToolUse",matcher:"apply_patch",command:"beacon hook",description:"Report file edits to Beacon's active feature so the map stays fresh."},{event:"UserPromptSubmit",matcher:"*",command:"beacon prompt",description:"On feature-y prompts in a Beacon-wired repo, remind the agent to run the context\u2192propose\u2192describe loop (no-op otherwise)."},{event:"Stop",matcher:"*",command:"beacon stop-hook",description:"When the agent ends a turn asking for plan approval in prose, nudge it to present the plan on Beacon's /plan canvas."}];hq=`${vq}
269
269
  [mcp_servers.beacon]
270
270
  command = "beacon"
271
271
  args = ["mcp"]
272
- ${xq}
273
- `});pq();export{hq as setupCodexAssets,Gq as removeCodexMcp,mq as removeCodexArtifacts,l as hasCodexMcp,Xq as ensureCodexMcp,Oq as codexMcpProblem,Bq as codexDetected,_q as auditCodex,F as CODEX_HOOKS};
272
+ ${Xq}
273
+ `});lq();export{mq as setupCodexAssets,xq as removeCodexMcp,pq as removeCodexArtifacts,s as hasCodexMcp,Gq as ensureCodexMcp,_q as codexMcpProblem,Bq as codexDetected,Sq as auditCodex,F as CODEX_HOOKS};
@@ -1,21 +1,21 @@
1
1
  // @bun
2
- var Tq=Object.defineProperty;var Iq=(q)=>q;function yq(q,z){this[q]=Iq.bind(null,z)}var Wq=(q,z)=>{for(var J in z)Tq(q,J,{get:z[J],enumerable:!0,configurable:!0,set:yq.bind(z,J)})};var j=(q,z)=>()=>(q&&(z=q(q=0)),z);var xz=1500,Hz=480000,wz=1800000,b=3600000,vz=3000;var Xq=()=>{};var s={};Wq(s,{removeRepoAssets:()=>mq,installRefreshSkill:()=>Aq,installPlanSkill:()=>Eq,installInitSkill:()=>Dq,installCodexRepoSkills:()=>kq,ensureWorkflowDoc:()=>hq,ensureMcp:()=>Lq,auditRepo:()=>_q,REFRESH_SKILL:()=>n,PLAN_SKILL:()=>xq,INIT_SKILL:()=>d});import{existsSync as w,mkdirSync as f,readFileSync as x,rmSync as K,writeFileSync as U}from"fs";import{join as $}from"path";function Dq(q){let z=$(q,".claude","skills","beacon-init");f(z,{recursive:!0});let J=$(z,"SKILL.md");return U(J,d),J}function Aq(q){let z=$(q,".claude","skills","beacon-refresh");f(z,{recursive:!0});let J=$(z,"SKILL.md");return U(J,n),J}function Eq(q){let z=$(q,".claude","skills","beacon-plan");f(z,{recursive:!0});let J=$(z,"SKILL.md");return U(J,xq),J}function kq(q){let z=[];for(let J of Oq){let Q=$(q,".agents","skills",J.name);f(Q,{recursive:!0});let V=$(Q,"SKILL.md");U(V,J.body()),z.push(V)}return z}function hq(q){let z=$(q,"AGENTS.md"),J="";try{J=x(z,"utf8")}catch{}let Q=new RegExp(`${C}[\\s\\S]*?${r}`);J=Q.test(J)?J.replace(Q,Uq):`${J.trim()}
2
+ var yq=Object.defineProperty;var Aq=(q)=>q;function Dq(q,z){this[q]=Aq.bind(null,z)}var Xq=(q,z)=>{for(var J in z)yq(q,J,{get:z[J],enumerable:!0,configurable:!0,set:Dq.bind(z,J)})};var B=(q,z)=>()=>(q&&(z=q(q=0)),z);var Bz=1500,gz=480000,Nz=1800000,C=3600000,Gz=3000;var Uq=()=>{};var l={};Xq(l,{removeRepoAssets:()=>cq,installRefreshSkill:()=>kq,installPlanSkill:()=>hq,installInitSkill:()=>Oq,installCodexRepoSkills:()=>_q,ensureWorkflowDoc:()=>pq,ensureMcp:()=>mq,auditRepo:()=>Sq,REFRESH_SKILL:()=>n,PLAN_SKILL:()=>wq,INIT_SKILL:()=>r});import{existsSync as v,mkdirSync as F,readFileSync as H,rmSync as f,writeFileSync as U}from"fs";import{join as $}from"path";function Oq(q){let z=$(q,".claude","skills","beacon-init");F(z,{recursive:!0});let J=$(z,"SKILL.md");return U(J,r),J}function kq(q){let z=$(q,".claude","skills","beacon-refresh");F(z,{recursive:!0});let J=$(z,"SKILL.md");return U(J,n),J}function hq(q){let z=$(q,".claude","skills","beacon-plan");F(z,{recursive:!0});let J=$(z,"SKILL.md");return U(J,wq),J}function _q(q){let z=[];for(let J of Lq){let Q=$(q,".agents","skills",J.name);F(Q,{recursive:!0});let V=$(Q,"SKILL.md");U(V,J.body()),z.push(V)}return z}function pq(q){let z=$(q,"AGENTS.md"),J="";try{J=H(z,"utf8")}catch{}let Q=new RegExp(`${R}[\\s\\S]*?${s}`);J=Q.test(J)?J.replace(Q,Hq):`${J.trim()}
3
3
 
4
- ${Uq}
4
+ ${Hq}
5
5
  `.trimStart(),U(z,J.endsWith(`
6
6
  `)?J:`${J}
7
- `);let V=$(q,"CLAUDE.md"),Y="";try{Y=x(V,"utf8")}catch{}if(!/@AGENTS\.md/.test(Y))U(V,`${Y?`${Y.trim()}
7
+ `);let V=$(q,"CLAUDE.md"),Y="";try{Y=H(V,"utf8")}catch{}if(!/@AGENTS\.md/.test(Y))U(V,`${Y?`${Y.trim()}
8
8
 
9
9
  `:""}@AGENTS.md
10
- `)}function Lq(q){let z=$(q,".mcp.json"),J={};try{J=JSON.parse(x(z,"utf8"))}catch{}J.mcpServers=J.mcpServers??{};let Q=J.mcpServers.beacon;if(Q){if(!Q.timeout||Q.timeout<b)return Q.timeout=b,U(z,JSON.stringify(J,null,2)+`
11
- `),{path:z,added:!1,updated:!0};return{path:z,added:!1,updated:!1}}return J.mcpServers.beacon={command:"beacon",args:["mcp"],timeout:b},U(z,JSON.stringify(J,null,2)+`
12
- `),{path:z,added:!0,updated:!1}}function _q(q){let z=$(q,".mcp.json"),J=!1;try{J=!!JSON.parse(x(z,"utf8")).mcpServers?.beacon}catch{}let Q=!1;try{Q=x($(q,"AGENTS.md"),"utf8").includes(C)}catch{}let V=!1;try{V=/@AGENTS\.md/.test(x($(q,"CLAUDE.md"),"utf8"))}catch{}return{repo:q,mcpRegistered:J,agentsMdBlock:Q,claudeMdImport:V,skills:{"beacon-init":w($(q,".claude","skills","beacon-init","SKILL.md")),"beacon-refresh":w($(q,".claude","skills","beacon-refresh","SKILL.md"))},codexSkills:{"beacon-init":w($(q,".agents","skills","beacon-init","SKILL.md")),"beacon-refresh":w($(q,".agents","skills","beacon-refresh","SKILL.md"))}}}function mq(q){let z=[];for(let Z of["beacon-init","beacon-refresh","beacon-db-design"]){let X=$(q,".claude","skills",Z);if(w(X))K(X,{recursive:!0,force:!0}),z.push(Z)}for(let Z of["beacon-init","beacon-refresh"]){let X=$(q,".agents","skills",Z);if(w(X))K(X,{recursive:!0,force:!0}),z.push(`codex:${Z}`)}let J=!1,Q=$(q,".mcp.json");try{let Z=JSON.parse(x(Q,"utf8"));if(Z.mcpServers?.beacon){if(delete Z.mcpServers.beacon,J=!0,Z.mcpServers&&Object.keys(Z.mcpServers).length===0)delete Z.mcpServers;if(Object.keys(Z).length===0)K(Q,{force:!0});else U(Q,JSON.stringify(Z,null,2)+`
13
- `)}}catch{}let V=!1,Y=$(q,"AGENTS.md");try{let Z=x(Y,"utf8"),X=new RegExp(`\\n?${C}[\\s\\S]*?${r}\\n?`);if(X.test(Z)){let t=Z.replace(X,`
10
+ `)}function mq(q){let z=$(q,".mcp.json"),J={};try{J=JSON.parse(H(z,"utf8"))}catch{}J.mcpServers=J.mcpServers??{};let Q=J.mcpServers.beacon;if(Q){if(!Q.timeout||Q.timeout<C)return Q.timeout=C,U(z,JSON.stringify(J,null,2)+`
11
+ `),{path:z,added:!1,updated:!0};return{path:z,added:!1,updated:!1}}return J.mcpServers.beacon={command:"beacon",args:["mcp"],timeout:C},U(z,JSON.stringify(J,null,2)+`
12
+ `),{path:z,added:!0,updated:!1}}function Sq(q){let z=$(q,".mcp.json"),J=!1;try{J=!!JSON.parse(H(z,"utf8")).mcpServers?.beacon}catch{}let Q=!1;try{Q=H($(q,"AGENTS.md"),"utf8").includes(R)}catch{}let V=!1;try{V=/@AGENTS\.md/.test(H($(q,"CLAUDE.md"),"utf8"))}catch{}return{repo:q,mcpRegistered:J,agentsMdBlock:Q,claudeMdImport:V,skills:{"beacon-init":v($(q,".claude","skills","beacon-init","SKILL.md")),"beacon-refresh":v($(q,".claude","skills","beacon-refresh","SKILL.md"))},codexSkills:{"beacon-init":v($(q,".agents","skills","beacon-init","SKILL.md")),"beacon-refresh":v($(q,".agents","skills","beacon-refresh","SKILL.md"))}}}function cq(q){let z=[];for(let Z of["beacon-init","beacon-refresh","beacon-db-design"]){let X=$(q,".claude","skills",Z);if(v(X))f(X,{recursive:!0,force:!0}),z.push(Z)}for(let Z of["beacon-init","beacon-refresh"]){let X=$(q,".agents","skills",Z);if(v(X))f(X,{recursive:!0,force:!0}),z.push(`codex:${Z}`)}let J=!1,Q=$(q,".mcp.json");try{let Z=JSON.parse(H(Q,"utf8"));if(Z.mcpServers?.beacon){if(delete Z.mcpServers.beacon,J=!0,Z.mcpServers&&Object.keys(Z.mcpServers).length===0)delete Z.mcpServers;if(Object.keys(Z).length===0)f(Q,{force:!0});else U(Q,JSON.stringify(Z,null,2)+`
13
+ `)}}catch{}let V=!1,Y=$(q,"AGENTS.md");try{let Z=H(Y,"utf8"),X=new RegExp(`\\n?${R}[\\s\\S]*?${s}\\n?`);if(X.test(Z)){let d=Z.replace(X,`
14
14
  `).replace(/\n{3,}/g,`
15
15
 
16
- `).trimStart();U(Y,t.endsWith(`
17
- `)?t:`${t}
18
- `),V=!0}}catch{}let P=!1,W=$(q,"CLAUDE.md");try{let Z=x(W,"utf8"),X=Z.replace(/^[ \t]*@AGENTS\.md[ \t]*\n?/m,"");if(X!==Z){if(!X.trim())K(W,{force:!0});else U(W,X);P=!0}}catch{}return{skillsRemoved:z,mcpUnregistered:J,agentsBlockRemoved:V,claudeImportRemoved:P}}var d=`---
16
+ `).trimStart();U(Y,d.endsWith(`
17
+ `)?d:`${d}
18
+ `),V=!0}}catch{}let W=!1,P=$(q,"CLAUDE.md");try{let Z=H(P,"utf8"),X=Z.replace(/^[ \t]*@AGENTS\.md[ \t]*\n?/m,"");if(X!==Z){if(!X.trim())f(P,{force:!0});else U(P,X);W=!0}}catch{}return{skillsRemoved:z,mcpUnregistered:J,agentsBlockRemoved:V,claudeImportRemoved:W}}var r=`---
19
19
  name: beacon-init
20
20
  description: Read this repository and map its architecture, schema, and roadmap into Beacon (the local visual planning panel). Use when the user runs /beacon-init, asks to "set up Beacon for this repo", or asks to initialize/bootstrap Beacon's map of this codebase.
21
21
  ---
@@ -109,7 +109,7 @@ The one caveat: if the user manually edited an INIT-source node on the canvas (e
109
109
  If \`beacon_entities\` or \`beacon_init_persist\` isn't available, the Beacon panel isn't running in this repo. Tell the user to run \`beacon\` here first, then re-invoke /beacon-refresh.
110
110
 
111
111
  After the tool returns, report the final counts plus a one-line summary of the diff you surfaced.
112
- `,xq=`---
112
+ `,wq=`---
113
113
  name: beacon-plan
114
114
  description: Present your current plan or approach to the user on Beacon's /plan canvas for review \u2014 instead of asking for approval in prose. Use when the user says "present the plan", "show me the plan", "let me see it / the plan", or whenever you are about to end a turn asking whether to proceed with a plan, design, or approach.
115
115
  ---
@@ -157,7 +157,7 @@ If it returns feedback, revise and call it again.
157
157
  If \`beacon_present_plan\` isn't available, the panel isn't wired here \u2014 fall back to ExitPlanMode
158
158
  with the same \`\`\`beacon block (Claude Code only; Codex has no ExitPlanMode), or tell the user to
159
159
  run \`beacon\` in this repo once.
160
- `,Oq,C="<!-- beacon:workflow:start -->",r="<!-- beacon:workflow:end -->",Uq;var l=j(()=>{Xq();Oq=[{name:"beacon-init",body:()=>d},{name:"beacon-refresh",body:()=>n}];Uq=`${C}
160
+ `,Lq,R="<!-- beacon:workflow:start -->",s="<!-- beacon:workflow:end -->",Hq;var i=B(()=>{Uq();Lq=[{name:"beacon-init",body:()=>r},{name:"beacon-refresh",body:()=>n}];Hq=`${R}
161
161
  ## Beacon \u2014 feature workflow
162
162
 
163
163
  This project uses Beacon (a local planning/visualization panel; run \`beacon\` to open it). When you start work on a FEATURE \u2014 whether referenced via an \`@beacon:feature://\u2026\` mention, an \`@beacon:note://\u2026\` note the user wrote in the Notes panel (treat its checkbox \`- [ ]\` todos as subtasks and order features by their dependencies), or just described in chat \u2014 follow these steps in order:
@@ -225,18 +225,18 @@ Register them all in that single batched call. If a plan added five features, th
225
225
  If the feature added or materially changed a REAL architectural component (a subsystem \u2014 NOT a file), also pass \`architecture: [{ title, domain, role, \u2026 }]\` so the Architecture map stays accurate. It upserts curated components by title; never list files as components. If you found a bug or something worth investigating in a component's code, add \`bugs: [{ note }]\` to its architecture entry \u2014 it renders as a bug flag on the node (attributed to the agent); identical open flags are not duplicated. Only flag what you actually saw in the code.
226
226
 
227
227
  Pull raw planning data anytime with \`beacon_entities\` (features / architecture / tables / endpoints).
228
- ${r}`});import{existsSync as Hq,mkdirSync as i,readFileSync as M,rmSync as pq,writeFileSync as R}from"fs";import{dirname as wq,join as F}from"path";function o(q){try{return JSON.parse(M(q,"utf8"))}catch{return{}}}function vq(q,z){i(wq(q),{recursive:!0}),R(q,JSON.stringify(z,null,2)+`
229
- `)}function I(q,z){let J=o(q);J.hooks=J.hooks??{},J.hooks[z.event]=J.hooks[z.event]??[];let Q=J.hooks[z.event];if(Q.some((Y)=>Y.matcher===z.matcher&&Y.hooks?.some((P)=>P.command===z.command)))return!1;return Q.push({matcher:z.matcher,hooks:[{type:"command",command:z.command}]}),vq(q,J),!0}function y(q,z){return(o(q).hooks?.[z.event]??[]).some((V)=>V.hooks?.some((Y)=>Y.command===z.command))}function D(q,z){let J=o(q),Q=J.hooks?.[z.event];if(!Q)return!1;let V=!1,Y=Q.map((P)=>{let W=P.hooks?.length??0,Z=(P.hooks??[]).filter((X)=>X.command!==z.command);if(Z.length!==W)V=!0;return{...P,hooks:Z}}).filter((P)=>(P.hooks??[]).length>0);if(!V)return!1;if(Y.length)J.hooks[z.event]=Y;else delete J.hooks[z.event];if(J.hooks&&Object.keys(J.hooks).length===0)delete J.hooks;return vq(q,J),!0}function A(q,z,J,Q){let V=`${z}
228
+ ${s}`});import{existsSync as M,mkdirSync as o,readdirSync as aq,readFileSync as g,rmSync as tq,writeFileSync as T}from"fs";import{dirname as xq,join as x}from"path";function vq(){return!!process.env.CLAUDE_PLUGIN_ROOT}function jq(q=process.env.HOME||process.env.USERPROFILE||""){if(!q)return null;let z=x(q,".claude","plugins");if(!M(z))return null;let J=[z];for(let Q=0;Q<3&&J.length;Q++){let V=[];for(let Y of J){let W=x(Y,".claude-plugin","plugin.json");try{if(M(W)&&JSON.parse(g(W,"utf8")).name==="beacon")return Y}catch{}try{for(let P of aq(Y,{withFileTypes:!0}))if(P.isDirectory())V.push(x(Y,P.name))}catch{}}J=V}return null}function Bq(q){return jq(q)!==null}function e(q){try{return JSON.parse(g(q,"utf8"))}catch{return{}}}function gq(q,z){o(xq(q),{recursive:!0}),T(q,JSON.stringify(z,null,2)+`
229
+ `)}function E(q,z){let J=e(q);J.hooks=J.hooks??{},J.hooks[z.event]=J.hooks[z.event]??[];let Q=J.hooks[z.event];if(Q.some((Y)=>Y.matcher===z.matcher&&Y.hooks?.some((W)=>W.command===z.command)))return!1;return Q.push({matcher:z.matcher,hooks:[{type:"command",command:z.command}]}),gq(q,J),!0}function y(q,z){return(e(q).hooks?.[z.event]??[]).some((V)=>V.hooks?.some((Y)=>Y.command===z.command))}function A(q,z){let J=e(q),Q=J.hooks?.[z.event];if(!Q)return!1;let V=!1,Y=Q.map((W)=>{let P=W.hooks?.length??0,Z=(W.hooks??[]).filter((X)=>X.command!==z.command);if(Z.length!==P)V=!0;return{...W,hooks:Z}}).filter((W)=>(W.hooks??[]).length>0);if(!V)return!1;if(Y.length)J.hooks[z.event]=Y;else delete J.hooks[z.event];if(J.hooks&&Object.keys(J.hooks).length===0)delete J.hooks;return gq(q,J),!0}function D(q,z,J,Q){let V=`${z}
230
230
  ${Q.trim()}
231
- ${J}`,Y="";try{Y=M(q,"utf8")}catch{}let P=new RegExp(`${z}[\\s\\S]*?${J}`);Y=P.test(Y)?Y.replace(P,V):Y.trim()?`${Y.trim()}
231
+ ${J}`,Y="";try{Y=g(q,"utf8")}catch{}let W=new RegExp(`${z}[\\s\\S]*?${J}`);Y=W.test(Y)?Y.replace(W,V):Y.trim()?`${Y.trim()}
232
232
 
233
233
  ${V}
234
234
  `:`${V}
235
- `,i(wq(q),{recursive:!0}),R(q,Y.endsWith(`
235
+ `,o(xq(q),{recursive:!0}),T(q,Y.endsWith(`
236
236
  `)?Y:`${Y}
237
- `)}function g(q,z){try{return M(q,"utf8").includes(z)}catch{return!1}}function E(q,z,J){let Q="";try{Q=M(q,"utf8")}catch{return!1}let V=new RegExp(`${z}[\\s\\S]*?${J}\\n?`);if(!V.test(Q))return!1;let Y=Q.replace(V,"").replace(/\n{3,}/g,`
237
+ `)}function N(q,z){try{return g(q,"utf8").includes(z)}catch{return!1}}function O(q,z,J){let Q="";try{Q=g(q,"utf8")}catch{return!1}let V=new RegExp(`${z}[\\s\\S]*?${J}\\n?`);if(!V.test(Q))return!1;let Y=Q.replace(V,"").replace(/\n{3,}/g,`
238
238
 
239
- `).trimStart();return R(q,Y),!0}function O(q,z,J){let Q=F(q,z);i(Q,{recursive:!0});let V=F(Q,"SKILL.md");return R(V,J),V}function B(q,z){return Hq(F(q,z,"SKILL.md"))}function k(q,z){let J=F(q,z);if(!Hq(J))return!1;return pq(J,{recursive:!0,force:!0}),!0}var H,T=`## Beacon (visual planning panel)
239
+ `).trimStart();return T(q,Y),!0}function k(q,z,J){let Q=x(q,z);o(Q,{recursive:!0});let V=x(Q,"SKILL.md");return T(V,J),V}function G(q,z){return M(x(q,z,"SKILL.md"))}function h(q,z){let J=x(q,z);if(!M(J))return!1;return tq(J,{recursive:!0,force:!0}),!0}var w,I=`## Beacon (visual planning panel)
240
240
 
241
241
  This machine has Beacon installed \u2014 a local visual planning surface for the terminal-side
242
242
  agent. Beacon proposes feature plans (roadmap features + DB schema + endpoints) via MCP,
@@ -257,17 +257,17 @@ the user reviews on a canvas at /plan, and feedback flows back as the next round
257
257
  Feedback bundles inline annotations on the markdown PLUS any edits the user made directly
258
258
  on the /map and /db boards (added features, attached subtasks, edited columns, new
259
259
  endpoints). Treat board edits as the user's revision intent \u2014 re-propose matching them
260
- verbatim. Do NOT implement until the tool returns approval.`;var e=j(()=>{H=["beacon-init","beacon-refresh","beacon-plan"]});import{mkdirSync as Sq,renameSync as aq,rmSync as cq,writeFileSync as tq}from"fs";import{dirname as dq}from"path";function h(q,z){Sq(dq(q),{recursive:!0});let J=`${q}.tmp`;try{tq(J,z),aq(J,q)}catch(Q){throw cq(J,{force:!0}),Q}}function Cz(q,z,J=!1){h(q,JSON.stringify(z,null,J?2:void 0))}var jq=()=>{};var fq={};Wq(fq,{setupCodexAssets:()=>lq,removeCodexMcp:()=>Kq,removeCodexArtifacts:()=>oq,hasCodexMcp:()=>Qq,ensureCodexMcp:()=>bq,codexMcpProblem:()=>sq,codexDetected:()=>uq,auditCodex:()=>iq,CODEX_HOOKS:()=>S});import{readFileSync as p}from"fs";import{homedir as nq}from"os";import{join as G}from"path";function gq(){return process.env.HOME||process.env.USERPROFILE||nq()}function uq(){if(process.env.BEACON_CODEX==="1")return!0;if(process.env.BEACON_CODEX==="0")return!1;if(qq===void 0)qq=Bun.which("codex")!==null;return qq}function N(q){try{return Bun.TOML.parse(q)}catch{return null}}function Qq(){try{return Boolean(N(p(v(),"utf8"))?.mcp_servers?.beacon)}catch{return!1}}function sq(){let q="";try{q=p(v(),"utf8")}catch{return null}let z=N(q);if(!z)return`~/.codex/config.toml does not parse \u2014 ${u}`;if(z.mcp_servers?.beacon)return null;if(/^\s*mcp_servers\s*=/m.test(q))return`mcp_servers is an inline table \u2014 ${u}`;return null}function bq(){let q="",z=!1;try{q=p(v(),"utf8"),z=!0}catch{}if(z){let Y=N(q);if(!Y)return{added:!1,error:`~/.codex/config.toml does not parse \u2014 ${u}`};if(Y.mcp_servers?.beacon)return{added:!1};if(/^\s*mcp_servers\s*=/m.test(q))return{added:!1,error:`mcp_servers is an inline table \u2014 ${u}`}}let J=!q?"":q.endsWith(`
260
+ verbatim. Do NOT implement until the tool returns approval.`;var qq=B(()=>{w=["beacon-init","beacon-refresh","beacon-plan"]});import{mkdirSync as dq,renameSync as rq,rmSync as nq,writeFileSync as sq}from"fs";import{dirname as lq}from"path";function L(q,z){dq(lq(q),{recursive:!0});let J=`${q}.tmp`;try{sq(J,z),rq(J,q)}catch(Q){throw nq(J,{force:!0}),Q}}function Iz(q,z,J=!1){L(q,JSON.stringify(z,null,J?2:void 0))}var Nq=()=>{};var Rq={};Xq(Rq,{setupCodexAssets:()=>qz,removeCodexMcp:()=>Fq,removeCodexArtifacts:()=>Jz,hasCodexMcp:()=>Vq,ensureCodexMcp:()=>fq,codexMcpProblem:()=>eq,codexDetected:()=>uq,auditCodex:()=>zz,CODEX_HOOKS:()=>c});import{readFileSync as S}from"fs";import{homedir as iq}from"os";import{join as K}from"path";function Gq(){return process.env.HOME||process.env.USERPROFILE||iq()}function uq(){if(process.env.BEACON_CODEX==="1")return!0;if(process.env.BEACON_CODEX==="0")return!1;if(zq===void 0)zq=Bun.which("codex")!==null;return zq}function u(q){try{return Bun.TOML.parse(q)}catch{return null}}function Vq(){try{return Boolean(u(S(j(),"utf8"))?.mcp_servers?.beacon)}catch{return!1}}function eq(){let q="";try{q=S(j(),"utf8")}catch{return null}let z=u(q);if(!z)return`~/.codex/config.toml does not parse \u2014 ${b}`;if(z.mcp_servers?.beacon)return null;if(/^\s*mcp_servers\s*=/m.test(q))return`mcp_servers is an inline table \u2014 ${b}`;return null}function fq(){let q="",z=!1;try{q=S(j(),"utf8"),z=!0}catch{}if(z){let Y=u(q);if(!Y)return{added:!1,error:`~/.codex/config.toml does not parse \u2014 ${b}`};if(Y.mcp_servers?.beacon)return{added:!1};if(/^\s*mcp_servers\s*=/m.test(q))return{added:!1,error:`mcp_servers is an inline table \u2014 ${b}`}}let J=!q?"":q.endsWith(`
261
261
  `)?`
262
262
  `:`
263
263
 
264
- `,Q=q+J+rq;if(N(Q)?.mcp_servers?.beacon?.command!=="beacon")return{added:!1,error:`could not safely append [mcp_servers.beacon] \u2014 ${u}`};return h(v(),Q),{added:!0}}function Kq(){let q="";try{q=p(v(),"utf8")}catch{return{removed:!1}}let z=q.split(`
265
- `),J=z.indexOf(Nq);if(J===-1)return{removed:!1,skipped:Qq()};let Q=z.indexOf(Gq,J);if(Q===-1)return{removed:!1,skipped:!0};z.splice(J,Q-J+1);let V=z.join(`
264
+ `,Q=q+J+oq;if(u(Q)?.mcp_servers?.beacon?.command!=="beacon")return{added:!1,error:`could not safely append [mcp_servers.beacon] \u2014 ${b}`};return L(j(),Q),{added:!0}}function Fq(){let q="";try{q=S(j(),"utf8")}catch{return{removed:!1}}let z=q.split(`
265
+ `),J=z.indexOf(Kq);if(J===-1)return{removed:!1,skipped:Vq()};let Q=z.indexOf(Cq,J);if(Q===-1)return{removed:!1,skipped:!0};z.splice(J,Q-J+1);let V=z.join(`
266
266
  `).replace(/\n{3,}/g,`
267
267
 
268
- `).replace(/^\n+/,"");if(N(V)===null)return{removed:!1,skipped:!0};return h(v(),V),{removed:!0}}async function lq(){let{INIT_SKILL:q,REFRESH_SKILL:z,PLAN_SKILL:J}=await Promise.resolve().then(() => (l(),s)),Q={"beacon-init":q,"beacon-refresh":z,"beacon-plan":J},V=[];for(let Z of H){if(!B(_(),Z))V.push(Z);O(_(),Z,Q[Z])}let Y=0;for(let Z of S)if(I(Jq(),{event:Z.event,matcher:Z.matcher,command:Z.command}))Y++;let P=g(L(),m);A(L(),m,Bq,T);let W=bq();return{skillsAdded:V,hooksAdded:Y,agentsMdBlockTouched:!P,mcp:W}}function iq(){let q={};for(let J of H)q[J]=B(_(),J);let z={};for(let J of S)z[J.event]=y(Jq(),{event:J.event,command:J.command});return{detected:uq(),skills:q,hooks:z,agentsMdBlock:g(L(),m),mcp:Qq()}}function oq(){let q=[];for(let V of H)if(k(_(),V))q.push(V);let z=0;for(let V of S)if(D(Jq(),{event:V.event,command:V.command}))z++;let J=E(L(),m,Bq),Q=Kq();return{skillsRemoved:q,hooksRemoved:z,agentsMdBlockRemoved:J,mcpRemoved:Q.removed,mcpSkipped:Q.skipped}}var zq=()=>G(gq(),".codex"),Jq=()=>G(zq(),"hooks.json"),v=()=>G(zq(),"config.toml"),L=()=>G(zq(),"AGENTS.md"),_=()=>G(gq(),".agents","skills"),m="<!-- beacon:global:start -->",Bq="<!-- beacon:global:end -->",S,qq,Nq="# beacon:start (managed by Beacon \u2014 `beacon uninstall` removes this block)",Gq="# beacon:end",rq,u="add it manually: codex mcp add beacon -- beacon mcp";var Cq=j(()=>{e();jq();S=[{event:"PostToolUse",matcher:"apply_patch",command:"beacon hook",description:"Report file edits to Beacon's active feature so the map stays fresh."},{event:"UserPromptSubmit",matcher:"*",command:"beacon prompt",description:"On feature-y prompts in a Beacon-wired repo, remind the agent to run the context\u2192propose\u2192describe loop (no-op otherwise)."},{event:"Stop",matcher:"*",command:"beacon stop-hook",description:"When the agent ends a turn asking for plan approval in prose, nudge it to present the plan on Beacon's /plan canvas."}];rq=`${Nq}
268
+ `).replace(/^\n+/,"");if(u(V)===null)return{removed:!1,skipped:!0};return L(j(),V),{removed:!0}}async function qz(){let{INIT_SKILL:q,REFRESH_SKILL:z,PLAN_SKILL:J}=await Promise.resolve().then(() => (i(),l)),Q={"beacon-init":q,"beacon-refresh":z,"beacon-plan":J},V=[];for(let Z of w){if(!G(p(),Z))V.push(Z);k(p(),Z,Q[Z])}let Y=0;for(let Z of c)if(E(Qq(),{event:Z.event,matcher:Z.matcher,command:Z.command}))Y++;let W=N(_(),m);D(_(),m,bq,I);let P=fq();return{skillsAdded:V,hooksAdded:Y,agentsMdBlockTouched:!W,mcp:P}}function zz(){let q={};for(let J of w)q[J]=G(p(),J);let z={};for(let J of c)z[J.event]=y(Qq(),{event:J.event,command:J.command});return{detected:uq(),skills:q,hooks:z,agentsMdBlock:N(_(),m),mcp:Vq()}}function Jz(){let q=[];for(let V of w)if(h(p(),V))q.push(V);let z=0;for(let V of c)if(A(Qq(),{event:V.event,command:V.command}))z++;let J=O(_(),m,bq),Q=Fq();return{skillsRemoved:q,hooksRemoved:z,agentsMdBlockRemoved:J,mcpRemoved:Q.removed,mcpSkipped:Q.skipped}}var Jq=()=>K(Gq(),".codex"),Qq=()=>K(Jq(),"hooks.json"),j=()=>K(Jq(),"config.toml"),_=()=>K(Jq(),"AGENTS.md"),p=()=>K(Gq(),".agents","skills"),m="<!-- beacon:global:start -->",bq="<!-- beacon:global:end -->",c,zq,Kq="# beacon:start (managed by Beacon \u2014 `beacon uninstall` removes this block)",Cq="# beacon:end",oq,b="add it manually: codex mcp add beacon -- beacon mcp";var Mq=B(()=>{qq();Nq();c=[{event:"PostToolUse",matcher:"apply_patch",command:"beacon hook",description:"Report file edits to Beacon's active feature so the map stays fresh."},{event:"UserPromptSubmit",matcher:"*",command:"beacon prompt",description:"On feature-y prompts in a Beacon-wired repo, remind the agent to run the context\u2192propose\u2192describe loop (no-op otherwise)."},{event:"Stop",matcher:"*",command:"beacon stop-hook",description:"When the agent ends a turn asking for plan approval in prose, nudge it to present the plan on Beacon's /plan canvas."}];oq=`${Kq}
269
269
  [mcp_servers.beacon]
270
270
  command = "beacon"
271
271
  args = ["mcp"]
272
- ${Gq}
273
- `});e();import{existsSync as eq}from"fs";import{homedir as qz}from"os";import{join as a}from"path";function zz(){return process.env.HOME||process.env.USERPROFILE||qz()}var c=()=>a(zz(),".claude"),Vq=()=>a(c(),"skills"),Yq=()=>a(c(),"settings.json"),Zq=()=>a(c(),"CLAUDE.md"),$q="<!-- beacon:global:start -->",Fq="<!-- beacon:global:end -->";var Jz=T,Pq=[{event:"PreToolUse",matcher:"Edit|Write|MultiEdit",command:"beacon guard",description:"Gate edits against the active plan's scope contract (when the scope-guard flag is on): in-scope \u2192 allow, off-scope \u2192 ask the user to authorize. No-op + fail-open otherwise."},{event:"PostToolUse",matcher:"Edit|Write|MultiEdit",command:"beacon hook",description:"Report file edits to Beacon's active feature so the map stays fresh."},{event:"PermissionRequest",matcher:"ExitPlanMode",command:"beacon plan",description:"Pipe the agent's plan markdown into Beacon's /plan canvas for review."},{event:"UserPromptSubmit",matcher:"*",command:"beacon prompt",description:"On feature-y prompts in a Beacon-wired repo, remind the agent to run the context\u2192propose\u2192describe loop (no-op otherwise)."},{event:"Stop",matcher:"*",command:"beacon stop-hook",description:"When the agent ends a turn asking for plan approval in prose (instead of presenting it), nudge it to present the plan on Beacon's /plan canvas. Bounded by stop_hook_active \u2014 at most one nudge."}];function Qz(q,z){return O(Vq(),q,z)}function Mq(q){return B(Vq(),q)}function Vz(q){return k(Vq(),q)}function Yz(q){return I(Yq(),q)}function Zz(q){return y(Yq(),q)}function $z(q){return D(Yq(),q)}function Pz(q){A(Zq(),$q,Fq,q)}function Rq(){return g(Zq(),$q)}function Wz(){return E(Zq(),$q,Fq)}function kz(){let q={};for(let J of H)q[J]=Mq(J);let z={};for(let J of Pq)z[J.event]=Zz({event:J.event,command:J.command});return{homeExists:eq(c()),skills:q,hooks:z,claudeMdBlock:Rq()}}async function Xz(){let{INIT_SKILL:q,REFRESH_SKILL:z,PLAN_SKILL:J}=await Promise.resolve().then(() => (l(),s)),Q={"beacon-init":q,"beacon-refresh":z,"beacon-plan":J},V=[];for(let W of H){if(!Mq(W))V.push(W);Qz(W,Q[W])}let Y=0;for(let W of Pq)if(Yz({event:W.event,matcher:W.matcher,command:W.command}))Y++;let P=Rq();return Pz(Jz),{skillsAdded:V,hooksAdded:Y,claudeMdBlockTouched:!P}}async function hz(){let q;try{q={ok:!0,...await Xz()}}catch(z){q={ok:!1,error:z instanceof Error?z.message:String(z),skillsAdded:[],hooksAdded:0,claudeMdBlockTouched:!1}}try{let z=await Promise.resolve().then(() => (Cq(),fq));if(z.codexDetected())q.codex={ok:!0,...await z.setupCodexAssets()}}catch(z){q.codex={ok:!1,error:z instanceof Error?z.message:String(z),skillsAdded:[],hooksAdded:0,agentsMdBlockTouched:!1,mcp:{added:!1}}}return q}function Lz(){let q=[];for(let Q of H)if(Vz(Q))q.push(Q);let z=0;for(let Q of Pq)if($z(Q))z++;let J=Wz();return{skillsRemoved:q,hooksRemoved:z,claudeMdBlockRemoved:J}}export{Xz as setupGlobalAssets,hz as selfHealGlobal,Vz as removeGlobalSkill,$z as removeGlobalHook,Wz as removeGlobalClaudeMdBlock,Lz as removeBeaconArtifacts,Mq as isGlobalSkillInstalled,Qz as installGlobalSkill,Zz as hasGlobalHook,Rq as hasGlobalClaudeMdBlock,Yz as ensureGlobalHook,Pz as ensureGlobalClaudeMdBlock,kz as auditGlobal,H as GLOBAL_SKILLS,Pq as GLOBAL_HOOKS,Jz as GLOBAL_CLAUDE_MD_BLOCK};
272
+ ${Cq}
273
+ `});qq();import{existsSync as Qz}from"fs";import{homedir as Vz}from"os";import{join as a}from"path";function Yz(){return process.env.HOME||process.env.USERPROFILE||Vz()}var t=()=>a(Yz(),".claude"),Yq=()=>a(t(),"skills"),Zq=()=>a(t(),"settings.json"),$q=()=>a(t(),"CLAUDE.md"),Wq="<!-- beacon:global:start -->",Tq="<!-- beacon:global:end -->";var Zz=I,Pq=[{event:"PreToolUse",matcher:"Edit|Write|MultiEdit",command:"beacon guard",description:"Gate edits against the active plan's scope contract (when the scope-guard flag is on): in-scope \u2192 allow, off-scope \u2192 ask the user to authorize. No-op + fail-open otherwise."},{event:"PostToolUse",matcher:"Edit|Write|MultiEdit",command:"beacon hook",description:"Report file edits to Beacon's active feature so the map stays fresh."},{event:"PermissionRequest",matcher:"ExitPlanMode",command:"beacon plan",description:"Pipe the agent's plan markdown into Beacon's /plan canvas for review."},{event:"UserPromptSubmit",matcher:"*",command:"beacon prompt",description:"On feature-y prompts in a Beacon-wired repo, remind the agent to run the context\u2192propose\u2192describe loop (no-op otherwise)."},{event:"Stop",matcher:"*",command:"beacon stop-hook",description:"When the agent ends a turn asking for plan approval in prose (instead of presenting it), nudge it to present the plan on Beacon's /plan canvas. Bounded by stop_hook_active \u2014 at most one nudge."}];function $z(q,z){return k(Yq(),q,z)}function Iq(q){return G(Yq(),q)}function Wz(q){return h(Yq(),q)}function Pz(q){return E(Zq(),q)}function Xz(q){return y(Zq(),q)}function Uz(q){return A(Zq(),q)}function Hz(q){D($q(),Wq,Tq,q)}function Eq(){return N($q(),Wq)}function wz(){return O($q(),Wq,Tq)}function mz(){let q={};for(let J of w)q[J]=Iq(J);let z={};for(let J of Pq)z[J.event]=Xz({event:J.event,command:J.command});return{homeExists:Qz(t()),skills:q,hooks:z,claudeMdBlock:Eq()}}async function xz(){let{INIT_SKILL:q,REFRESH_SKILL:z,PLAN_SKILL:J}=await Promise.resolve().then(() => (i(),l)),Q={"beacon-init":q,"beacon-refresh":z,"beacon-plan":J},V=[];for(let P of w){if(!Iq(P))V.push(P);$z(P,Q[P])}let Y=0;for(let P of Pq)if(Pz({event:P.event,matcher:P.matcher,command:P.command}))Y++;let W=Eq();return Hz(Zz),{skillsAdded:V,hooksAdded:Y,claudeMdBlockTouched:!W}}async function Sz(){if(vq())return{ok:!0,skipped:"plugin",skillsAdded:[],hooksAdded:0,claudeMdBlockTouched:!1};let q;if(Bq()){try{vz()}catch{}q={ok:!0,skipped:"plugin-present",skillsAdded:[],hooksAdded:0,claudeMdBlockTouched:!1}}else try{q={ok:!0,...await xz()}}catch(z){q={ok:!1,error:z instanceof Error?z.message:String(z),skillsAdded:[],hooksAdded:0,claudeMdBlockTouched:!1}}try{let z=await Promise.resolve().then(() => (Mq(),Rq));if(z.codexDetected())q.codex={ok:!0,...await z.setupCodexAssets()}}catch(z){q.codex={ok:!1,error:z instanceof Error?z.message:String(z),skillsAdded:[],hooksAdded:0,agentsMdBlockTouched:!1,mcp:{added:!1}}}return q}function vz(){let q=[];for(let Q of w)if(Wz(Q))q.push(Q);let z=0;for(let Q of Pq)if(Uz(Q))z++;let J=wz();return{skillsRemoved:q,hooksRemoved:z,claudeMdBlockRemoved:J}}export{xz as setupGlobalAssets,Sz as selfHealGlobal,Wz as removeGlobalSkill,Uz as removeGlobalHook,wz as removeGlobalClaudeMdBlock,vz as removeBeaconArtifacts,vq as isPluginManaged,Iq as isGlobalSkillInstalled,$z as installGlobalSkill,Xz as hasGlobalHook,Eq as hasGlobalClaudeMdBlock,jq as findBeaconPluginDir,Pz as ensureGlobalHook,Hz as ensureGlobalClaudeMdBlock,Bq as beaconPluginInstalled,mz as auditGlobal,w as GLOBAL_SKILLS,Pq as GLOBAL_HOOKS,Zz as GLOBAL_CLAUDE_MD_BLOCK};
package/package.json CHANGED
@@ -1,8 +1,17 @@
1
1
  {
2
2
  "name": "trybeacon",
3
- "version": "0.1.63",
3
+ "version": "0.1.64",
4
4
  "description": "The visual planning surface for the coding agent in your terminal.",
5
5
  "homepage": "https://trybeacon.sh",
6
+ "license": "Apache-2.0",
7
+ "author": "Wenzo (https://trybeacon.sh)",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/wenzorithelly/beacon.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/wenzorithelly/beacon/issues"
14
+ },
6
15
  "bin": {
7
16
  "beacon": "dist/bin/beacon.js"
8
17
  },
@@ -11,13 +20,17 @@
11
20
  ".next",
12
21
  "public",
13
22
  "drizzle",
14
- "next.config.ts"
23
+ "next.config.ts",
24
+ "bun.lock",
25
+ ".claude-plugin/plugin.json",
26
+ "plugin"
15
27
  ],
16
28
  "scripts": {
17
29
  "dev": "next dev",
18
30
  "build": "next build",
19
31
  "build:cli": "bun scripts/build-cli.ts",
20
- "build:release": "rm -rf .next && next build --webpack && rm -rf .next/cache .next/dev && find .next -name '*.js.map' -delete && bun run build:cli",
32
+ "build:plugin": "bun scripts/build-plugin.ts",
33
+ "build:release": "rm -rf .next && next build --webpack && rm -rf .next/cache .next/dev && find .next -name '*.js.map' -delete && bun run build:cli && bun run build:plugin",
21
34
  "prepublishOnly": "bun run build:release",
22
35
  "start": "next start",
23
36
  "lint": "eslint",
@@ -0,0 +1,11 @@
1
+ ---
2
+ name: beacon
3
+ description: Open the Beacon visual planning panel for this repo in your browser.
4
+ ---
5
+
6
+ Open Beacon's panel for the current repo. Run this in the repo's shell — it registers the repo,
7
+ makes sure the shared Beacon daemon is running, and opens (or reuses) the browser tab on /map:
8
+
9
+ ```bash
10
+ bun "${CLAUDE_PLUGIN_ROOT}/dist/bin/boot.js"
11
+ ```
@@ -0,0 +1,70 @@
1
+ {
2
+ "hooks": {
3
+ "PreToolUse": [
4
+ {
5
+ "matcher": "Edit|Write|MultiEdit",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "bun ${CLAUDE_PLUGIN_ROOT}/dist/bin/boot.js guard"
10
+ }
11
+ ]
12
+ }
13
+ ],
14
+ "PostToolUse": [
15
+ {
16
+ "matcher": "Edit|Write|MultiEdit",
17
+ "hooks": [
18
+ {
19
+ "type": "command",
20
+ "command": "bun ${CLAUDE_PLUGIN_ROOT}/dist/bin/boot.js hook"
21
+ }
22
+ ]
23
+ }
24
+ ],
25
+ "PermissionRequest": [
26
+ {
27
+ "matcher": "ExitPlanMode",
28
+ "hooks": [
29
+ {
30
+ "type": "command",
31
+ "command": "bun ${CLAUDE_PLUGIN_ROOT}/dist/bin/boot.js plan"
32
+ }
33
+ ]
34
+ }
35
+ ],
36
+ "UserPromptSubmit": [
37
+ {
38
+ "matcher": "*",
39
+ "hooks": [
40
+ {
41
+ "type": "command",
42
+ "command": "bun ${CLAUDE_PLUGIN_ROOT}/dist/bin/boot.js prompt"
43
+ }
44
+ ]
45
+ }
46
+ ],
47
+ "Stop": [
48
+ {
49
+ "matcher": "*",
50
+ "hooks": [
51
+ {
52
+ "type": "command",
53
+ "command": "bun ${CLAUDE_PLUGIN_ROOT}/dist/bin/boot.js stop-hook"
54
+ }
55
+ ]
56
+ }
57
+ ],
58
+ "SessionStart": [
59
+ {
60
+ "matcher": "*",
61
+ "hooks": [
62
+ {
63
+ "type": "command",
64
+ "command": "bun ${CLAUDE_PLUGIN_ROOT}/dist/bin/boot.js ensure"
65
+ }
66
+ ]
67
+ }
68
+ ]
69
+ }
70
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "beacon": {
3
+ "command": "bun",
4
+ "args": [
5
+ "${CLAUDE_PLUGIN_ROOT}/dist/bin/boot.js",
6
+ "mcp"
7
+ ],
8
+ "timeout": 3600000
9
+ }
10
+ }
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: beacon-init
3
+ description: Read this repository and map its architecture, schema, and roadmap into Beacon (the local visual planning panel). Use when the user runs /beacon-init, asks to "set up Beacon for this repo", or asks to initialize/bootstrap Beacon's map of this codebase.
4
+ ---
5
+
6
+ # Map this repo into Beacon (/beacon-init)
7
+
8
+ The user already has Beacon running. You're going to map this repository's architecture into it — what used to be `beacon init`. **You** do the analysis (your session already has the codebase context); Beacon just persists what you send.
9
+
10
+ ## What you produce
11
+
12
+ A single `beacon_init_persist` MCP tool call with:
13
+
14
+ - **hasFrontend**: `true` or `false` — does this repo have a frontend surface (UI code)? You just read the repo, so you know. Set it explicitly; it gates the frontend/backend `layer` distinction on the boards (a pure-backend repo never shows it).
15
+ - **classificationRoots** (optional): the top-level directories whose immediate children are the meaningful groups on the Files canvas — e.g. `["frontend", "backend/app"]`. The canvas groups files ONE level below each root (so `frontend` → `frontend/components`, `frontend/app`, …). Pick the dir sitting directly ABOVE the real package dirs — use `frontend/src` if there's a `src/` wrapper. List both sides of a monorepo so neither collapses into one flat blob. Not every dir — just where grouping should START. Omit it for a simple single-root repo; the canvas falls back to automatic grouping.
16
+ - **components**: 8–25 main building blocks of this codebase. NOT every file. Group them by `domain` (short UPPERCASE: AUTH, API, DATA, UI, JOBS, INFRA, BILLING, SEARCH, …). For each: a one-line technical `role`, a one-sentence plain-language `plain`, the few `files` that implement it (repo-relative), `depends` listing other component titles it relies on — and, when `hasFrontend` is true, `layer` (`"frontend" | "backend" | "fullstack"`). Use the dependency graph you can see in the source — files that import each other heavily usually belong together. If you spot a bug or something worth investigating while reading a component's code, add `bugs: [{ note }]` to that component — it renders as a bug flag on the node (attributed to the agent). Only flag what you actually saw in the code; don't speculate.
17
+ - **roadmap**: 3–6 BROAD strategic directions. Big-picture themes only — "Harden auth & security", "Add observability", "Scale the data layer", "Pay down test-coverage debt". NOT detailed tasks. NOT file-level. Each gets a short title and one-line `why`. If one of them is a concrete BUG to fix (something broken you saw in the code), add `kind: "BUG"` so it renders as a typed bug card. When `hasFrontend` is true, give each a `layer` too (`"frontend" | "backend" | "fullstack"`).
18
+ - **overview**: one paragraph describing what this project is and its stack. This lands in AGENTS.md as the project intro.
19
+ - **conventions**: 3–8 concrete rules a contributor MUST follow — build/test commands, where code goes, patterns, things easy to get wrong. Infer from actual files, not assumptions.
20
+ - **snapshot** (optional but encouraged): `{ tables, relations, endpoints }` for the existing database. If the project uses Prisma, read `prisma/schema.prisma`. If SQLAlchemy, read the model files. If Django, read `models.py`. If you find no obvious schema source, skip the snapshot — don't fabricate.
21
+
22
+ ## How to do it
23
+
24
+ 1. **Survey**. Use `LS` / `Glob` to see the top-level structure. Read `README.md` and the manifest (`package.json` / `pyproject.toml` / `go.mod` / `Cargo.toml` / `pom.xml`).
25
+ 2. **Sample the source.** Read 15–30 representative files — one per cluster you can identify. Don't read everything; pick by name (route files, model files, main entrypoints, key services). The goal is to identify boundaries, not memorize every line.
26
+ 3. **Identify the schema** if any. `prisma/schema.prisma` → translate each model into a `tables` entry. `alembic`/SQLAlchemy → read the latest models. Django → read `models.py`. Skip the snapshot if the source-of-truth isn't obvious.
27
+ 4. **Identify endpoints** if any. Look for routes — Next.js `app/api/*` files, FastAPI `@router.*` / `@app.*`, Express `app.get`/etc. For each endpoint try to fill `uses: [{ table, access }]` so the canvas can draw which endpoint touches which table.
28
+ 5. **Call `beacon_init_persist`** ONCE with the whole analysis. It replaces any prior init-derived map (idempotent) and regenerates `AGENTS.md`.
29
+
30
+ ## What you should NOT do
31
+
32
+ - Don't propose detailed tasks in `roadmap` — that's what `beacon_propose_plan` is for. Init roadmap is strategic only.
33
+ - Don't list every file as a `component`. Aim for ~15. If you have 40, you're listing files, not components.
34
+ - Don't fabricate tables/endpoints. If you can't find the schema source, omit `snapshot`.
35
+ - Don't ask the user to confirm before persisting. The user invoked /beacon-init — that's the confirmation.
36
+
37
+ ## If `beacon_init_persist` is NOT in your tools (or the call can't reach the daemon)
38
+
39
+ That happens when this repo was never opened with `beacon`: there's no `.mcp.json`, so the Beacon MCP server isn't in this session — and MCP tools can't be added mid-session. (It also covers a wired repo whose daemon is down, so the tool call errors.) **Do NOT stop and tell the user to run `beacon` first.** /beacon-init bootstraps itself: write the EXACT analysis object you'd have passed to `beacon_init_persist` to a temp JSON file, then persist it through the CLI:
40
+
41
+ ```bash
42
+ beacon init-persist /tmp/beacon-init.json # or: beacon init-persist < /tmp/beacon-init.json
43
+ ```
44
+
45
+ That one command wires the repo (writes `.mcp.json` + skills so your NEXT session gets the `beacon_*` tools natively, heals the global install), starts the Beacon daemon if it isn't running, registers + provisions this workspace, and POSTs your analysis to the same `/api/init` endpoint the MCP tool uses — so init completes in THIS session. Read the counts it prints and report them.
46
+
47
+ After the tool (or `beacon init-persist`) returns, tell the user the counts (components / roadmap / tables / endpoints) and point them at the running Beacon panel.
@@ -0,0 +1,48 @@
1
+ ---
2
+ name: beacon-plan
3
+ description: Present your current plan or approach to the user on Beacon's /plan canvas for review — instead of asking for approval in prose. Use when the user says "present the plan", "show me the plan", "let me see it / the plan", or whenever you are about to end a turn asking whether to proceed with a plan, design, or approach.
4
+ ---
5
+
6
+ # Present a plan on Beacon (/beacon-plan)
7
+
8
+ Beacon reviews plans on a canvas at /plan — never as a wall of text in the terminal. So do NOT
9
+ end a turn with "here's my plan… should I proceed?" in prose. Present it through Beacon and let the
10
+ tool BLOCK until the user decides.
11
+
12
+ ## How to present
13
+
14
+ Call the **`beacon_present_plan`** MCP tool with your plan as markdown:
15
+
16
+ - `description`: a one-line summary shown in the review header.
17
+ - `markdown`: the full plan as markdown (headings, lists, code).
18
+ - If the plan proposes DB tables / relations / endpoints or roadmap features, embed ONE fenced
19
+ ```beacon JSON block in the markdown — the same shapes `beacon_propose_plan` accepts:
20
+
21
+ ```beacon
22
+ { "tables": [...], "relations": [...], "endpoints": [...], "features": [...] }
23
+ ```
24
+
25
+ Beacon extracts that block deterministically, strips it from the prose, and renders an editable
26
+ board on /plan. The board is built ONLY from the block — prose is never parsed — so mirror EVERY
27
+ table/endpoint/feature you mention in the prose into the block, or that board will be empty.
28
+
29
+ - **Declare your scope.** List the repo-relative files this plan will touch in a top-level
30
+ `"contract"` array in the block (or the `contract` arg of `beacon_propose_plan`). When the user
31
+ has the plan scope-guard enabled, those files are frozen at approval and you're held to them while
32
+ implementing — editing an undeclared file pauses for the user's authorization (which then adds it
33
+ to the contract). Harmless when the guard is off. Declare the files you genuinely expect to edit.
34
+
35
+ `beacon_present_plan` opens /plan and BLOCKS until the user clicks Approve / Discard / submits
36
+ feedback, then returns their verdict. Implement code or migrations ONLY after it returns approval.
37
+ If it returns feedback, revise and call it again.
38
+
39
+ ## Which tool
40
+
41
+ - **Pure schema/feature plan** (tables + endpoints + roadmap features, little prose) → you may use
42
+ `beacon_propose_plan` with the structured fields instead; it's the same review loop.
43
+ - **Anything else** (a code-change plan, a mixed plan, a "how should I approach X") → use
44
+ `beacon_present_plan` with markdown so the full reasoning shows on /plan.
45
+
46
+ If `beacon_present_plan` isn't available, the panel isn't wired here — fall back to ExitPlanMode
47
+ with the same ```beacon block (Claude Code only; Codex has no ExitPlanMode), or tell the user to
48
+ run `beacon` in this repo once.