@hlix/cli 0.4.2 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -33,21 +33,23 @@ For CI, and for anything else that must not change underneath you, pin the
33
33
  version instead of floating to `latest`:
34
34
 
35
35
  ```bash
36
- npm install --global @hlix/cli@0.4.2
37
- npx @hlix/cli@0.4.2 status --json
36
+ npm install --global @hlix/cli@0.4.3
37
+ npx @hlix/cli@0.4.3 status --json
38
38
  ```
39
39
 
40
40
  ## Authenticate
41
41
 
42
42
  ```bash
43
- hlix auth login --workspace <workspace-id>
43
+ hlix auth login [--workspace <workspace-id>]
44
44
  ```
45
45
 
46
46
  The command reads the API key from a hidden terminal prompt; it never accepts a
47
- credential as a command-line argument. `--workspace` is required. An API key authenticates a **user**; it names no
48
- workspace, so the caller states which one to act in. The key is verified against
49
- a real API call **before** it is written to disk, so a key that does not work is
50
- never stored.
47
+ credential as a command-line argument. `--workspace` is **optional**: an API key
48
+ authenticates a **user** and names no workspace, so the key is used to list the
49
+ workspaces its owner belongs to. With one, it is taken automatically; with
50
+ several, a terminal offers a numbered list and a non-interactive run names the
51
+ ids to pass. The key is verified against a real API call **before** it is
52
+ written to disk, so a key that does not work is never stored.
51
53
 
52
54
  For CI, skip the login step and set the environment directly:
53
55
 
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
- import{q as Ws}from"./index-syeavftx.js";class h extends Error{code;constructor(e,t){super(t);this.name="CliError",this.code=e}}var ca=1,S=(e,t)=>({schemaVersion:1,command:e,data:t}),Ee=(e,t)=>({schemaVersion:1,command:e,error:t});function w(e){return`${JSON.stringify(e,null,2)}
2
+ import{q as Ws}from"./index-syeavftx.js";class h extends Error{code;constructor(e,t){super(t);this.name="CliError",this.code=e}}var pa=1,S=(e,t)=>({schemaVersion:1,command:e,data:t}),Ce=(e,t)=>({schemaVersion:1,command:e,error:t});function w(e){return`${JSON.stringify(e,null,2)}
3
3
  `}function O(e){let t=Math.max(0,...e.map(([n])=>n.length));return e.map(([n,r])=>`${n.padEnd(t)} ${r}`).join(`
4
4
  `)}function X(e,t){let n=e.map((s,o)=>Math.max(s.length,...t.map((i)=>(i[o]??"").length))),r=(s)=>s.map((o,i)=>o.padEnd(n[i])).join(" ").trimEnd();return[r(e),r(n.map((s)=>"-".repeat(s))),...t.map(r)].join(`
5
- `)}import{statSync as Ts}from"node:fs";import{dirname as Os,resolve as As}from"node:path";import{closeSync as Pt,constants as Pe,existsSync as rt,fsyncSync as Jn,lstatSync as Ct,mkdirSync as Ss,openSync as qn,readFileSync as Gn,renameSync as bs,statSync as Wn,unlinkSync as Vn,writeFileSync as ks}from"node:fs";import{homedir as js}from"node:os";import{dirname as Es,join as $t}from"node:path";function de(e=process.env){let t=e.HLIX_CONFIG_HOME??e.XDG_CONFIG_HOME??$t(js(),".config");return $t(t,"hlix","credentials.json")}function Xn(e=process.env){let t=e.HLIX_API_KEY;if(!t&&e.HLIX_SESSION_TOKEN)return{baseUrl:e.HLIX_BASE_URL??"https://server.hlix.ai",apiKey:"",sessionToken:e.HLIX_SESSION_TOKEN,...e.HLIX_WORKSPACE_ID?{organizationId:e.HLIX_WORKSPACE_ID}:{}};if(t)return{baseUrl:e.HLIX_BASE_URL??"https://server.hlix.ai",apiKey:t,...e.HLIX_WORKSPACE_ID?{organizationId:e.HLIX_WORKSPACE_ID}:{}};try{let n=JSON.parse(Gn(de(e),"utf8"));return n.apiKey&&n.baseUrl?n:null}catch{return null}}function Zn(e=process.env){let t=de(e);return rt(t)?t:null}function It(e=process.env){let t=de(e);if(!rt(t))return{path:t,removed:!1,reason:"absent"};let n=Ct(t);if(n.isSymbolicLink()||!n.isFile())throw Error("Refusing to remove a credential path that is not a regular file.");let r=process.getuid?.();if(r!==void 0&&Wn(t).uid!==r)throw Error("Refusing to remove a credential file owned by another user.");let s;try{s=JSON.parse(Gn(t,"utf8"))}catch{s=null}let o=s;if(!o||typeof o.apiKey!=="string"||typeof o.baseUrl!=="string")throw Error(`Refusing to remove ${t}: it is not a credential written by this CLI.`);return Vn(t),{path:t,removed:!0,reason:"removed"}}function Yn(e,t=process.env){let n=de(t),r=Es(n);if(Ss(r,{recursive:!0,mode:448}),Ct(r).isSymbolicLink())throw Error("Refusing to write credentials through a symlinked directory.");if(rt(n)){let i=Ct(n);if(i.isSymbolicLink()||!i.isFile())throw Error("Refusing to replace a credential path that is not a regular file.");let a=process.getuid?.();if(a!==void 0&&Wn(n).uid!==a)throw Error("Refusing to replace a credential file owned by another user.")}let s=$t(r,`.credentials.${process.pid}.${crypto.randomUUID()}.tmp`),o;try{o=qn(s,Pe.O_WRONLY|Pe.O_CREAT|Pe.O_EXCL|Pe.O_NOFOLLOW,384),ks(o,`${JSON.stringify(e,null,2)}
6
- `,"utf8"),Jn(o),Pt(o),o=void 0,bs(s,n);let i=qn(r,Pe.O_RDONLY);try{try{Jn(i)}catch(a){let c=a.code;if(c!=="EINVAL"&&c!=="ENOTSUP")throw a}}finally{Pt(i)}}catch(i){if(o!==void 0)Pt(o);if(rt(s))Vn(s);throw i}return n}import{constants as st,existsSync as ot,lstatSync as er,mkdirSync as Ps,openSync as Cs,closeSync as Qn,fsyncSync as $s,readFileSync as tr,renameSync as Is,unlinkSync as xs,writeFileSync as xt}from"node:fs";import{dirname as Rs,join as Ce,resolve as it}from"node:path";function _s(e){if(!ot(e))return;let t=er(e);if(t.isSymbolicLink()||!t.isFile())throw Error(`Refusing to replace a non-regular Hlix file: ${e}`)}function $e(e,t){let n=Rs(e);if(Ps(n,{recursive:!0,mode:448}),er(n).isSymbolicLink())throw Error(`Refusing to write through a symlinked Hlix directory: ${n}`);_s(e);let r=Ce(n,`.hlix-${process.pid}-${crypto.randomUUID()}.tmp`),s;try{s=Cs(r,st.O_WRONLY|st.O_CREAT|st.O_EXCL|st.O_NOFOLLOW,384),xt(s,`${JSON.stringify(t,null,2)}
7
- `,"utf8"),$s(s),Qn(s),s=void 0,Is(r,e)}catch(o){if(s!==void 0)Qn(s);if(ot(r))xs(r);throw o}}function Ie(e){return Ce(it(e),".hlix","config.json")}function nr(e){return Ce(it(e),".hlix","state.json")}function pe(e){try{let t=JSON.parse(tr(Ie(e),"utf8"));return t.schemaVersion===1&&t.workspaceId&&t.apiUrl?t:null}catch{return null}}function xe(e,t){$e(Ie(e),t);let n=Ce(it(e),".hlix",".gitignore");if(!ot(n))xt(n,`state.json
8
- `,{mode:420,flag:"wx"});let r=Ce(it(e),".hlixignore");if(!ot(r))xt(r,`# Additional project-local paths to exclude from Hlix snapshots.
9
- `,{mode:420,flag:"wx"})}function Re(e,t){$e(nr(e),t)}function at(e){try{let t=JSON.parse(tr(nr(e),"utf8"));return t.schemaVersion===1&&t.revisionId&&t.generation>0?t:null}catch{return null}}var Rt="https://server.hlix.ai";function A(e){let t=As(e);for(;;){let n=pe(t);if(n)return{root:t,config:n};let r=Os(t);if(r===t)return null;t=r}}function sr(e){try{return Ts(e).isDirectory()}catch{return!1}}function ct(e){if(typeof e!=="string")return;let t=e.trim();return t?t:void 0}var rr=(e,t)=>e.replace(/\/+$/,"")===t.replace(/\/+$/,"");function K(e){let{env:t,flags:n,cwd:r}=e,s=A(r),o=Xn(t),i=o?t.HLIX_API_KEY||t.HLIX_SESSION_TOKEN?"env":"file":null,a=i==="file"?o:null,c=ct(n["base-url"]),l=ct(t.HLIX_BASE_URL),p=ct(n.workspace),d=ct(t.HLIX_WORKSPACE_ID),m=c??l??s?.config.apiUrl??a?.baseUrl??Rt,u=c?"flag":l?"env":s?.config.apiUrl?"project":a?.baseUrl?"credential":"default",f=p??d??s?.config.workspaceId??a?.organizationId??null,g=p?"flag":d?"env":s?.config.workspaceId?"project":a?.organizationId?"credential":null;return{baseUrl:m,baseUrlSource:u,workspaceId:f,workspaceSource:g,credential:o,credentialSource:i,credentialPath:de(t),binding:s,conflict:Fs(s,{flagBaseUrl:c,envBaseUrl:l,flagWorkspace:p,envWorkspace:d})}}function Fs(e,t){if(!e)return null;let n=`${e.root} is bound to`,r="Drop the override, or point --cwd at a folder bound to it.";if(t.flagWorkspace&&t.flagWorkspace!==e.config.workspaceId)return`${n} workspace ${e.config.workspaceId}, but --workspace names ${t.flagWorkspace}. ${r}`;if(t.envWorkspace&&t.envWorkspace!==e.config.workspaceId)return`${n} workspace ${e.config.workspaceId}, but HLIX_WORKSPACE_ID names ${t.envWorkspace}. ${r}`;if(t.flagBaseUrl&&!rr(t.flagBaseUrl,e.config.apiUrl))return`${n} ${e.config.apiUrl}, but --base-url names ${t.flagBaseUrl}. ${r}`;if(t.envBaseUrl&&!rr(t.envBaseUrl,e.config.apiUrl))return`${n} ${e.config.apiUrl}, but HLIX_BASE_URL names ${t.envBaseUrl}. ${r}`;return null}import{resolve as Vs}from"node:path";import{parseArgs as Xs}from"node:util";import Ns from"openapi-fetch";function _t(e){return Ns({baseUrl:e.baseUrl,headers:e.headers,fetch:e.fetch})}var _e=(e)=>({kind:"apiKey",apiKey:e});var Tt=(e)=>({kind:"bearer",token:e});function Hs(e){switch(e.kind){case"apiKey":return{"x-api-key":e.apiKey};case"session":return{cookie:e.cookie};case"bearer":return{authorization:`Bearer ${e.token}`}}}function Ls(e){return e?{"X-Organization-Id":e}:{}}function or(e,t){return{...Hs(e),...Ls(t)}}function Us(e){if(typeof e!=="object"||e===null)return null;let{error:t}=e;return typeof t==="string"?t:null}class M extends Error{status;body;requestId;method;url;constructor(e,t){super(e);this.name=new.target.name,this.status=t.status,this.body=t.body,this.requestId=t.requestId??null,this.method=t.method,this.url=t.url}}class Te extends M{issues;constructor(e,t,n){super(e,t);this.issues=n}}class Oe extends M{}class Ae extends M{}class Fe extends M{}class Ne extends M{}class He extends M{}class Le extends M{retryAfter;constructor(e,t,n){super(e,t);this.retryAfter=n}}class Ue extends M{}class Me extends M{}class ue extends Error{method;url;constructor(e,t){super(e,{cause:t.cause});this.name="HlixTransportError",this.method=t.method,this.url=t.url}}function Ms(e){if(typeof e!=="object"||e===null)return null;let t=e;if(t.success!==!1)return null;let n=t.error?.message;if(typeof n!=="string")return null;try{let r=JSON.parse(n);return Array.isArray(r)?r:[]}catch{return[]}}function Bs(e){let t=e.get("retry-after");if(!t)return null;let n=Number(t);return Number.isFinite(n)&&n>=0?n:null}function me(e,t,n){let r={status:e.status,body:t,requestId:e.headers.get("x-request-id"),method:n.method,url:n.url},s=Us(t),o=`${n.method} ${n.url} failed with ${e.status}`,i=Ms(t);if(i)return new Te(`${n.method} ${n.url}: request body failed validation`,r,i);let a=s??o;switch(e.status){case 400:return new Oe(a,r);case 401:return new Ae(a,r);case 403:return new Fe(a,r);case 404:return new Ne(a,r);case 409:return new He(a,r);case 429:return new Le(a,r,Bs(e.headers));case 501:return new Ue(a,r);default:return e.status>=500?new Me(a,r):new M(a,r)}}var ir=new Set(["GET","HEAD","PUT","DELETE","OPTIONS","TRACE"]);function lt(e){return ir.has(e.toUpperCase())}var zs=new Set([429,500,502,503,504]);function Ks(e){return zs.has(e)}var Ot={attempts:3,baseDelayMs:200,maxDelayMs:5000};function At(e,t,n,r=Math.random){if(n!==null)return Math.min(n*1000,t.maxDelayMs);let s=Math.min(t.baseDelayMs*2**e,t.maxDelayMs);return Math.round(r()*s)}function Ft(e){if(!lt(e.method))return!1;if(e.attempt+1>=e.policy.attempts)return!1;return e.status===null||Ks(e.status)}var Ds=(e)=>new Promise((t)=>setTimeout(t,e));function Js(e){let t=e.headers.get("retry-after");if(!t)return null;let n=Number(t);return Number.isFinite(n)&&n>=0?n:null}function ar(e){let{base:t,policy:n}=e,r=e.sleep??Ds,s=e.random??Math.random;return async(o)=>{let i=o.method.toUpperCase(),a=lt(i)?o.clone():null;for(let c=0;;c+=1){let l=c===0?o:a.clone(),p;try{p=await t(l)}catch(d){if(!a||!Ft({method:i,attempt:c,policy:n,status:null}))throw new ue(`${i} ${o.url}: ${d instanceof Error?d.message:String(d)}`,{method:i,url:o.url,cause:d});await r(At(c,n,null,s));continue}if(!Ft({method:i,attempt:c,policy:n,status:p.status}))return p;if(!a)return p;await r(At(c,n,Js(p),s))}}}function b(e,t){if(e.response.ok)return e.data;throw me(e.response,e.error??e.data,t)}var Be=(e)=>typeof e==="string"?e:"";function Nt(e){let t;try{t=JSON.parse(e)}catch{return null}if(typeof t!=="object"||t===null)return null;let n=t;switch(n.type){case"idle":return{type:"idle"};case"done":return{type:"done"};case"active":return typeof n.runId==="string"?{type:"active",runId:n.runId}:{type:"active"};case"on_chat_model_stream":return{type:"on_chat_model_stream",delta:Be(n.delta)};case"reasoning":return{type:"reasoning",delta:Be(n.delta)};case"on_tool_start":return{type:"on_tool_start",name:Be(n.name),input:n.input};case"on_tool_end":return{type:"on_tool_end",name:Be(n.name),output:n.output};case"error":return{type:"error",message:Be(n.message)};default:return null}}var Ht=(e)=>e.type==="done"||e.type==="idle"||e.type==="error";var qs=()=>({event:null,data:[],id:null,retry:null});function cr(e,t,n){switch(t){case"event":e.event=n;return;case"data":e.data.push(n);return;case"id":if(!n.includes("\x00"))e.id=n;return;case"retry":{if(/^\d+$/.test(n))e.retry=Number(n);return}default:return}}function dr(e){let t=e.data.join(`
10
- `),n=e.event,r=e.id;if(e.data=[],e.event=null,t==="")return null;return{event:n,data:t,id:r,retry:e.retry}}function lr(e,t){if(t==="")return dr(e);if(t.startsWith(":"))return null;let n=t.indexOf(":");if(n===-1)return cr(e,t,""),null;let r=t.slice(0,n),s=t.slice(n+1);if(s.startsWith(" "))s=s.slice(1);return cr(e,r,s),null}function Gs(e){let t=[],n=0;for(let r=0;r<e.length;r+=1){let s=e[r];if(s!==`
5
+ `)}import{statSync as _s}from"node:fs";import{dirname as Os,resolve as As}from"node:path";import{closeSync as Pt,constants as $e,existsSync as rt,fsyncSync as qn,lstatSync as Ct,mkdirSync as bs,openSync as Gn,readFileSync as Wn,renameSync as Ss,statSync as Vn,unlinkSync as Xn,writeFileSync as ks}from"node:fs";import{homedir as js}from"node:os";import{dirname as Es,join as $t}from"node:path";function de(e=process.env){let t=e.HLIX_CONFIG_HOME??e.XDG_CONFIG_HOME??$t(js(),".config");return $t(t,"hlix","credentials.json")}function Yn(e=process.env){let t=e.HLIX_API_KEY;if(!t&&e.HLIX_SESSION_TOKEN)return{baseUrl:e.HLIX_BASE_URL??"https://server.hlix.ai",apiKey:"",sessionToken:e.HLIX_SESSION_TOKEN,...e.HLIX_WORKSPACE_ID?{organizationId:e.HLIX_WORKSPACE_ID}:{}};if(t)return{baseUrl:e.HLIX_BASE_URL??"https://server.hlix.ai",apiKey:t,...e.HLIX_WORKSPACE_ID?{organizationId:e.HLIX_WORKSPACE_ID}:{}};try{let n=JSON.parse(Wn(de(e),"utf8"));return n.apiKey&&n.baseUrl?n:null}catch{return null}}function Zn(e=process.env){let t=de(e);return rt(t)?t:null}function It(e=process.env){let t=de(e);if(!rt(t))return{path:t,removed:!1,reason:"absent"};let n=Ct(t);if(n.isSymbolicLink()||!n.isFile())throw Error("Refusing to remove a credential path that is not a regular file.");let r=process.getuid?.();if(r!==void 0&&Vn(t).uid!==r)throw Error("Refusing to remove a credential file owned by another user.");let s;try{s=JSON.parse(Wn(t,"utf8"))}catch{s=null}let o=s;if(!o||typeof o.apiKey!=="string"||typeof o.baseUrl!=="string")throw Error(`Refusing to remove ${t}: it is not a credential written by this CLI.`);return Xn(t),{path:t,removed:!0,reason:"removed"}}function Qn(e,t=process.env){let n=de(t),r=Es(n);if(bs(r,{recursive:!0,mode:448}),Ct(r).isSymbolicLink())throw Error("Refusing to write credentials through a symlinked directory.");if(rt(n)){let i=Ct(n);if(i.isSymbolicLink()||!i.isFile())throw Error("Refusing to replace a credential path that is not a regular file.");let a=process.getuid?.();if(a!==void 0&&Vn(n).uid!==a)throw Error("Refusing to replace a credential file owned by another user.")}let s=$t(r,`.credentials.${process.pid}.${crypto.randomUUID()}.tmp`),o;try{o=Gn(s,$e.O_WRONLY|$e.O_CREAT|$e.O_EXCL|$e.O_NOFOLLOW,384),ks(o,`${JSON.stringify(e,null,2)}
6
+ `,"utf8"),qn(o),Pt(o),o=void 0,Ss(s,n);let i=Gn(r,$e.O_RDONLY);try{try{qn(i)}catch(a){let c=a.code;if(c!=="EINVAL"&&c!=="ENOTSUP")throw a}}finally{Pt(i)}}catch(i){if(o!==void 0)Pt(o);if(rt(s))Xn(s);throw i}return n}import{constants as st,existsSync as ot,lstatSync as tr,mkdirSync as Ps,openSync as Cs,closeSync as er,fsyncSync as $s,readFileSync as nr,renameSync as Is,unlinkSync as xs,writeFileSync as xt}from"node:fs";import{dirname as Ts,join as Ie,resolve as it}from"node:path";function Rs(e){if(!ot(e))return;let t=tr(e);if(t.isSymbolicLink()||!t.isFile())throw Error(`Refusing to replace a non-regular Hlix file: ${e}`)}function xe(e,t){let n=Ts(e);if(Ps(n,{recursive:!0,mode:448}),tr(n).isSymbolicLink())throw Error(`Refusing to write through a symlinked Hlix directory: ${n}`);Rs(e);let r=Ie(n,`.hlix-${process.pid}-${crypto.randomUUID()}.tmp`),s;try{s=Cs(r,st.O_WRONLY|st.O_CREAT|st.O_EXCL|st.O_NOFOLLOW,384),xt(s,`${JSON.stringify(t,null,2)}
7
+ `,"utf8"),$s(s),er(s),s=void 0,Is(r,e)}catch(o){if(s!==void 0)er(s);if(ot(r))xs(r);throw o}}function Te(e){return Ie(it(e),".hlix","config.json")}function rr(e){return Ie(it(e),".hlix","state.json")}function pe(e){try{let t=JSON.parse(nr(Te(e),"utf8"));return t.schemaVersion===1&&t.workspaceId&&t.apiUrl?t:null}catch{return null}}function Re(e,t){xe(Te(e),t);let n=Ie(it(e),".hlix",".gitignore");if(!ot(n))xt(n,`state.json
8
+ `,{mode:420,flag:"wx"});let r=Ie(it(e),".hlixignore");if(!ot(r))xt(r,`# Additional project-local paths to exclude from Hlix snapshots.
9
+ `,{mode:420,flag:"wx"})}function _e(e,t){xe(rr(e),t)}function at(e){try{let t=JSON.parse(nr(rr(e),"utf8"));return t.schemaVersion===1&&t.revisionId&&t.generation>0?t:null}catch{return null}}var Tt="https://server.hlix.ai";function A(e){let t=As(e);for(;;){let n=pe(t);if(n)return{root:t,config:n};let r=Os(t);if(r===t)return null;t=r}}function or(e){try{return _s(e).isDirectory()}catch{return!1}}function ct(e){if(typeof e!=="string")return;let t=e.trim();return t?t:void 0}var sr=(e,t)=>e.replace(/\/+$/,"")===t.replace(/\/+$/,"");function D(e){let{env:t,flags:n,cwd:r}=e,s=A(r),o=Yn(t),i=o?t.HLIX_API_KEY||t.HLIX_SESSION_TOKEN?"env":"file":null,a=i==="file"?o:null,c=ct(n["base-url"]),l=ct(t.HLIX_BASE_URL),p=ct(n.workspace),d=ct(t.HLIX_WORKSPACE_ID),m=c??l??s?.config.apiUrl??a?.baseUrl??Tt,u=c?"flag":l?"env":s?.config.apiUrl?"project":a?.baseUrl?"credential":"default",f=p??d??s?.config.workspaceId??a?.organizationId??null,g=p?"flag":d?"env":s?.config.workspaceId?"project":a?.organizationId?"credential":null;return{baseUrl:m,baseUrlSource:u,workspaceId:f,workspaceSource:g,credential:o,credentialSource:i,credentialPath:de(t),binding:s,conflict:Fs(s,{flagBaseUrl:c,envBaseUrl:l,flagWorkspace:p,envWorkspace:d})}}function Fs(e,t){if(!e)return null;let n=`${e.root} is bound to`,r="Drop the override, or point --cwd at a folder bound to it.";if(t.flagWorkspace&&t.flagWorkspace!==e.config.workspaceId)return`${n} workspace ${e.config.workspaceId}, but --workspace names ${t.flagWorkspace}. ${r}`;if(t.envWorkspace&&t.envWorkspace!==e.config.workspaceId)return`${n} workspace ${e.config.workspaceId}, but HLIX_WORKSPACE_ID names ${t.envWorkspace}. ${r}`;if(t.flagBaseUrl&&!sr(t.flagBaseUrl,e.config.apiUrl))return`${n} ${e.config.apiUrl}, but --base-url names ${t.flagBaseUrl}. ${r}`;if(t.envBaseUrl&&!sr(t.envBaseUrl,e.config.apiUrl))return`${n} ${e.config.apiUrl}, but HLIX_BASE_URL names ${t.envBaseUrl}. ${r}`;return null}import{resolve as Vs}from"node:path";import{parseArgs as Xs}from"node:util";import Ns from"openapi-fetch";function Rt(e){return Ns({baseUrl:e.baseUrl,headers:e.headers,fetch:e.fetch})}var ue=(e)=>({kind:"apiKey",apiKey:e});var _t=(e)=>({kind:"bearer",token:e});function Hs(e){switch(e.kind){case"apiKey":return{"x-api-key":e.apiKey};case"session":return{cookie:e.cookie};case"bearer":return{authorization:`Bearer ${e.token}`}}}function Ls(e){return e?{"X-Organization-Id":e}:{}}function ir(e,t){return{...Hs(e),...Ls(t)}}function Us(e){if(typeof e!=="object"||e===null)return null;let{error:t}=e;return typeof t==="string"?t:null}class M extends Error{status;body;requestId;method;url;constructor(e,t){super(e);this.name=new.target.name,this.status=t.status,this.body=t.body,this.requestId=t.requestId??null,this.method=t.method,this.url=t.url}}class Oe extends M{issues;constructor(e,t,n){super(e,t);this.issues=n}}class Ae extends M{}class Fe extends M{}class Ne extends M{}class He extends M{}class Le extends M{}class Ue extends M{retryAfter;constructor(e,t,n){super(e,t);this.retryAfter=n}}class Me extends M{}class Be extends M{}class me extends Error{method;url;constructor(e,t){super(e,{cause:t.cause});this.name="HlixTransportError",this.method=t.method,this.url=t.url}}function Ms(e){if(typeof e!=="object"||e===null)return null;let t=e;if(t.success!==!1)return null;let n=t.error?.message;if(typeof n!=="string")return null;try{let r=JSON.parse(n);return Array.isArray(r)?r:[]}catch{return[]}}function Bs(e){let t=e.get("retry-after");if(!t)return null;let n=Number(t);return Number.isFinite(n)&&n>=0?n:null}function fe(e,t,n){let r={status:e.status,body:t,requestId:e.headers.get("x-request-id"),method:n.method,url:n.url},s=Us(t),o=`${n.method} ${n.url} failed with ${e.status}`,i=Ms(t);if(i)return new Oe(`${n.method} ${n.url}: request body failed validation`,r,i);let a=s??o;switch(e.status){case 400:return new Ae(a,r);case 401:return new Fe(a,r);case 403:return new Ne(a,r);case 404:return new He(a,r);case 409:return new Le(a,r);case 429:return new Ue(a,r,Bs(e.headers));case 501:return new Me(a,r);default:return e.status>=500?new Be(a,r):new M(a,r)}}var ar=new Set(["GET","HEAD","PUT","DELETE","OPTIONS","TRACE"]);function lt(e){return ar.has(e.toUpperCase())}var zs=new Set([429,500,502,503,504]);function Ds(e){return zs.has(e)}var Ot={attempts:3,baseDelayMs:200,maxDelayMs:5000};function At(e,t,n,r=Math.random){if(n!==null)return Math.min(n*1000,t.maxDelayMs);let s=Math.min(t.baseDelayMs*2**e,t.maxDelayMs);return Math.round(r()*s)}function Ft(e){if(!lt(e.method))return!1;if(e.attempt+1>=e.policy.attempts)return!1;return e.status===null||Ds(e.status)}var Ks=(e)=>new Promise((t)=>setTimeout(t,e));function Js(e){let t=e.headers.get("retry-after");if(!t)return null;let n=Number(t);return Number.isFinite(n)&&n>=0?n:null}function cr(e){let{base:t,policy:n}=e,r=e.sleep??Ks,s=e.random??Math.random;return async(o)=>{let i=o.method.toUpperCase(),a=lt(i)?o.clone():null;for(let c=0;;c+=1){let l=c===0?o:a.clone(),p;try{p=await t(l)}catch(d){if(!a||!Ft({method:i,attempt:c,policy:n,status:null}))throw new me(`${i} ${o.url}: ${d instanceof Error?d.message:String(d)}`,{method:i,url:o.url,cause:d});await r(At(c,n,null,s));continue}if(!Ft({method:i,attempt:c,policy:n,status:p.status}))return p;if(!a)return p;await r(At(c,n,Js(p),s))}}}function b(e,t){if(e.response.ok)return e.data;throw fe(e.response,e.error??e.data,t)}var ze=(e)=>typeof e==="string"?e:"";function Nt(e){let t;try{t=JSON.parse(e)}catch{return null}if(typeof t!=="object"||t===null)return null;let n=t;switch(n.type){case"idle":return{type:"idle"};case"done":return{type:"done"};case"active":return typeof n.runId==="string"?{type:"active",runId:n.runId}:{type:"active"};case"on_chat_model_stream":return{type:"on_chat_model_stream",delta:ze(n.delta)};case"reasoning":return{type:"reasoning",delta:ze(n.delta)};case"on_tool_start":return{type:"on_tool_start",name:ze(n.name),input:n.input};case"on_tool_end":return{type:"on_tool_end",name:ze(n.name),output:n.output};case"error":return{type:"error",message:ze(n.message)};default:return null}}var Ht=(e)=>e.type==="done"||e.type==="idle"||e.type==="error";var qs=()=>({event:null,data:[],id:null,retry:null});function lr(e,t,n){switch(t){case"event":e.event=n;return;case"data":e.data.push(n);return;case"id":if(!n.includes("\x00"))e.id=n;return;case"retry":{if(/^\d+$/.test(n))e.retry=Number(n);return}default:return}}function pr(e){let t=e.data.join(`
10
+ `),n=e.event,r=e.id;if(e.data=[],e.event=null,t==="")return null;return{event:n,data:t,id:r,retry:e.retry}}function dr(e,t){if(t==="")return pr(e);if(t.startsWith(":"))return null;let n=t.indexOf(":");if(n===-1)return lr(e,t,""),null;let r=t.slice(0,n),s=t.slice(n+1);if(s.startsWith(" "))s=s.slice(1);return lr(e,r,s),null}function Gs(e){let t=[],n=0;for(let r=0;r<e.length;r+=1){let s=e[r];if(s!==`
11
11
  `&&s!=="\r")continue;if(t.push(e.slice(n,r)),s==="\r"&&e[r+1]===`
12
- `)r+=1;n=r+1}return{lines:t,rest:e.slice(n)}}async function*Lt(e,t){let n=e.getReader(),r=new TextDecoder,s=qs(),o="",i=()=>void n.cancel().catch(()=>{});t?.addEventListener("abort",i,{once:!0});try{for(;;){let{done:c,value:l}=await n.read();if(c)break;o+=r.decode(l,{stream:!0});let{lines:p,rest:d}=Gs(o);o=d;for(let m of p){let u=lr(s,m);if(u)yield u}if(t?.aborted)return}if(o+=r.decode(),o!==""){let c=lr(s,o);if(c)yield c}let a=dr(s);if(a)yield a}finally{t?.removeEventListener("abort",i),n.releaseLock()}}class ze{raw;baseUrl;headers;fetcher;constructor(e){this.baseUrl=e.baseUrl.replace(/\/+$/,""),this.headers=or(e.credential,e.organizationId);let t={...Ot,...e.retry},n=e.fetch??((r)=>globalThis.fetch(r));this.fetcher=ar({base:n,policy:t}),this.raw=_t({baseUrl:this.baseUrl,headers:this.headers,fetch:this.fetcher})}at(e,t){return{method:e,url:`${this.baseUrl}${t}`}}projects={list:async()=>b(await this.raw.GET("/v1/api/projects"),this.at("GET","/v1/api/projects")),get:async(e)=>b(await this.raw.GET("/v1/api/projects/{id}",{params:{path:{id:e}}}),this.at("GET",`/v1/api/projects/${e}`)),create:async(e)=>b(await this.raw.POST("/v1/api/projects",{body:e}),this.at("POST","/v1/api/projects")),delete:async(e)=>b(await this.raw.DELETE("/v1/api/projects/{id}",{params:{path:{id:e}}}),this.at("DELETE",`/v1/api/projects/${e}`)),start:async(e,t)=>b(await this.raw.POST("/v1/api/projects/{id}/start",{params:{path:{id:e}},body:t}),this.at("POST",`/v1/api/projects/${e}/start`)),refreshPreview:async(e)=>b(await this.raw.POST("/v1/api/projects/{id}/preview/refresh",{params:{path:{id:e}}}),this.at("POST",`/v1/api/projects/${e}/preview/refresh`)),terminal:async(e)=>b(await this.raw.GET("/v1/api/projects/{id}/terminal",{params:{path:{id:e}}}),this.at("GET",`/v1/api/projects/${e}/terminal`)),observeAgent:(e,t,n)=>this.observeAgent(e,t,n),workspace:(e)=>({fs:async(t)=>b(await this.raw.POST("/v1/api/projects/{id}/workspace/fs",{params:{path:{id:e}},body:t}),this.at("POST",`/v1/api/projects/${e}/workspace/fs`)),exec:async(t)=>b(await this.raw.POST("/v1/api/projects/{id}/workspace/exec",{params:{path:{id:e}},body:t}),this.at("POST",`/v1/api/projects/${e}/workspace/exec`))})};secrets={listEntries:async(e)=>b(await this.raw.GET("/v1/api/secrets/project/{projectId}/entries",{params:{path:{projectId:e}}}),this.at("GET",`/v1/api/secrets/project/${e}/entries`)),upsertEntries:async(e,t)=>b(await this.raw.PUT("/v1/api/secrets/project/{projectId}/entries",{params:{path:{projectId:e}},body:t}),this.at("PUT",`/v1/api/secrets/project/${e}/entries`)),importFiles:async(e,t)=>b(await this.raw.PUT("/v1/api/secrets/project/{projectId}/files",{params:{path:{projectId:e}},body:{files:t}}),this.at("PUT",`/v1/api/secrets/project/${e}/files`)),deleteEntry:async(e,t,n)=>b(await this.raw.DELETE("/v1/api/secrets/project/{projectId}/entries/{key}",{params:{path:{projectId:e,key:t},...n===void 0?{}:{query:{source:n}}}}),this.at("DELETE",`/v1/api/secrets/project/${e}/entries/${encodeURIComponent(t)}`)),exportEntries:async(e,t={})=>{let n=`/v1/api/secrets/project/${e}/export`,r=`${this.baseUrl}${n}`,s=await this.fetcher(new Request(r,{method:"POST",headers:{...this.headers,"content-type":"application/json"},body:JSON.stringify({...t.source===void 0?{}:{source:t.source},...t.format===void 0?{}:{format:t.format}})}));if(!s.ok)throw me(s,await s.json().catch(()=>{return}),{method:"POST",url:r});return s.text()}};imports={create:async(e)=>{let t=await this.raw.POST("/v1/api/imports",{body:e});return b(t,this.at("POST","/v1/api/imports"))},get:async(e)=>b(await this.raw.GET("/v1/api/imports/{id}",{params:{path:{id:e}}}),this.at("GET",`/v1/api/imports/${e}`)),finalize:async(e,t)=>{let n=await this.raw.POST("/v1/api/imports/{id}/finalize",{params:{path:{id:e}},body:t});return b(n,this.at("POST",`/v1/api/imports/${e}/finalize`))},uploadBundle:async(e,t,n={})=>{let r=n.chunkSize??8388608;if(r<=0||r%262144!==0)throw Error("Import upload chunkSize must be a positive multiple of 256 KiB");let s=e.url.startsWith("/")?`${this.baseUrl}${e.url}`:e.url;if(e.kind==="hlix-stream"){let i=new Request(s,{method:"PUT",headers:{...this.headers,"content-type":"application/x-git-bundle","content-length":String(t.size)},body:t,signal:n.signal}),a=await this.fetcher(i);if(!a.ok)await this.throwUploadError(a,s);n.onProgress?.(t.size,t.size);return}let o=0;while(o<t.size){let i=Math.min(o+r,t.size),a=new Request(s,{method:"PUT",headers:{"content-type":"application/x-git-bundle","content-length":String(i-o),"content-range":`bytes ${o}-${i-1}/${t.size}`},body:t.slice(o,i),signal:n.signal}),c=await this.fetcher(a);if(c.status!==308&&!c.ok)await this.throwUploadError(c,s);let l=c.headers.get("range")?.match(/bytes=0-(\d+)/)?.[1];if(o=l?Number(l)+1:i,!Number.isSafeInteger(o)||o<i||o>t.size)throw Error("Import upload server returned an invalid acknowledged range");n.onProgress?.(o,t.size)}}};revisions={head:async(e)=>b(await this.raw.GET("/v1/api/projects/{id}/revisions/head",{params:{path:{id:e}}}),this.at("GET",`/v1/api/projects/${e}/revisions/head`)),protectedFiles:async(e)=>b(await this.raw.GET("/v1/api/projects/{id}/protected-files",{params:{path:{id:e}}}),this.at("GET",`/v1/api/projects/${e}/protected-files`)),createUpload:async(e,t)=>{let n=await this.raw.POST("/v1/api/projects/{id}/revisions/uploads",{params:{path:{id:e}},body:t});return b(n,this.at("POST",`/v1/api/projects/${e}/revisions/uploads`))},finalize:async(e,t,n)=>{let r=await this.raw.POST("/v1/api/projects/{id}/revisions/uploads/{uploadId}/finalize",{params:{path:{id:e,uploadId:t}},body:n});return b(r,this.at("POST",`/v1/api/projects/${e}/revisions/uploads/${t}/finalize`))},uploadBundle:async(e,t,n={})=>this.imports.uploadBundle(e,t,n),downloadBundle:async(e,t)=>{let n=`/v1/api/projects/${e}/revisions/${t}/bundle`,r=new Request(`${this.baseUrl}${n}`,{method:"GET",headers:this.headers}),s=await this.fetcher(r);if(!s.ok)await this.throwUploadError(s,`${this.baseUrl}${n}`);return s.blob()}};resources={importSkill:async(e,t)=>b(await this.raw.POST("/v1/api/projects/{id}/resources/skill",{params:{path:{id:e}},body:t}),this.at("POST",`/v1/api/projects/${e}/resources/skill`)),importAgent:async(e,t)=>b(await this.raw.POST("/v1/api/projects/{id}/resources/agent",{params:{path:{id:e}},body:t}),this.at("POST",`/v1/api/projects/${e}/resources/agent`)),importMcp:async(e,t)=>b(await this.raw.POST("/v1/api/projects/{id}/resources/mcp",{params:{path:{id:e}},body:t}),this.at("POST",`/v1/api/projects/${e}/resources/mcp`))};async throwUploadError(e,t){let n=null;try{n=await e.json()}catch{n=await e.text().catch(()=>null)}throw me(e,n,{method:"PUT",url:t})}tasks={list:async(e)=>b(await this.raw.GET("/v1/api/tasks",{params:{query:e??{}}}),this.at("GET","/v1/api/tasks")),get:async(e)=>b(await this.raw.GET("/v1/api/tasks/{id}",{params:{path:{id:e}}}),this.at("GET",`/v1/api/tasks/${e}`)),create:async(e)=>b(await this.raw.POST("/v1/api/tasks",{body:e}),this.at("POST","/v1/api/tasks")),update:async(e,t)=>b(await this.raw.PATCH("/v1/api/tasks/{id}",{params:{path:{id:e}},body:t}),this.at("PATCH",`/v1/api/tasks/${e}`)),listComments:async(e)=>b(await this.raw.GET("/v1/api/tasks/{id}/comments",{params:{path:{id:e}}}),this.at("GET",`/v1/api/tasks/${e}/comments`)),addComment:async(e,t)=>b(await this.raw.POST("/v1/api/tasks/{id}/comments",{params:{path:{id:e}},body:t}),this.at("POST",`/v1/api/tasks/${e}/comments`)),review:async(e)=>b(await this.raw.GET("/v1/api/tasks/{id}/review",{params:{path:{id:e}}}),this.at("GET",`/v1/api/tasks/${e}/review`)),stream:(e,t)=>this.stream(`/v1/api/tasks/${e}/stream`,t)};modelConfig={setProjectHarness:async(e,t)=>b(await this.raw.PUT("/v1/api/model-config/harness/{projectId}",{params:{path:{projectId:e}},body:{harness:t}}),this.at("PUT",`/v1/api/model-config/harness/${e}`)),clearProjectHarness:async(e)=>b(await this.raw.DELETE("/v1/api/model-config/harness/{projectId}",{params:{path:{projectId:e}}}),this.at("DELETE",`/v1/api/model-config/harness/${e}`)),setHarness:async(e)=>b(await this.raw.PUT("/v1/api/model-config/harness",{body:{harness:e}}),this.at("PUT","/v1/api/model-config/harness")),clearHarness:async()=>b(await this.raw.DELETE("/v1/api/model-config/harness"),this.at("DELETE","/v1/api/model-config/harness")),resolvedHarness:async()=>b(await this.raw.GET("/v1/api/model-config/harness/resolved"),this.at("GET","/v1/api/model-config/harness/resolved")),resolvedProjectHarness:async(e)=>b(await this.raw.GET("/v1/api/model-config/harness/{projectId}/resolved",{params:{path:{projectId:e}}}),this.at("GET",`/v1/api/model-config/harness/${e}/resolved`))};cycles={list:async(e)=>b(await this.raw.GET("/v1/api/cycles",{params:{query:e??{}}}),this.at("GET","/v1/api/cycles")),get:async(e)=>b(await this.raw.GET("/v1/api/cycles/{id}",{params:{path:{id:e}}}),this.at("GET",`/v1/api/cycles/${e}`)),propose:async(e)=>b(await this.raw.POST("/v1/api/cycles",{body:e}),this.at("POST","/v1/api/cycles")),stream:(e,t)=>this.stream(`/v1/api/cycles/${e}/stream`,t)};clientInvoices={list:async(e)=>b(await this.raw.GET("/v1/api/client-billing/invoices",{params:{query:e??{}}}),this.at("GET","/v1/api/client-billing/invoices")),get:async(e)=>b(await this.raw.GET("/v1/api/client-billing/invoices/{id}",{params:{path:{id:e}}}),this.at("GET",`/v1/api/client-billing/invoices/${e}`)),createDraft:async(e)=>b(await this.raw.POST("/v1/api/client-billing/invoices",{body:e}),this.at("POST","/v1/api/client-billing/invoices")),issue:async(e)=>b(await this.raw.POST("/v1/api/client-billing/invoices/{id}/issue",{params:{path:{id:e}},body:{}}),this.at("POST",`/v1/api/client-billing/invoices/${e}/issue`)),void:async(e,t)=>b(await this.raw.POST("/v1/api/client-billing/invoices/{id}/void",{params:{path:{id:e}},body:{reason:t}}),this.at("POST",`/v1/api/client-billing/invoices/${e}/void`)),pay:async(e)=>b(await this.raw.POST("/v1/api/client-billing/invoices/{id}/pay",{params:{path:{id:e}},body:{}}),this.at("POST",`/v1/api/client-billing/invoices/${e}/pay`)),paymentLink:async(e,t={})=>b(await this.raw.POST("/v1/api/client-billing/invoices/{id}/payment-link",{params:{path:{id:e}},body:t}),this.at("POST",`/v1/api/client-billing/invoices/${e}/payment-link`))};async*observeAgent(e,t,n){let r=`/v1/api/projects/${e}/agents/${t}/observe`;for await(let s of this.stream(r,n)){let o=Nt(s.data);if(!o)continue;if(yield o,Ht(o))return}}async*stream(e,t){let n=`${this.baseUrl}${e}`,r=new Request(n,{headers:{...this.headers,accept:"text/event-stream"},signal:t?.signal}),s=await globalThis.fetch(r);if(!s.ok||!s.body){let o=null;try{o=await s.json()}catch{o=null}throw me(s,o,{method:"GET",url:n})}yield*Lt(s.body,t?.signal)}}function Mt(e){if(e instanceof h)return{code:e.code,status:null};if(e instanceof Te)return{code:"invalid_request",status:400};if(e instanceof Oe)return{code:"bad_request",status:400};if(e instanceof Ae)return{code:"unauthenticated",status:401};if(e instanceof Fe)return{code:"forbidden",status:403};if(e instanceof Ne)return{code:"not_found",status:404};if(e instanceof He)return{code:"conflict",status:409};if(e instanceof Le)return{code:"rate_limited",status:429};if(e instanceof Ue)return{code:"not_implemented",status:501};if(e instanceof Me)return{code:"server_error",status:e.status};if(e instanceof ue)return{code:"unreachable",status:null};return{code:"unknown",status:null}}var Ut=(e)=>e instanceof Error?e.message:String(e);function Zs(e,t){let n=K({env:e,flags:t.flags,cwd:t.cwd});if(n.conflict)throw new h("workspace_mismatch",n.conflict);if(!n.credential)throw new h("unauthenticated","No credential. Run `hlix auth login`, or set HLIX_API_KEY for CI.");return new ze({baseUrl:n.baseUrl,credential:n.credential.sessionToken?Tt(n.credential.sessionToken):_e(n.credential.apiKey),...n.workspaceId?{organizationId:n.workspaceId}:{}})}function pr(e){let t=Math.max(...e.map((r)=>r.name.length));return`hlix — the hlix control-plane CLI
12
+ `)r+=1;n=r+1}return{lines:t,rest:e.slice(n)}}async function*Lt(e,t){let n=e.getReader(),r=new TextDecoder,s=qs(),o="",i=()=>void n.cancel().catch(()=>{});t?.addEventListener("abort",i,{once:!0});try{for(;;){let{done:c,value:l}=await n.read();if(c)break;o+=r.decode(l,{stream:!0});let{lines:p,rest:d}=Gs(o);o=d;for(let m of p){let u=dr(s,m);if(u)yield u}if(t?.aborted)return}if(o+=r.decode(),o!==""){let c=dr(s,o);if(c)yield c}let a=pr(s);if(a)yield a}finally{t?.removeEventListener("abort",i),n.releaseLock()}}class ge{raw;baseUrl;headers;fetcher;constructor(e){this.baseUrl=e.baseUrl.replace(/\/+$/,""),this.headers=ir(e.credential,e.organizationId);let t={...Ot,...e.retry},n=e.fetch??((r)=>globalThis.fetch(r));this.fetcher=cr({base:n,policy:t}),this.raw=Rt({baseUrl:this.baseUrl,headers:this.headers,fetch:this.fetcher})}at(e,t){return{method:e,url:`${this.baseUrl}${t}`}}workspaces={list:async()=>b(await this.raw.GET("/v1/api/workspaces"),this.at("GET","/v1/api/workspaces"))};projects={list:async()=>b(await this.raw.GET("/v1/api/projects"),this.at("GET","/v1/api/projects")),get:async(e)=>b(await this.raw.GET("/v1/api/projects/{id}",{params:{path:{id:e}}}),this.at("GET",`/v1/api/projects/${e}`)),create:async(e)=>b(await this.raw.POST("/v1/api/projects",{body:e}),this.at("POST","/v1/api/projects")),delete:async(e)=>b(await this.raw.DELETE("/v1/api/projects/{id}",{params:{path:{id:e}}}),this.at("DELETE",`/v1/api/projects/${e}`)),start:async(e,t)=>b(await this.raw.POST("/v1/api/projects/{id}/start",{params:{path:{id:e}},body:t}),this.at("POST",`/v1/api/projects/${e}/start`)),refreshPreview:async(e)=>b(await this.raw.POST("/v1/api/projects/{id}/preview/refresh",{params:{path:{id:e}}}),this.at("POST",`/v1/api/projects/${e}/preview/refresh`)),terminal:async(e)=>b(await this.raw.GET("/v1/api/projects/{id}/terminal",{params:{path:{id:e}}}),this.at("GET",`/v1/api/projects/${e}/terminal`)),observeAgent:(e,t,n)=>this.observeAgent(e,t,n),workspace:(e)=>({fs:async(t)=>b(await this.raw.POST("/v1/api/projects/{id}/workspace/fs",{params:{path:{id:e}},body:t}),this.at("POST",`/v1/api/projects/${e}/workspace/fs`)),exec:async(t)=>b(await this.raw.POST("/v1/api/projects/{id}/workspace/exec",{params:{path:{id:e}},body:t}),this.at("POST",`/v1/api/projects/${e}/workspace/exec`))})};secrets={listEntries:async(e)=>b(await this.raw.GET("/v1/api/secrets/project/{projectId}/entries",{params:{path:{projectId:e}}}),this.at("GET",`/v1/api/secrets/project/${e}/entries`)),upsertEntries:async(e,t)=>b(await this.raw.PUT("/v1/api/secrets/project/{projectId}/entries",{params:{path:{projectId:e}},body:t}),this.at("PUT",`/v1/api/secrets/project/${e}/entries`)),importFiles:async(e,t)=>b(await this.raw.PUT("/v1/api/secrets/project/{projectId}/files",{params:{path:{projectId:e}},body:{files:t}}),this.at("PUT",`/v1/api/secrets/project/${e}/files`)),deleteEntry:async(e,t,n)=>b(await this.raw.DELETE("/v1/api/secrets/project/{projectId}/entries/{key}",{params:{path:{projectId:e,key:t},...n===void 0?{}:{query:{source:n}}}}),this.at("DELETE",`/v1/api/secrets/project/${e}/entries/${encodeURIComponent(t)}`)),exportEntries:async(e,t={})=>{let n=`/v1/api/secrets/project/${e}/export`,r=`${this.baseUrl}${n}`,s=await this.fetcher(new Request(r,{method:"POST",headers:{...this.headers,"content-type":"application/json"},body:JSON.stringify({...t.source===void 0?{}:{source:t.source},...t.format===void 0?{}:{format:t.format}})}));if(!s.ok)throw fe(s,await s.json().catch(()=>{return}),{method:"POST",url:r});return s.text()}};imports={create:async(e)=>{let t=await this.raw.POST("/v1/api/imports",{body:e});return b(t,this.at("POST","/v1/api/imports"))},get:async(e)=>b(await this.raw.GET("/v1/api/imports/{id}",{params:{path:{id:e}}}),this.at("GET",`/v1/api/imports/${e}`)),finalize:async(e,t)=>{let n=await this.raw.POST("/v1/api/imports/{id}/finalize",{params:{path:{id:e}},body:t});return b(n,this.at("POST",`/v1/api/imports/${e}/finalize`))},uploadBundle:async(e,t,n={})=>{let r=n.chunkSize??8388608;if(r<=0||r%262144!==0)throw Error("Import upload chunkSize must be a positive multiple of 256 KiB");let s=e.url.startsWith("/")?`${this.baseUrl}${e.url}`:e.url;if(e.kind==="hlix-stream"){let i=new Request(s,{method:"PUT",headers:{...this.headers,"content-type":"application/x-git-bundle","content-length":String(t.size)},body:t,signal:n.signal}),a=await this.fetcher(i);if(!a.ok)await this.throwUploadError(a,s);n.onProgress?.(t.size,t.size);return}let o=0;while(o<t.size){let i=Math.min(o+r,t.size),a=new Request(s,{method:"PUT",headers:{"content-type":"application/x-git-bundle","content-length":String(i-o),"content-range":`bytes ${o}-${i-1}/${t.size}`},body:t.slice(o,i),signal:n.signal}),c=await this.fetcher(a);if(c.status!==308&&!c.ok)await this.throwUploadError(c,s);let l=c.headers.get("range")?.match(/bytes=0-(\d+)/)?.[1];if(o=l?Number(l)+1:i,!Number.isSafeInteger(o)||o<i||o>t.size)throw Error("Import upload server returned an invalid acknowledged range");n.onProgress?.(o,t.size)}}};revisions={head:async(e)=>b(await this.raw.GET("/v1/api/projects/{id}/revisions/head",{params:{path:{id:e}}}),this.at("GET",`/v1/api/projects/${e}/revisions/head`)),protectedFiles:async(e)=>b(await this.raw.GET("/v1/api/projects/{id}/protected-files",{params:{path:{id:e}}}),this.at("GET",`/v1/api/projects/${e}/protected-files`)),createUpload:async(e,t)=>{let n=await this.raw.POST("/v1/api/projects/{id}/revisions/uploads",{params:{path:{id:e}},body:t});return b(n,this.at("POST",`/v1/api/projects/${e}/revisions/uploads`))},finalize:async(e,t,n)=>{let r=await this.raw.POST("/v1/api/projects/{id}/revisions/uploads/{uploadId}/finalize",{params:{path:{id:e,uploadId:t}},body:n});return b(r,this.at("POST",`/v1/api/projects/${e}/revisions/uploads/${t}/finalize`))},uploadBundle:async(e,t,n={})=>this.imports.uploadBundle(e,t,n),downloadBundle:async(e,t)=>{let n=`/v1/api/projects/${e}/revisions/${t}/bundle`,r=new Request(`${this.baseUrl}${n}`,{method:"GET",headers:this.headers}),s=await this.fetcher(r);if(!s.ok)await this.throwUploadError(s,`${this.baseUrl}${n}`);return s.blob()}};resources={importSkill:async(e,t)=>b(await this.raw.POST("/v1/api/projects/{id}/resources/skill",{params:{path:{id:e}},body:t}),this.at("POST",`/v1/api/projects/${e}/resources/skill`)),importAgent:async(e,t)=>b(await this.raw.POST("/v1/api/projects/{id}/resources/agent",{params:{path:{id:e}},body:t}),this.at("POST",`/v1/api/projects/${e}/resources/agent`)),importMcp:async(e,t)=>b(await this.raw.POST("/v1/api/projects/{id}/resources/mcp",{params:{path:{id:e}},body:t}),this.at("POST",`/v1/api/projects/${e}/resources/mcp`))};async throwUploadError(e,t){let n=null;try{n=await e.json()}catch{n=await e.text().catch(()=>null)}throw fe(e,n,{method:"PUT",url:t})}tasks={list:async(e)=>b(await this.raw.GET("/v1/api/tasks",{params:{query:e??{}}}),this.at("GET","/v1/api/tasks")),get:async(e)=>b(await this.raw.GET("/v1/api/tasks/{id}",{params:{path:{id:e}}}),this.at("GET",`/v1/api/tasks/${e}`)),create:async(e)=>b(await this.raw.POST("/v1/api/tasks",{body:e}),this.at("POST","/v1/api/tasks")),update:async(e,t)=>b(await this.raw.PATCH("/v1/api/tasks/{id}",{params:{path:{id:e}},body:t}),this.at("PATCH",`/v1/api/tasks/${e}`)),listComments:async(e)=>b(await this.raw.GET("/v1/api/tasks/{id}/comments",{params:{path:{id:e}}}),this.at("GET",`/v1/api/tasks/${e}/comments`)),addComment:async(e,t)=>b(await this.raw.POST("/v1/api/tasks/{id}/comments",{params:{path:{id:e}},body:t}),this.at("POST",`/v1/api/tasks/${e}/comments`)),review:async(e)=>b(await this.raw.GET("/v1/api/tasks/{id}/review",{params:{path:{id:e}}}),this.at("GET",`/v1/api/tasks/${e}/review`)),stream:(e,t)=>this.stream(`/v1/api/tasks/${e}/stream`,t)};modelConfig={setProjectHarness:async(e,t)=>b(await this.raw.PUT("/v1/api/model-config/harness/{projectId}",{params:{path:{projectId:e}},body:{harness:t}}),this.at("PUT",`/v1/api/model-config/harness/${e}`)),clearProjectHarness:async(e)=>b(await this.raw.DELETE("/v1/api/model-config/harness/{projectId}",{params:{path:{projectId:e}}}),this.at("DELETE",`/v1/api/model-config/harness/${e}`)),setHarness:async(e)=>b(await this.raw.PUT("/v1/api/model-config/harness",{body:{harness:e}}),this.at("PUT","/v1/api/model-config/harness")),clearHarness:async()=>b(await this.raw.DELETE("/v1/api/model-config/harness"),this.at("DELETE","/v1/api/model-config/harness")),resolvedHarness:async()=>b(await this.raw.GET("/v1/api/model-config/harness/resolved"),this.at("GET","/v1/api/model-config/harness/resolved")),resolvedProjectHarness:async(e)=>b(await this.raw.GET("/v1/api/model-config/harness/{projectId}/resolved",{params:{path:{projectId:e}}}),this.at("GET",`/v1/api/model-config/harness/${e}/resolved`))};cycles={list:async(e)=>b(await this.raw.GET("/v1/api/cycles",{params:{query:e??{}}}),this.at("GET","/v1/api/cycles")),get:async(e)=>b(await this.raw.GET("/v1/api/cycles/{id}",{params:{path:{id:e}}}),this.at("GET",`/v1/api/cycles/${e}`)),propose:async(e)=>b(await this.raw.POST("/v1/api/cycles",{body:e}),this.at("POST","/v1/api/cycles")),stream:(e,t)=>this.stream(`/v1/api/cycles/${e}/stream`,t)};clientInvoices={list:async(e)=>b(await this.raw.GET("/v1/api/client-billing/invoices",{params:{query:e??{}}}),this.at("GET","/v1/api/client-billing/invoices")),get:async(e)=>b(await this.raw.GET("/v1/api/client-billing/invoices/{id}",{params:{path:{id:e}}}),this.at("GET",`/v1/api/client-billing/invoices/${e}`)),createDraft:async(e)=>b(await this.raw.POST("/v1/api/client-billing/invoices",{body:e}),this.at("POST","/v1/api/client-billing/invoices")),issue:async(e)=>b(await this.raw.POST("/v1/api/client-billing/invoices/{id}/issue",{params:{path:{id:e}},body:{}}),this.at("POST",`/v1/api/client-billing/invoices/${e}/issue`)),void:async(e,t)=>b(await this.raw.POST("/v1/api/client-billing/invoices/{id}/void",{params:{path:{id:e}},body:{reason:t}}),this.at("POST",`/v1/api/client-billing/invoices/${e}/void`)),pay:async(e)=>b(await this.raw.POST("/v1/api/client-billing/invoices/{id}/pay",{params:{path:{id:e}},body:{}}),this.at("POST",`/v1/api/client-billing/invoices/${e}/pay`)),paymentLink:async(e,t={})=>b(await this.raw.POST("/v1/api/client-billing/invoices/{id}/payment-link",{params:{path:{id:e}},body:t}),this.at("POST",`/v1/api/client-billing/invoices/${e}/payment-link`))};async*observeAgent(e,t,n){let r=`/v1/api/projects/${e}/agents/${t}/observe`;for await(let s of this.stream(r,n)){let o=Nt(s.data);if(!o)continue;if(yield o,Ht(o))return}}async*stream(e,t){let n=`${this.baseUrl}${e}`,r=new Request(n,{headers:{...this.headers,accept:"text/event-stream"},signal:t?.signal}),s=await globalThis.fetch(r);if(!s.ok||!s.body){let o=null;try{o=await s.json()}catch{o=null}throw fe(s,o,{method:"GET",url:n})}yield*Lt(s.body,t?.signal)}}function Bt(e){if(e instanceof h)return{code:e.code,status:null};if(e instanceof Oe)return{code:"invalid_request",status:400};if(e instanceof Ae)return{code:"bad_request",status:400};if(e instanceof Fe)return{code:"unauthenticated",status:401};if(e instanceof Ne)return{code:"forbidden",status:403};if(e instanceof He)return{code:"not_found",status:404};if(e instanceof Le)return{code:"conflict",status:409};if(e instanceof Ue)return{code:"rate_limited",status:429};if(e instanceof Me)return{code:"not_implemented",status:501};if(e instanceof Be)return{code:"server_error",status:e.status};if(e instanceof me)return{code:"unreachable",status:null};return{code:"unknown",status:null}}var Ut=(e)=>e instanceof Error?e.message:String(e);function Ys(e,t){let n=D({env:e,flags:t.flags,cwd:t.cwd});if(n.conflict)throw new h("workspace_mismatch",n.conflict);if(!n.credential)throw new h("unauthenticated","No credential. Run `hlix auth login`, or set HLIX_API_KEY for CI.");return new ge({baseUrl:n.baseUrl,credential:n.credential.sessionToken?_t(n.credential.sessionToken):ue(n.credential.apiKey),...n.workspaceId?{organizationId:n.workspaceId}:{}})}function ur(e){let t=Math.max(...e.map((r)=>r.name.length));return`hlix — the hlix control-plane CLI
13
13
 
14
14
  Usage:
15
15
  hlix <command> [options]
@@ -29,30 +29,31 @@ Options:
29
29
  A command targets the workspace named by, in order: an explicit flag, the
30
30
  HLIX_* environment, the nearest .hlix/config.json, then the stored credential.
31
31
  Run \`hlix status\` to see which one applied.
32
- `}function ur(e,t){for(let n of[...e].sort((r,s)=>s.name.length-r.name.length)){let r=n.name.split(" ");if(r.every((s,o)=>t[o]===s))return{command:n,rest:t.slice(r.length)}}return null}async function tc(e,t,n){if(t.some((k)=>k==="--api-key"||k.startsWith("--api-key=")))return n.stderr("error: API keys are never accepted as command-line arguments. Run `hlix auth login` and use the hidden prompt.\n"),2;let r;try{r=Xs({args:t,allowPositionals:!0,strict:!0,options:{json:{type:"boolean"},help:{type:"boolean"},version:{type:"boolean"},cwd:{type:"string"},"base-url":{type:"string"},workspace:{type:"string"},"dry-run":{type:"boolean"},print:{type:"boolean"},web:{type:"boolean"},"env-file":{type:"string"},history:{type:"string"},name:{type:"string"},stack:{type:"string"},status:{type:"string"},project:{type:"string"},yes:{type:"boolean"},global:{type:"boolean"},org:{type:"boolean"},title:{type:"string"},description:{type:"string"},force:{type:"boolean"},runtime:{type:"string"},duty:{type:"string"},profile:{type:"string"},server:{type:"string"},"allow-stdio":{type:"boolean"},source:{type:"string"},format:{type:"string"},out:{type:"string"},"from-stdin":{type:"boolean"}}})}catch(k){let F=t.includes("--json"),H=Ut(k);if(F)n.stdout(w(Ee("cli",{code:"invalid_usage",message:H,status:null})));else n.stderr(`${H}
33
- `);return 2}let s=r.values.json===!0,o=r.positionals;if(r.values.version===!0){let{version:k}=await import("./package-hbd79e7c.js");return n.stdout(`${k}
34
- `),0}if(o.length===0||r.values.help===!0){let k=ur(e,o);return n.stdout(k?`${k.command.usage}
35
- `:pr(e)),o.length===0&&r.values.help!==!0?1:0}let i=ur(e,o);if(!i){let k=o.join(" ");if(s)n.stdout(w(Ee(k,{code:"unknown_command",message:`Unknown command: ${k}`,status:null})));else n.stderr(`Unknown command: ${k}
32
+ `}function Zs(e,t){let n=[...Array(t.length+1).keys()];for(let r=1;r<=e.length;r+=1){let s=[r];for(let o=1;o<=t.length;o+=1)s[o]=Math.min(n[o]+1,s[o-1]+1,n[o-1]+(e[r-1]===t[o-1]?0:1));n=s}return n[t.length]}function Qs(e,t,n){let r=/Unknown option '--([^'=]+)/.exec(n)?.[1];if(!r)return n;let s=t.findIndex((c)=>c.startsWith("-")),o=s===-1?t:t.slice(0,s),i=new Set(["json","help","version","cwd","workspace","base-url",...Mt(e,o)?.command.options??[]]),a=null;for(let c of i){let l=Zs(r,c);if(l<=2&&(!a||l<a.distance))a={name:c,distance:l}}return a?`${n}
33
+ Did you mean --${a.name}?`:n}function Mt(e,t){for(let n of[...e].sort((r,s)=>s.name.length-r.name.length)){let r=n.name.split(" ");if(r.every((s,o)=>t[o]===s))return{command:n,rest:t.slice(r.length)}}return null}async function sc(e,t,n){if(t.some((k)=>k==="--api-key"||k.startsWith("--api-key=")))return n.stderr("error: API keys are never accepted as command-line arguments. Run `hlix auth login` and use the hidden prompt.\n"),2;let r;try{r=Xs({args:t,allowPositionals:!0,strict:!0,options:{json:{type:"boolean"},help:{type:"boolean"},version:{type:"boolean"},cwd:{type:"string"},"base-url":{type:"string"},workspace:{type:"string"},"dry-run":{type:"boolean"},print:{type:"boolean"},web:{type:"boolean"},"env-file":{type:"string"},history:{type:"string"},name:{type:"string"},stack:{type:"string"},status:{type:"string"},project:{type:"string"},yes:{type:"boolean"},global:{type:"boolean"},org:{type:"boolean"},title:{type:"string"},description:{type:"string"},force:{type:"boolean"},runtime:{type:"string"},duty:{type:"string"},profile:{type:"string"},server:{type:"string"},"allow-stdio":{type:"boolean"},source:{type:"string"},format:{type:"string"},out:{type:"string"},"from-stdin":{type:"boolean"}}})}catch(k){let F=t.includes("--json"),H=Qs(e,t,Ut(k));if(F)n.stdout(w(Ce("cli",{code:"invalid_usage",message:H,status:null})));else n.stderr(`${H}
34
+ `);return 2}let s=r.values.json===!0,o=r.positionals;if(r.values.version===!0){let{version:k}=await import("./package-jey6n0rh.js");return n.stdout(`${k}
35
+ `),0}if(o.length===0||r.values.help===!0){let k=Mt(e,o);return n.stdout(k?`${k.command.usage}
36
+ `:ur(e)),o.length===0&&r.values.help!==!0?1:0}let i=Mt(e,o);if(!i){let k=o.join(" ");if(s)n.stdout(w(Ce(k,{code:"unknown_command",message:`Unknown command: ${k}`,status:null})));else n.stderr(`Unknown command: ${k}
36
37
 
37
- ${pr(e)}`);return 2}let a=new Set(["json","help","version","cwd","workspace","base-url"]),c=new Set(i.command.options??[]),l=Object.entries(r.values).filter(([k,F])=>F!==void 0&&!a.has(k)&&!c.has(k)).map(([k])=>`--${k}`),p=i.command.args??{min:0,max:0},d=i.rest.length<p.min?{code:"missing_argument",message:i.command.usage.split(`
38
+ ${ur(e)}`);return 2}let a=new Set(["json","help","version","cwd","workspace","base-url"]),c=new Set(i.command.options??[]),l=Object.entries(r.values).filter(([k,F])=>F!==void 0&&!a.has(k)&&!c.has(k)).map(([k])=>`--${k}`),p=i.command.args??{min:0,max:0},d=i.rest.length<p.min?{code:"missing_argument",message:i.command.usage.split(`
38
39
  `)[0]}:i.rest.length>p.max?{code:"invalid_usage",message:i.command.usage.split(`
39
- `)[0]}:null,m=typeof r.values.cwd==="string"?r.values.cwd:void 0,u=Vs(m??"."),f=m!==void 0&&!sr(u)?{code:"invalid_usage",message:`--cwd is not a directory: ${u}`}:null,g=l.length>0?{code:"invalid_usage",message:`Unsupported option for ${i.command.name}: ${l.join(", ")}`}:f??d;if(g){if(s)n.stdout(w(Ee(i.command.name,{...g,status:null})));else n.stderr(`error: ${g.message}
40
+ `)[0]}:null,m=typeof r.values.cwd==="string"?r.values.cwd:void 0,u=Vs(m??"."),f=m!==void 0&&!or(u)?{code:"invalid_usage",message:`--cwd is not a directory: ${u}`}:null,g=l.length>0?{code:"invalid_usage",message:`Unsupported option for ${i.command.name}: ${l.join(", ")}`}:f??d;if(g){if(s)n.stdout(w(Ce(i.command.name,{...g,status:null})));else n.stderr(`error: ${g.message}
40
41
 
41
42
  ${i.command.usage}
42
- `);return 2}let P=r.values,_={...n,args:i.rest,json:s,flags:P,cwd:u,requireClient:(k)=>Zs(n.env,{cwd:k??u,flags:P})};try{return await i.command.run(_)}catch(k){let{code:F,status:H}=Mt(k);if(s)n.stdout(w(Ee(i.command.name,{code:F,message:Ut(k),status:H})));else n.stderr(`error: ${Ut(k)}
43
- `);return F==="unauthenticated"||F==="forbidden"?3:1}}import{readFileSync as Ys}from"node:fs";import{homedir as Qs}from"node:os";import{join as eo}from"node:path";var mr=["cloud","docker","local"],fe=["claude-code","codex","cursor-agent","hlix"],pc="hlix",fr={harness:"local and docker sandboxes only",model:"all sandboxes",sandbox:"all sandboxes"},ge=["harness","model","sandbox"],Bt=["projectId","workspaceId","apiUrl"];function zt(e=process.env){return eo(e.HLIX_CONFIG_HOME??Qs(),".hlix","config.json")}function gr(e=process.env){try{let t=JSON.parse(Ys(zt(e),"utf8"));return t.schemaVersion===1?t:null}catch{return null}}function Kt(e,t=process.env){let n=gr(t),r=A(e),s=r?.root??null,o=r?.config??null,i={},a={},c=(l)=>{let p=o?.[l],d=n?.[l];if(p!==void 0)i[l]=p,a[l]="project";else if(d!==void 0)i[l]=d,a[l]="global"};for(let l of ge)c(l);for(let l of Bt){let p=o?.[l];if(p!==void 0)i[l]=p,a[l]="project"}return{merged:i,sources:a,global:n,project:o,paths:{global:zt(t),project:s?Ie(s):null}}}function hr(e){return[...ge,...Bt].map((n)=>({key:n,value:e.merged[n]??null,source:e.sources[n]??"default"}))}function to(e,t){if(e==="sandbox"&&!mr.includes(t))return`sandbox must be one of ${mr.join(", ")}; got "${t}".`;if(e==="harness"&&!fe.includes(t))return`harness must be one of ${fe.join(", ")}; got "${t}".`;if(e==="model"&&t.trim()==="")return"model must not be empty.";return null}function Dt(e){if(ge.includes(e))return e;let t=Bt.includes(e);throw new h("invalid_usage",t?`${e} is written by \`hlix init\` and \`hlix import\`, not by \`hlix config set\`.`:`Unknown setting: ${e}. Known settings: ${ge.join(", ")}.`)}function yr(e,t){let n=to(e,t);if(n)throw new h("invalid_usage",n);return t}function vr(e){if(e.scope==="global"){let r=zt(e.env),s=gr(e.env)??{schemaVersion:1};return $e(r,{...s,[e.key]:e.value}),r}let t=A(e.cwd);if(!t)throw new h("not_initialized","This folder is not bound to hlix. Run `hlix init` here, or set it machine-wide with --global.");let n=Ie(t.root);return $e(n,{...t.config,[e.key]:e.value}),n}import{createHash as no}from"node:crypto";import{mkdirSync as ro,readdirSync as kr,readFileSync as so,rmSync as oo,statSync as jr,writeFileSync as io}from"node:fs";import{homedir as ao,tmpdir as co}from"node:os";import{basename as Er,isAbsolute as lo,join as x,relative as po}from"node:path";var Pr=(e=process.env)=>e.HOME??e.USERPROFILE??ao();function D(e){try{if(!jr(e).isFile())return null;return so(e,"utf8")}catch{return null}}function uo(e){try{return jr(e).isDirectory()}catch{return!1}}function De(e,t){try{return kr(e,{withFileTypes:!0}).filter((n)=>n.isFile()&&n.name.endsWith(t)).map((n)=>x(e,n.name)).sort()}catch{return[]}}function mo(e){try{return kr(e,{withFileTypes:!0}).filter((t)=>t.isDirectory()||t.isSymbolicLink()).map((t)=>x(e,t.name)).sort()}catch{return[]}}function qt(e){let t=e.replace(/^\uFEFF/,""),n=t.indexOf(`
43
+ `);return 2}let P=r.values,R={...n,args:i.rest,json:s,flags:P,cwd:u,requireClient:(k)=>Ys(n.env,{cwd:k??u,flags:P})};try{return await i.command.run(R)}catch(k){let{code:F,status:H}=Bt(k);if(s)n.stdout(w(Ce(i.command.name,{code:F,message:Ut(k),status:H})));else n.stderr(`error: ${Ut(k)}
44
+ `);return F==="unauthenticated"||F==="forbidden"?3:1}}import{readFileSync as eo}from"node:fs";import{homedir as to}from"node:os";import{join as no}from"node:path";var mr=["cloud","docker","local"],he=["claude-code","codex","cursor-agent","hlix"],fc="hlix",fr={harness:"local and docker sandboxes only",model:"all sandboxes",sandbox:"all sandboxes"},ye=["harness","model","sandbox"],zt=["projectId","workspaceId","apiUrl"];function Dt(e=process.env){return no(e.HLIX_CONFIG_HOME??to(),".hlix","config.json")}function gr(e=process.env){try{let t=JSON.parse(eo(Dt(e),"utf8"));return t.schemaVersion===1?t:null}catch{return null}}function Kt(e,t=process.env){let n=gr(t),r=A(e),s=r?.root??null,o=r?.config??null,i={},a={},c=(l)=>{let p=o?.[l],d=n?.[l];if(p!==void 0)i[l]=p,a[l]="project";else if(d!==void 0)i[l]=d,a[l]="global"};for(let l of ye)c(l);for(let l of zt){let p=o?.[l];if(p!==void 0)i[l]=p,a[l]="project"}return{merged:i,sources:a,global:n,project:o,paths:{global:Dt(t),project:s?Te(s):null}}}function hr(e){return[...ye,...zt].map((n)=>({key:n,value:e.merged[n]??null,source:e.sources[n]??"default"}))}function ro(e,t){if(e==="sandbox"&&!mr.includes(t))return`sandbox must be one of ${mr.join(", ")}; got "${t}".`;if(e==="harness"&&!he.includes(t))return`harness must be one of ${he.join(", ")}; got "${t}".`;if(e==="model"&&t.trim()==="")return"model must not be empty.";return null}function Jt(e){if(ye.includes(e))return e;let t=zt.includes(e);throw new h("invalid_usage",t?`${e} is written by \`hlix init\` and \`hlix import\`, not by \`hlix config set\`.`:`Unknown setting: ${e}. Known settings: ${ye.join(", ")}.`)}function yr(e,t){let n=ro(e,t);if(n)throw new h("invalid_usage",n);return t}function vr(e){if(e.scope==="global"){let r=Dt(e.env),s=gr(e.env)??{schemaVersion:1};return xe(r,{...s,[e.key]:e.value}),r}let t=A(e.cwd);if(!t)throw new h("not_initialized","This folder is not bound to hlix. Run `hlix init` here, or set it machine-wide with --global.");let n=Te(t.root);return xe(n,{...t.config,[e.key]:e.value}),n}import{createHash as so}from"node:crypto";import{mkdirSync as oo,readdirSync as kr,readFileSync as io,rmSync as ao,statSync as jr,writeFileSync as co}from"node:fs";import{homedir as lo,tmpdir as po}from"node:os";import{basename as Er,isAbsolute as uo,join as x,relative as mo}from"node:path";var Pr=(e=process.env)=>e.HOME??e.USERPROFILE??lo();function K(e){try{if(!jr(e).isFile())return null;return io(e,"utf8")}catch{return null}}function fo(e){try{return jr(e).isDirectory()}catch{return!1}}function Ke(e,t){try{return kr(e,{withFileTypes:!0}).filter((n)=>n.isFile()&&n.name.endsWith(t)).map((n)=>x(e,n.name)).sort()}catch{return[]}}function go(e){try{return kr(e,{withFileTypes:!0}).filter((t)=>t.isDirectory()||t.isSymbolicLink()).map((t)=>x(e,t.name)).sort()}catch{return[]}}function Gt(e){let t=e.replace(/^\uFEFF/,""),n=t.indexOf(`
44
45
  `);if(!t.startsWith("---")||n===-1)return{fields:{},body:t.trim()};let r=t.indexOf(`
45
46
  ---`,n);if(r===-1)return{fields:{},body:t.trim()};let s={};for(let i of t.slice(n+1,r).split(`
46
47
  `)){let a=/^([A-Za-z_][\w-]*)\s*:\s*(.*)$/.exec(i);if(!a)continue;s[a[1]]=a[2].trim().replace(/^["']|["']$/g,"")}let o=t.indexOf(`
47
- `,r+1);return{fields:s,body:o===-1?"":t.slice(o+1).trim()}}function fo(e){let t=e.trimStart(),n=/^"((?:[^"\\]|\\.)*)"/.exec(t)??/^'([^']*)'/.exec(t);if(n)return n[1].replace(/\\"/g,'"').replace(/\\n/g,`
48
+ `,r+1);return{fields:s,body:o===-1?"":t.slice(o+1).trim()}}function ho(e){let t=e.trimStart(),n=/^"((?:[^"\\]|\\.)*)"/.exec(t)??/^'([^']*)'/.exec(t);if(n)return n[1].replace(/\\"/g,'"').replace(/\\n/g,`
48
49
  `);if(t.startsWith("["))return[...t.matchAll(/"((?:[^"\\]|\\.)*)"|'([^']*)'/g)].map((s)=>s[1]??s[2]??"");if(t.startsWith("{")){let s={};for(let o of t.matchAll(/([A-Za-z0-9_.-]+)\s*=\s*"((?:[^"\\]|\\.)*)"/g))s[o[1]]=o[2].replace(/\\"/g,'"');return s}let r=/^[^\s#]+/.exec(t)?.[0];if(r===void 0)return;if(r==="true"||r==="false")return r==="true";if(/^-?\d+(\.\d+)?$/.test(r))return Number(r);return r}function Cr(e){let t={"":{}},n="",r=e.split(`
49
50
  `);for(let s=0;s<r.length;s+=1){let i=r[s].trim();if(!i||i.startsWith("#"))continue;let a=/^\[\[?([^\]]+)\]\]?$/.exec(i);if(a){n=a[1].trim(),t[n]??={};continue}let c=/^([A-Za-z0-9_.-]+|"[^"]+")\s*=\s*(.*)$/.exec(i);if(!c)continue;let l=c[1].replace(/^"|"$/g,""),p=c[2];if(p.startsWith('"""')){let m=[],u=p.slice(3);if(u.includes('"""'))m.push(u.slice(0,u.indexOf('"""')));else{if(u)m.push(u);while(s+1<r.length){s+=1;let f=r[s],g=f.indexOf('"""');if(g===-1){m.push(f);continue}m.push(f.slice(0,g));break}}t[n][l]=m.join(`
50
- `).replace(/^\n/,"");continue}let d=fo(p);if(d!==void 0)t[n][l]=d}return t}function Jt(e,t){return e.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}/g,(n,r,s)=>{let o=t[r];return o!==void 0&&o!==""?o:s??""})}var wr=(e,t)=>{let n={};for(let[r,s]of Object.entries(e))if(typeof s==="string")n[r]=Jt(s,t);return n},go=[{relative:"GEMINI.md",source:"gemini"},{relative:x(".gemini","GEMINI.md"),source:"gemini"},{relative:".cursorrules",source:"cursor"},{relative:".windsurfrules",source:"windsurf"},{relative:x(".github","copilot-instructions.md"),source:"copilot"}],ho=[{relative:x(".gemini","GEMINI.md"),source:"gemini"}],yo=[{relative:x(".cursor","rules"),source:"cursor",extension:".mdc"},{relative:x(".windsurf","rules"),source:"windsurf",extension:".md"}];function vo(e,t){let n=x(e,".clinerules"),r=uo(n)?De(n,".md"):[n],s=[];for(let o of r){let i=D(o)?.trim();if(i)s.push({path:o,source:"cline",scope:t,content:i})}return s}function wo(e,t,n){let{fields:r,body:s}=qt(t);if(r.alwaysApply==="false")return{path:e,source:"cursor",scope:n,reason:"alwaysApply: false"};if(!s)return{path:e,source:"cursor",scope:n,reason:"no rule body"};let o=r.globs?.replace(/^\[|\]$/g,"").trim();return{path:e,source:"cursor",scope:n,content:s,...o?{note:`Applies to: ${o}`}:{}}}function Sr(e,t){let n=[];for(let r of["",".claude",t])for(let s of["AGENTS.md","CLAUDE.md"]){let o=D(x(e,r,s))?.trim();if(o)n.push(o)}return n}var So=[{dir:".claude",source:"claude",harnessReads:!0},{dir:".agents",source:"agents",harnessReads:!0},{dir:".hlix",source:"hlix",harnessReads:!0},{dir:".codex",source:"codex",harnessReads:!1}],bo=[{relative:x(".cursor","commands"),source:"cursor"},{relative:x(".codex","prompts"),source:"codex"}],$r=[{relative:x(".cursor","mcp.json"),source:"cursor",key:"mcpServers",format:"json"},{relative:x(".windsurf","mcp.json"),source:"windsurf",key:"mcpServers",format:"json"},{relative:x(".gemini","settings.json"),source:"gemini",key:"mcpServers",format:"json"},{relative:x(".vscode","mcp.json"),source:"vscode",key:"servers",format:"json"},{relative:x(".codex","config.toml"),source:"codex",key:"mcp_servers",format:"toml"}],ko="found, not loaded (machine-wide; enable per project by copying into .hlix/mcp.json)",jo=$r.filter((e)=>e.source!=="vscode");function Eo(e,t){if(!e||typeof e!=="object"||Array.isArray(e))return{reason:"not an object"};let n=e;if(n.enabled===!1||n.disabled===!0)return{reason:"disabled"};let r=typeof n.command==="string"&&n.command!=="",s=typeof n.url==="string"&&n.url!=="";if(r&&s)return{reason:'has both "command" and "url"'};if(r){let c=Array.isArray(n.args)?n.args.filter((p)=>typeof p==="string"):void 0,l=n.env&&typeof n.env==="object"&&!Array.isArray(n.env)?wr(n.env,t):void 0;return{config:{command:n.command,...c&&c.length>0?{args:c}:{},...l&&Object.keys(l).length>0?{env:l}:{}}}}if(!s)return{reason:'missing "command" or "url"'};let o=n.headers??n.http_headers,i=o&&typeof o==="object"&&!Array.isArray(o)?wr(o,t):{},a=n.bearer_token_env_var;if(typeof a==="string"&&/^[A-Za-z_][A-Za-z0-9_]*$/.test(a)&&!Object.keys(i).some((c)=>c.toLowerCase()==="authorization"))i.Authorization=`Bearer ${Jt(`\${${a}}`,t)}`;return{config:{url:Jt(n.url,t),...Object.keys(i).length>0?{headers:i}:{}}}}function br(e,t,n,r){let s=D(e),o=[],i=[];if(s===null)return{servers:o,skipped:i};let a=[];if(t.format==="toml"){let c=Cr(s);a=Object.entries(c).filter(([l])=>l.startsWith(`${t.key}.`)).map(([l,p])=>[l.slice(t.key.length+1),p])}else try{let l=JSON.parse(s)?.[t.key];if(l&&typeof l==="object"&&!Array.isArray(l))a=Object.entries(l)}catch{return i.push({path:e,source:t.source,scope:n,reason:"not valid JSON"}),{servers:o,skipped:i}}for(let[c,l]of a){let p=Eo(l,r);if("reason"in p){i.push({path:e,source:t.source,scope:n,reason:`${c}: ${p.reason}`});continue}o.push({path:e,source:t.source,scope:n,name:c,config:p.config})}return{servers:o,skipped:i}}function Po(e,t,n){let{fields:r,body:s}=qt(t);if(!s)return{path:e,source:"claude",scope:n,reason:"no instructions"};let o=r.tools?.replace(/^\[|\]$/g,"").split(",").map((i)=>i.trim()).filter(Boolean);return{path:e,source:"claude",scope:n,name:r.name||Er(e,".md"),description:r.description??"",instructions:s,...o&&o.length>0&&o[0]!=="*"?{tools:o}:{},...r.model?{model:r.model}:{}}}function Co(e){let t=Cr(e)[""]??{},n=typeof t.prompt==="string"?t.prompt.trim():"";if(!n)return null;return{description:typeof t.description==="string"?t.description:"",body:n}}function Ir(e,t,n={}){let r=n.configDir??".hlix",s=n.env??process.env,o={instructions:[],skills:[],commands:[],generatedCommands:[],mcpServers:[],subagents:[],skipped:[]},i=(u)=>{if("reason"in u)o.skipped.push(u);else o.instructions.push(u)};for(let u of go){let f=x(e,u.relative),g=D(f)?.trim();if(g)o.instructions.push({path:f,source:u.source,scope:"project",content:g})}for(let u of yo)for(let f of De(x(e,u.relative),u.extension)){let g=D(f);if(g===null)continue;if(u.source==="cursor"){i(wo(f,g,"project"));continue}let{body:P}=qt(g);if(P)o.instructions.push({path:f,source:u.source,scope:"project",content:P})}for(let u of vo(e,"project"))i(u);let a=Sr(e,r),c=x(e,".codex","AGENTS.md"),l=D(c)?.trim();if(l&&a.includes(l))o.skipped.push({path:c,source:"codex",scope:"project",reason:"same content as the project's AGENTS.md"});else if(l)o.instructions.push({path:c,source:"codex",scope:"project",content:l});for(let u of ho){let f=x(t,u.relative),g=D(f)?.trim();if(g)o.instructions.push({path:f,source:u.source,scope:"global",content:g})}let p=x(t,".codex","AGENTS.md"),d=D(p)?.trim(),m=Sr(t,r);if(d&&m.includes(d))o.skipped.push({path:p,source:"codex",scope:"global",reason:"same content as the machine's AGENTS.md"});else if(d)o.instructions.push({path:p,source:"codex",scope:"global",content:d});for(let[u,f]of[[e,"project"],[t,"global"]])for(let g of So){let P=x(u,g.dir===".hlix"?r:g.dir,"skills");if(!mo(P).some((k)=>D(x(k,"SKILL.md"))!==null))continue;o.skills.push({path:P,source:g.source,scope:f,harnessReads:g.harnessReads})}for(let[u,f]of[[e,"project"],[t,"global"]]){for(let g of bo){let P=x(u,g.relative);if(De(P,".md").length===0)continue;o.commands.push({path:P,source:g.source,scope:f})}for(let g of De(x(u,".gemini","commands"),".toml")){let P=D(g),_=P===null?null:Co(P);if(!_){o.skipped.push({path:g,source:"gemini",scope:f,reason:"no prompt field"});continue}o.generatedCommands.push({path:g,source:"gemini",scope:f,name:Er(g,".toml"),body:`---
51
- description: ${_.description}
51
+ `).replace(/^\n/,"");continue}let d=ho(p);if(d!==void 0)t[n][l]=d}return t}function qt(e,t){return e.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}/g,(n,r,s)=>{let o=t[r];return o!==void 0&&o!==""?o:s??""})}var wr=(e,t)=>{let n={};for(let[r,s]of Object.entries(e))if(typeof s==="string")n[r]=qt(s,t);return n},yo=[{relative:"GEMINI.md",source:"gemini"},{relative:x(".gemini","GEMINI.md"),source:"gemini"},{relative:".cursorrules",source:"cursor"},{relative:".windsurfrules",source:"windsurf"},{relative:x(".github","copilot-instructions.md"),source:"copilot"}],vo=[{relative:x(".gemini","GEMINI.md"),source:"gemini"}],wo=[{relative:x(".cursor","rules"),source:"cursor",extension:".mdc"},{relative:x(".windsurf","rules"),source:"windsurf",extension:".md"}];function bo(e,t){let n=x(e,".clinerules"),r=fo(n)?Ke(n,".md"):[n],s=[];for(let o of r){let i=K(o)?.trim();if(i)s.push({path:o,source:"cline",scope:t,content:i})}return s}function So(e,t,n){let{fields:r,body:s}=Gt(t);if(r.alwaysApply==="false")return{path:e,source:"cursor",scope:n,reason:"alwaysApply: false"};if(!s)return{path:e,source:"cursor",scope:n,reason:"no rule body"};let o=r.globs?.replace(/^\[|\]$/g,"").trim();return{path:e,source:"cursor",scope:n,content:s,...o?{note:`Applies to: ${o}`}:{}}}function br(e,t){let n=[];for(let r of["",".claude",t])for(let s of["AGENTS.md","CLAUDE.md"]){let o=K(x(e,r,s))?.trim();if(o)n.push(o)}return n}var ko=[{dir:".claude",source:"claude",harnessReads:!0},{dir:".agents",source:"agents",harnessReads:!0},{dir:".hlix",source:"hlix",harnessReads:!0},{dir:".codex",source:"codex",harnessReads:!1}],jo=[{relative:x(".cursor","commands"),source:"cursor"},{relative:x(".codex","prompts"),source:"codex"}],$r=[{relative:x(".cursor","mcp.json"),source:"cursor",key:"mcpServers",format:"json"},{relative:x(".windsurf","mcp.json"),source:"windsurf",key:"mcpServers",format:"json"},{relative:x(".gemini","settings.json"),source:"gemini",key:"mcpServers",format:"json"},{relative:x(".vscode","mcp.json"),source:"vscode",key:"servers",format:"json"},{relative:x(".codex","config.toml"),source:"codex",key:"mcp_servers",format:"toml"}],Eo="found, not loaded (machine-wide; enable per project by copying into .hlix/mcp.json)",Po=$r.filter((e)=>e.source!=="vscode");function Co(e,t){if(!e||typeof e!=="object"||Array.isArray(e))return{reason:"not an object"};let n=e;if(n.enabled===!1||n.disabled===!0)return{reason:"disabled"};let r=typeof n.command==="string"&&n.command!=="",s=typeof n.url==="string"&&n.url!=="";if(r&&s)return{reason:'has both "command" and "url"'};if(r){let c=Array.isArray(n.args)?n.args.filter((p)=>typeof p==="string"):void 0,l=n.env&&typeof n.env==="object"&&!Array.isArray(n.env)?wr(n.env,t):void 0;return{config:{command:n.command,...c&&c.length>0?{args:c}:{},...l&&Object.keys(l).length>0?{env:l}:{}}}}if(!s)return{reason:'missing "command" or "url"'};let o=n.headers??n.http_headers,i=o&&typeof o==="object"&&!Array.isArray(o)?wr(o,t):{},a=n.bearer_token_env_var;if(typeof a==="string"&&/^[A-Za-z_][A-Za-z0-9_]*$/.test(a)&&!Object.keys(i).some((c)=>c.toLowerCase()==="authorization"))i.Authorization=`Bearer ${qt(`\${${a}}`,t)}`;return{config:{url:qt(n.url,t),...Object.keys(i).length>0?{headers:i}:{}}}}function Sr(e,t,n,r){let s=K(e),o=[],i=[];if(s===null)return{servers:o,skipped:i};let a=[];if(t.format==="toml"){let c=Cr(s);a=Object.entries(c).filter(([l])=>l.startsWith(`${t.key}.`)).map(([l,p])=>[l.slice(t.key.length+1),p])}else try{let l=JSON.parse(s)?.[t.key];if(l&&typeof l==="object"&&!Array.isArray(l))a=Object.entries(l)}catch{return i.push({path:e,source:t.source,scope:n,reason:"not valid JSON"}),{servers:o,skipped:i}}for(let[c,l]of a){let p=Co(l,r);if("reason"in p){i.push({path:e,source:t.source,scope:n,reason:`${c}: ${p.reason}`});continue}o.push({path:e,source:t.source,scope:n,name:c,config:p.config})}return{servers:o,skipped:i}}function $o(e,t,n){let{fields:r,body:s}=Gt(t);if(!s)return{path:e,source:"claude",scope:n,reason:"no instructions"};let o=r.tools?.replace(/^\[|\]$/g,"").split(",").map((i)=>i.trim()).filter(Boolean);return{path:e,source:"claude",scope:n,name:r.name||Er(e,".md"),description:r.description??"",instructions:s,...o&&o.length>0&&o[0]!=="*"?{tools:o}:{},...r.model?{model:r.model}:{}}}function Io(e){let t=Cr(e)[""]??{},n=typeof t.prompt==="string"?t.prompt.trim():"";if(!n)return null;return{description:typeof t.description==="string"?t.description:"",body:n}}function Ir(e,t,n={}){let r=n.configDir??".hlix",s=n.env??process.env,o={instructions:[],skills:[],commands:[],generatedCommands:[],mcpServers:[],subagents:[],skipped:[]},i=(u)=>{if("reason"in u)o.skipped.push(u);else o.instructions.push(u)};for(let u of yo){let f=x(e,u.relative),g=K(f)?.trim();if(g)o.instructions.push({path:f,source:u.source,scope:"project",content:g})}for(let u of wo)for(let f of Ke(x(e,u.relative),u.extension)){let g=K(f);if(g===null)continue;if(u.source==="cursor"){i(So(f,g,"project"));continue}let{body:P}=Gt(g);if(P)o.instructions.push({path:f,source:u.source,scope:"project",content:P})}for(let u of bo(e,"project"))i(u);let a=br(e,r),c=x(e,".codex","AGENTS.md"),l=K(c)?.trim();if(l&&a.includes(l))o.skipped.push({path:c,source:"codex",scope:"project",reason:"same content as the project's AGENTS.md"});else if(l)o.instructions.push({path:c,source:"codex",scope:"project",content:l});for(let u of vo){let f=x(t,u.relative),g=K(f)?.trim();if(g)o.instructions.push({path:f,source:u.source,scope:"global",content:g})}let p=x(t,".codex","AGENTS.md"),d=K(p)?.trim(),m=br(t,r);if(d&&m.includes(d))o.skipped.push({path:p,source:"codex",scope:"global",reason:"same content as the machine's AGENTS.md"});else if(d)o.instructions.push({path:p,source:"codex",scope:"global",content:d});for(let[u,f]of[[e,"project"],[t,"global"]])for(let g of ko){let P=x(u,g.dir===".hlix"?r:g.dir,"skills");if(!go(P).some((k)=>K(x(k,"SKILL.md"))!==null))continue;o.skills.push({path:P,source:g.source,scope:f,harnessReads:g.harnessReads})}for(let[u,f]of[[e,"project"],[t,"global"]]){for(let g of jo){let P=x(u,g.relative);if(Ke(P,".md").length===0)continue;o.commands.push({path:P,source:g.source,scope:f})}for(let g of Ke(x(u,".gemini","commands"),".toml")){let P=K(g),R=P===null?null:Io(P);if(!R){o.skipped.push({path:g,source:"gemini",scope:f,reason:"no prompt field"});continue}o.generatedCommands.push({path:g,source:"gemini",scope:f,name:Er(g,".toml"),body:`---
52
+ description: ${R.description}
52
53
  ---
53
54
 
54
- ${_.body}
55
- `})}}for(let u of $r){let f=br(x(e,u.relative),u,"project",s);o.skipped.push(...f.skipped);for(let g of f.servers){let P=o.mcpServers.findIndex((_)=>_.name===g.name);if(P===-1)o.mcpServers.push(g);else o.mcpServers[P]=g}}for(let u of jo){let f=br(x(t,u.relative),u,"global",s);for(let g of f.servers)o.skipped.push({path:g.path,source:g.source,scope:"global",reason:`${g.name}: ${ko}`})}for(let[u,f]of[[e,"project"],[t,"global"]])for(let g of De(x(u,".claude","agents"),".md")){let P=D(g);if(P===null)continue;let _=Po(g,P,f);if("reason"in _)o.skipped.push(_);else if(o.subagents.some((k)=>k.name===_.name))o.skipped.push({path:g,source:"claude",scope:f,reason:`a project agent already claims the name ${_.name}`});else o.subagents.push(_)}return o}function yc(e,t){if(e.length===0)return null;let n=x(co(),"hlix-standards-commands",no("sha256").update(t).digest("hex").slice(0,16));try{oo(n,{recursive:!0,force:!0}),ro(n,{recursive:!0});for(let r of e)io(x(n,`${r.name}.md`),r.body,"utf8");return n}catch{return null}}var $o=60000,xr=(e,t)=>{let n=po(t,e);return!n||n.startsWith("..")||lo(n)?e:n};function vc(e,t,n=$o){if(e.length===0)return"";let r=["# Project standards from other agent tools","","These files were written for other coding agents working in this same","project. Treat them as the project's instructions and follow them."].join(`
55
+ ${R.body}
56
+ `})}}for(let u of $r){let f=Sr(x(e,u.relative),u,"project",s);o.skipped.push(...f.skipped);for(let g of f.servers){let P=o.mcpServers.findIndex((R)=>R.name===g.name);if(P===-1)o.mcpServers.push(g);else o.mcpServers[P]=g}}for(let u of Po){let f=Sr(x(t,u.relative),u,"global",s);for(let g of f.servers)o.skipped.push({path:g.path,source:g.source,scope:"global",reason:`${g.name}: ${Eo}`})}for(let[u,f]of[[e,"project"],[t,"global"]])for(let g of Ke(x(u,".claude","agents"),".md")){let P=K(g);if(P===null)continue;let R=$o(g,P,f);if("reason"in R)o.skipped.push(R);else if(o.subagents.some((k)=>k.name===R.name))o.skipped.push({path:g,source:"claude",scope:f,reason:`a project agent already claims the name ${R.name}`});else o.subagents.push(R)}return o}function bc(e,t){if(e.length===0)return null;let n=x(po(),"hlix-standards-commands",so("sha256").update(t).digest("hex").slice(0,16));try{ao(n,{recursive:!0,force:!0}),oo(n,{recursive:!0});for(let r of e)co(x(n,`${r.name}.md`),r.body,"utf8");return n}catch{return null}}var xo=60000,xr=(e,t)=>{let n=mo(t,e);return!n||n.startsWith("..")||uo(n)?e:n};function Sc(e,t,n=xo){if(e.length===0)return"";let r=["# Project standards from other agent tools","","These files were written for other coding agents working in this same","project. Treat them as the project's instructions and follow them."].join(`
56
57
  `),s=[],o=r.length,i=!1;for(let c of e){let l=`# From ${xr(c.path,t)} (${c.source})`,p=c.note?`${l}
57
58
  ${c.note}`:l,d=n-o-p.length-4;if(d<=0){i=!0;break}let m=c.content.length<=d?c.content:`${c.content.slice(0,d)}
58
59
  [truncated]`;if(m.length<c.content.length)i=!0;s.push(`${p}
@@ -63,118 +64,121 @@ ${m}`),o+=p.length+m.length+4}let a=i?`
63
64
 
64
65
  ${s.join(`
65
66
 
66
- `)}${a}`}var Ke=(e,t,n)=>`${e} ${e===1?t:n}`;function wc(e){let t=[];if(e.instructions.length>0)t.push(Ke(e.instructions.length,"instruction file","instruction files"));if(e.skills.length>0)t.push(Ke(e.skills.length,"skill directory","skill directories"));let n=e.commands.length+e.generatedCommands.length;if(n>0)t.push(Ke(n,"command source","command sources"));if(e.mcpServers.length>0)t.push(Ke(e.mcpServers.length,"mcp server","mcp servers"));if(e.subagents.length>0)t.push(Ke(e.subagents.length,"subagent","subagents"));if(t.length===0)return"";let r=[...new Set([...e.instructions,...e.skills,...e.commands,...e.generatedCommands,...e.mcpServers,...e.subagents].map((s)=>s.source))].sort();return`standards: ${t.join(" · ")} (${r.join(", ")})`}function Rr(e,t){let n=[],r=(o,i)=>{if(i.length===0)return;n.push(o,...i.map((a)=>` ${a}`),"")},s=(o)=>`${o.source}${o.scope==="global"?" (global)":""} ${xr(o.path,t)}`;if(r("Instructions",e.instructions.map((o)=>`${s(o)}${o.note?` — ${o.note}`:""}`)),r("Skills",e.skills.map((o)=>`${s(o)}${o.harnessReads?" — already read by the harness":""}`)),r("Commands",[...e.commands.map(s),...e.generatedCommands.map((o)=>`${s(o)} → /${o.name}`)]),r("MCP servers",e.mcpServers.map((o)=>`${s(o)} → ${o.name} (${"command"in o.config?"stdio":"http"})`)),r("Subagents",e.subagents.map((o)=>`${s(o)} → ${o.name}`)),r("Skipped",e.skipped.map((o)=>`${s(o)} — ${o.reason}`)),n.length===0)return`No standards from other agent tools were found in this folder.
67
+ `)}${a}`}var De=(e,t,n)=>`${e} ${e===1?t:n}`;function kc(e){let t=[];if(e.instructions.length>0)t.push(De(e.instructions.length,"instruction file","instruction files"));if(e.skills.length>0)t.push(De(e.skills.length,"skill directory","skill directories"));let n=e.commands.length+e.generatedCommands.length;if(n>0)t.push(De(n,"command source","command sources"));if(e.mcpServers.length>0)t.push(De(e.mcpServers.length,"mcp server","mcp servers"));if(e.subagents.length>0)t.push(De(e.subagents.length,"subagent","subagents"));if(t.length===0)return"";let r=[...new Set([...e.instructions,...e.skills,...e.commands,...e.generatedCommands,...e.mcpServers,...e.subagents].map((s)=>s.source))].sort();return`standards: ${t.join(" · ")} (${r.join(", ")})`}function Tr(e,t){let n=[],r=(o,i)=>{if(i.length===0)return;n.push(o,...i.map((a)=>` ${a}`),"")},s=(o)=>`${o.source}${o.scope==="global"?" (global)":""} ${xr(o.path,t)}`;if(r("Instructions",e.instructions.map((o)=>`${s(o)}${o.note?` — ${o.note}`:""}`)),r("Skills",e.skills.map((o)=>`${s(o)}${o.harnessReads?" — already read by the harness":""}`)),r("Commands",[...e.commands.map(s),...e.generatedCommands.map((o)=>`${s(o)} → /${o.name}`)]),r("MCP servers",e.mcpServers.map((o)=>`${s(o)} → ${o.name} (${"command"in o.config?"stdio":"http"})`)),r("Subagents",e.subagents.map((o)=>`${s(o)} → ${o.name}`)),r("Skipped",e.skipped.map((o)=>`${s(o)} — ${o.reason}`)),n.length===0)return`No standards from other agent tools were found in this folder.
67
68
  `;return`${n.join(`
68
69
  `).trimEnd()}
69
- `}var Gt={name:"auth login",summary:"Verify and store a credential for this machine",usage:["Usage: hlix auth login --workspace <id> [--base-url <url>]",""," --base-url Defaults to https://server.hlix.ai"," --workspace Required. Workspace (organization) id to act in","","The API key is read from a hidden prompt and never accepted as an argument.","For CI, set HLIX_API_KEY and HLIX_WORKSPACE_ID in the environment."].join(`
70
- `),supportsJson:!0,options:["base-url","workspace"],async run(e){let t=typeof e.flags.workspace==="string"?e.flags.workspace:e.env.HLIX_WORKSPACE_ID;if(!t)throw new h("missing_argument","--workspace is required.");let n=e.env.HLIX_API_KEY??await e.readSecret?.("Hlix API key: ")??"";if(!n)throw new h("missing_credential","No API key entered. Run from a terminal or set HLIX_API_KEY for CI.");let r=typeof e.flags["base-url"]==="string"?e.flags["base-url"]:e.env.HLIX_BASE_URL??Rt,s=new URL(r),o=s.hostname==="localhost"||s.hostname==="127.0.0.1"||s.hostname==="::1";if(s.protocol!=="https:"&&!(s.protocol==="http:"&&o))throw new h("invalid_base_url","--base-url must use HTTPS (HTTP is allowed only for localhost).");await new ze({baseUrl:r,credential:_e(n),organizationId:t,retry:{attempts:1}}).projects.list();let a=Yn({baseUrl:r,apiKey:n,organizationId:t},e.env);if(e.json)e.stdout(w(S(Gt.name,{baseUrl:r,organizationId:t,credentialPath:a})));else e.stdout(`Signed in to ${r}
71
- Credential stored at ${a}
72
- `);return 0}},Wt={name:"auth status",summary:"Show which credential is in use, where it came from, and whether it works",usage:["Usage: hlix auth status [--json]","","Names the SOURCE of the credential — the environment or the stored file —","and verifies it against the API. The key itself is never printed, not even","a prefix: machine output gets piped into logs."].join(`
73
- `),supportsJson:!0,async run(e){let t=K({env:e.env,flags:e.flags,cwd:e.cwd});if(t.conflict)throw new h("workspace_mismatch",t.conflict);if(!t.credential)throw new h("unauthenticated","No credential. Run `hlix auth login`, or set HLIX_API_KEY for CI.");try{await e.requireClient().projects.list()}catch(r){throw e.stderr(`credential from ${t.credentialSource}, workspace ${t.workspaceId??"none"}, api ${t.baseUrl}
74
- `),r}let n={credentialSource:t.credentialSource,credentialPath:t.credentialSource==="file"?t.credentialPath:null,baseUrl:t.baseUrl,baseUrlSource:t.baseUrlSource,workspaceId:t.workspaceId,workspaceSource:t.workspaceSource,valid:!0};if(e.json)return e.stdout(w(S(Wt.name,n))),0;return e.stdout(`${O([["credential",t.credentialSource==="env"?`environment (${t.credential?.sessionToken?"HLIX_SESSION_TOKEN":"HLIX_API_KEY"})`:`file (${t.credentialPath})`],["api",`${t.baseUrl} (from ${t.baseUrlSource})`],["workspace",t.workspaceId?`${t.workspaceId} (from ${t.workspaceSource})`:"none"],["status","valid"]])}
75
- `),0}},he={name:"auth logout",summary:"Remove the stored credential from this machine",usage:["Usage: hlix auth logout [--yes] [--json]","","Removes ~/.config/hlix/credentials.json after confirming. A credential","supplied through HLIX_API_KEY is not removed — unset it in the shell that","set it."].join(`
76
- `),supportsJson:!0,options:["yes"],async run(e){let t=K({env:e.env,flags:e.flags,cwd:e.cwd});if(t.credentialSource==="env"){let r=Zn(e.env);if(!r){let o={removed:!1,reason:"environment",path:null};if(e.json)e.stdout(w(S(he.name,o)));else e.stdout(`HLIX_API_KEY is set in this environment; unset it there to sign out.
77
- `);return 0}if(e.flags.yes!==!0){let o={removed:!1,reason:"environment",path:r};if(e.json)e.stdout(w(S(he.name,o)));else e.stdout(`HLIX_API_KEY is set in this environment; unset it there to sign out.
70
+ `}async function To(e,t,n){let r=t.map((a)=>a.id);if(n){if(!r.includes(n))throw new h("workspace_mismatch",t.length===0?`This key belongs to a user who is not a member of any workspace, including ${n}.`:`This key cannot act in workspace ${n}. Available: ${r.join(", ")}.`);return n}if(t.length===0)throw new h("workspace_required","This key belongs to a user who is not a member of any workspace. Create or join one first.");let s=t[0];if(s&&t.length===1)return e.stderr(`Using your only workspace: ${s.name} (${s.id})
71
+ `),s.id;if(e.json||!e.promptChoice)throw new h("missing_argument",`--workspace is required here: this key can act in ${t.length} workspaces. Pass one of: ${r.join(", ")}.`);let o=Math.max(...t.map((a)=>a.name.length));e.stderr(`${t.map((a,c)=>` ${c+1}) ${a.name.padEnd(o)} ${a.slug} ${a.role} ${a.id}`).join(`
72
+ `)}
73
+ `);let i=await e.promptChoice(`Workspace [1-${t.length}]: `,t.length);return r[i]}var Wt={name:"auth login",summary:"Verify and store a credential for this machine",usage:["Usage: hlix auth login [--workspace <id>] [--base-url <url>]",""," --base-url Defaults to https://server.hlix.ai"," --workspace Workspace (organization) id to act in. Optional: the key's"," own workspaces are listed after it is read, and the only"," one is taken automatically.","","The API key is read from a hidden prompt and never accepted as an argument.","For CI, set HLIX_API_KEY and HLIX_WORKSPACE_ID in the environment."].join(`
74
+ `),supportsJson:!0,options:["base-url","workspace"],async run(e){let t=typeof e.flags.workspace==="string"?e.flags.workspace:e.env.HLIX_WORKSPACE_ID,n=e.env.HLIX_API_KEY??await e.readSecret?.("Hlix API key: ")??"";if(!n)throw new h("missing_credential","No API key entered. Run from a terminal or set HLIX_API_KEY for CI.");let r=typeof e.flags["base-url"]==="string"?e.flags["base-url"]:e.env.HLIX_BASE_URL??Tt,s=new URL(r),o=s.hostname==="localhost"||s.hostname==="127.0.0.1"||s.hostname==="::1";if(s.protocol!=="https:"&&!(s.protocol==="http:"&&o))throw new h("invalid_base_url","--base-url must use HTTPS (HTTP is allowed only for localhost).");let i=new ge({baseUrl:r,credential:ue(n),retry:{attempts:1}}),a=await To(e,await i.workspaces.list(),t);await new ge({baseUrl:r,credential:ue(n),organizationId:a,retry:{attempts:1}}).projects.list();let l=Qn({baseUrl:r,apiKey:n,organizationId:a},e.env);if(e.json)e.stdout(w(S(Wt.name,{baseUrl:r,organizationId:a,credentialPath:l})));else e.stdout(`Signed in to ${r}
75
+ Credential stored at ${l}
76
+ `);return 0}},Vt={name:"auth status",summary:"Show which credential is in use, where it came from, and whether it works",usage:["Usage: hlix auth status [--json]","","Names the SOURCE of the credential — the environment or the stored file —","and verifies it against the API. The key itself is never printed, not even","a prefix: machine output gets piped into logs."].join(`
77
+ `),supportsJson:!0,async run(e){let t=D({env:e.env,flags:e.flags,cwd:e.cwd});if(t.conflict)throw new h("workspace_mismatch",t.conflict);if(!t.credential)throw new h("unauthenticated","No credential. Run `hlix auth login`, or set HLIX_API_KEY for CI.");try{await e.requireClient().projects.list()}catch(r){throw e.stderr(`credential from ${t.credentialSource}, workspace ${t.workspaceId??"none"}, api ${t.baseUrl}
78
+ `),r}let n={credentialSource:t.credentialSource,credentialPath:t.credentialSource==="file"?t.credentialPath:null,baseUrl:t.baseUrl,baseUrlSource:t.baseUrlSource,workspaceId:t.workspaceId,workspaceSource:t.workspaceSource,valid:!0};if(e.json)return e.stdout(w(S(Vt.name,n))),0;return e.stdout(`${O([["credential",t.credentialSource==="env"?`environment (${t.credential?.sessionToken?"HLIX_SESSION_TOKEN":"HLIX_API_KEY"})`:`file (${t.credentialPath})`],["api",`${t.baseUrl} (from ${t.baseUrlSource})`],["workspace",t.workspaceId?`${t.workspaceId} (from ${t.workspaceSource})`:"none"],["status","valid"]])}
79
+ `),0}},ve={name:"auth logout",summary:"Remove the stored credential from this machine",usage:["Usage: hlix auth logout [--yes] [--json]","","Removes ~/.config/hlix/credentials.json after confirming. A credential","supplied through HLIX_API_KEY is not removed — unset it in the shell that","set it."].join(`
80
+ `),supportsJson:!0,options:["yes"],async run(e){let t=D({env:e.env,flags:e.flags,cwd:e.cwd});if(t.credentialSource==="env"){let r=Zn(e.env);if(!r){let o={removed:!1,reason:"environment",path:null};if(e.json)e.stdout(w(S(ve.name,o)));else e.stdout(`HLIX_API_KEY is set in this environment; unset it there to sign out.
81
+ `);return 0}if(e.flags.yes!==!0){let o={removed:!1,reason:"environment",path:r};if(e.json)e.stdout(w(S(ve.name,o)));else e.stdout(`HLIX_API_KEY is set in this environment; unset it there to sign out.
78
82
  A stored credential also exists at ${r} — repeat with --yes to remove it.
79
- `);return 0}let s=It(e.env);if(e.json)e.stdout(w(S(he.name,s)));else e.stdout(`Removed ${s.path}
83
+ `);return 0}let s=It(e.env);if(e.json)e.stdout(w(S(ve.name,s)));else e.stdout(`Removed ${s.path}
80
84
  HLIX_API_KEY is still set in this environment; unset it there to finish signing out.
81
- `);return 0}if(e.flags.yes!==!0&&t.credential){if(e.json||!e.confirm)throw new h("approval_required","Removing the stored credential needs approval. Repeat with `--yes`.");if(!await e.confirm(`Remove the stored credential at ${t.credentialPath}? Signing back in needs the API key again.`))throw new h("cancelled","Logout cancelled.")}let n=It(e.env);if(e.json)e.stdout(w(S(he.name,n)));else e.stdout(n.removed?`Removed ${n.path}
85
+ `);return 0}if(e.flags.yes!==!0&&t.credential){if(e.json||!e.confirm)throw new h("approval_required","Removing the stored credential needs approval. Repeat with `--yes`.");if(!await e.confirm(`Remove the stored credential at ${t.credentialPath}? Signing back in needs the API key again.`))throw new h("cancelled","Logout cancelled.")}let n=It(e.env);if(e.json)e.stdout(w(S(ve.name,n)));else e.stdout(n.removed?`Removed ${n.path}
82
86
  `:`No stored credential at ${n.path}
83
- `);return 0}};var _r=ge.join(" | "),Vt={name:"config list",summary:"Show every setting in effect and which file supplied it",usage:["Usage: hlix config list [--cwd <dir>] [--json]","","Merges the machine-wide file with this folder's, per key, and names the","source of each value: project, global, or default (no file names it)."].join(`
84
- `),supportsJson:!0,async run(e){let t=Kt(e.cwd,e.env),n=hr(t);if(e.json)return e.stdout(w(S(Vt.name,{settings:n,paths:t.paths}))),0;return e.stdout(`${X(["setting","value","source","applies to"],n.map((r)=>[r.key,r.value??"-",r.source,fr[r.key]??"this folder's binding"]))}
87
+ `);return 0}};var Rr=ye.join(" | "),Xt={name:"config list",summary:"Show every setting in effect and which file supplied it",usage:["Usage: hlix config list [--cwd <dir>] [--json]","","Merges the machine-wide file with this folder's, per key, and names the","source of each value: project, global, or default (no file names it)."].join(`
88
+ `),supportsJson:!0,async run(e){let t=Kt(e.cwd,e.env),n=hr(t);if(e.json)return e.stdout(w(S(Xt.name,{settings:n,paths:t.paths}))),0;return e.stdout(`${X(["setting","value","source","applies to"],n.map((r)=>[r.key,r.value??"-",r.source,fr[r.key]??"this folder's binding"]))}
85
89
  `),e.stdout(`
86
90
  global ${t.paths.global}
87
91
  `),e.stdout(`project ${t.paths.project??"- (this folder is not bound to hlix)"}
88
- `),0}},Xt={name:"config get",summary:"Print one setting's effective value",usage:[`Usage: hlix config get <${_r}> [--cwd <dir>] [--json]`,"","Prints the value the cascade resolves for one key, or exits 1 when no","file names it."].join(`
89
- `),supportsJson:!0,args:{min:1,max:1},async run(e){let t=Dt(e.args[0]),n=Kt(e.cwd,e.env),r=n.merged[t]??null,s=n.sources[t]??"default";if(e.json)return e.stdout(w(S(Xt.name,{key:t,value:r,source:s}))),r===null?1:0;if(r===null)return e.stderr(`${t} is not set. Set it with \`hlix config set ${t} <value>\`.
92
+ `),0}},Yt={name:"config get",summary:"Print one setting's effective value",usage:[`Usage: hlix config get <${Rr}> [--cwd <dir>] [--json]`,"","Prints the value the cascade resolves for one key, or exits 1 when no","file names it."].join(`
93
+ `),supportsJson:!0,args:{min:1,max:1},async run(e){let t=Jt(e.args[0]),n=Kt(e.cwd,e.env),r=n.merged[t]??null,s=n.sources[t]??"default";if(e.json)return e.stdout(w(S(Yt.name,{key:t,value:r,source:s}))),r===null?1:0;if(r===null)return e.stderr(`${t} is not set. Set it with \`hlix config set ${t} <value>\`.
90
94
  `),1;return e.stdout(`${r}
91
- `),0}},Zt={name:"config set",summary:"Set one setting for this folder, or for the machine with --global",usage:[`Usage: hlix config set <${_r}> <value> [--global] [--cwd <dir>] [--json]`,"","Writes this folder's .hlix/config.json, or the machine-wide file with","--global. Other keys in the file are left untouched. The binding keys","(projectId, workspaceId, apiUrl) are written by init/import and are","refused here."].join(`
92
- `),supportsJson:!0,options:["global"],args:{min:2,max:2},async run(e){let t=Dt(e.args[0]),n=yr(t,e.args[1]),r=e.flags.global===!0?"global":"project",s=vr({key:t,value:n,scope:r,cwd:e.cwd,env:e.env});if(e.json)return e.stdout(w(S(Zt.name,{key:t,value:n,scope:r,path:s}))),0;return e.stdout(`${t} = ${n} (${r}: ${s})
93
- `),0}};function se(e,t){if(typeof e!=="object"||e===null)return"";let n=e[t];return n===null||n===void 0?"":String(n)}var Yt={name:"projects list",summary:"List the projects in your workspace",usage:"Usage: hlix projects list [--json]",supportsJson:!0,async run(e){let t=await e.requireClient().projects.list();if(e.json)return e.stdout(w(S(Yt.name,t))),0;let n=Array.isArray(t)?t:[];if(n.length===0)return e.stdout(`No projects.
95
+ `),0}},Zt={name:"config set",summary:"Set one setting for this folder, or for the machine with --global",usage:[`Usage: hlix config set <${Rr}> <value> [--global] [--cwd <dir>] [--json]`,"","Writes this folder's .hlix/config.json, or the machine-wide file with","--global. Other keys in the file are left untouched. The binding keys","(projectId, workspaceId, apiUrl) are written by init/import and are","refused here."].join(`
96
+ `),supportsJson:!0,options:["global"],args:{min:2,max:2},async run(e){let t=Jt(e.args[0]),n=yr(t,e.args[1]),r=e.flags.global===!0?"global":"project",s=vr({key:t,value:n,scope:r,cwd:e.cwd,env:e.env});if(e.json)return e.stdout(w(S(Zt.name,{key:t,value:n,scope:r,path:s}))),0;return e.stdout(`${t} = ${n} (${r}: ${s})
97
+ `),0}};function se(e,t){if(typeof e!=="object"||e===null)return"";let n=e[t];return n===null||n===void 0?"":String(n)}var Qt={name:"projects list",summary:"List the projects in your workspace",usage:"Usage: hlix projects list [--json]",supportsJson:!0,async run(e){let t=await e.requireClient().projects.list();if(e.json)return e.stdout(w(S(Qt.name,t))),0;let n=Array.isArray(t)?t:[];if(n.length===0)return e.stdout(`No projects.
94
98
  `),0;return e.stdout(`${X(["ID","NAME","STACK"],n.map((r)=>[se(r,"id"),se(r,"name"),se(r,"stack")]))}
95
- `),0}},Qt={name:"projects get",summary:"Show one project, defaulting to the one this folder is bound to",usage:["Usage: hlix projects get [project-id] [--json]","","With no id, the project this folder is bound to is used."].join(`
96
- `),supportsJson:!0,args:{min:0,max:1},async run(e){let t=e.args[0]??A(e.cwd)?.config.projectId;if(!t)throw new h("missing_argument","A project id is required, or run this inside a folder bound to a project.");let n=await e.requireClient().projects.get(t);if(e.json)return e.stdout(w(S(Qt.name,n))),0;let r=n.repos;return e.stdout(`${O([["id",se(n,"id")],["name",se(n,"name")],["stack",se(n,"stack")],["status",se(n,"status")],["repos",Array.isArray(r)?String(r.length):""]].filter(([,s])=>s!==""))}
97
- `),0}};function en(e,t){let n=e.args[0];if(!n)throw new h("missing_argument",`A ${t} id is required.`);return n}function Tr(e,t){let n=e.flags[t];return typeof n==="string"&&n.trim()?n.trim():void 0}function J(e,t){if(typeof e!=="object"||e===null)return"";let n=e[t];return n===null||n===void 0?"":String(n)}var tn={name:"tasks list",summary:"List tasks, defaulting to the project this folder is bound to",usage:["Usage: hlix tasks list [--project <id>] [--status <status>] [--json]","","With no --project, a folder bound to a project lists that project's tasks;","anywhere else it lists the workspace's tasks."].join(`
98
- `),supportsJson:!0,options:["project","status"],async run(e){let t=Tr(e,"project")??A(e.cwd)?.config.projectId,n=Tr(e,"status"),r=await e.requireClient().tasks.list({...t?{projectId:t}:{},...n?{status:n}:{}});if(e.json)return e.stdout(w(S(tn.name,r))),0;let s=Array.isArray(r)?r:[];if(s.length===0)return e.stdout(`No tasks.
99
+ `),0}},en={name:"projects get",summary:"Show one project, defaulting to the one this folder is bound to",usage:["Usage: hlix projects get [project-id] [--json]","","With no id, the project this folder is bound to is used."].join(`
100
+ `),supportsJson:!0,args:{min:0,max:1},async run(e){let t=e.args[0]??A(e.cwd)?.config.projectId;if(!t)throw new h("missing_argument","A project id is required, or run this inside a folder bound to a project.");let n=await e.requireClient().projects.get(t);if(e.json)return e.stdout(w(S(en.name,n))),0;let r=n.repos;return e.stdout(`${O([["id",se(n,"id")],["name",se(n,"name")],["stack",se(n,"stack")],["status",se(n,"status")],["repos",Array.isArray(r)?String(r.length):""]].filter(([,s])=>s!==""))}
101
+ `),0}};function tn(e,t){let n=e.args[0];if(!n)throw new h("missing_argument",`A ${t} id is required.`);return n}function _r(e,t){let n=e.flags[t];return typeof n==="string"&&n.trim()?n.trim():void 0}function J(e,t){if(typeof e!=="object"||e===null)return"";let n=e[t];return n===null||n===void 0?"":String(n)}var nn={name:"tasks list",summary:"List tasks, defaulting to the project this folder is bound to",usage:["Usage: hlix tasks list [--project <id>] [--status <status>] [--json]","","With no --project, a folder bound to a project lists that project's tasks;","anywhere else it lists the workspace's tasks."].join(`
102
+ `),supportsJson:!0,options:["project","status"],async run(e){let t=_r(e,"project")??A(e.cwd)?.config.projectId,n=_r(e,"status"),r=await e.requireClient().tasks.list({...t?{projectId:t}:{},...n?{status:n}:{}});if(e.json)return e.stdout(w(S(nn.name,r))),0;let s=Array.isArray(r)?r:[];if(s.length===0)return e.stdout(`No tasks.
99
103
  `),0;return e.stdout(`${X(["ID","STATUS","TITLE"],s.map((o)=>[J(o,"id"),J(o,"status"),J(o,"title")||J(o,"description").split(`
100
104
  `)[0]||""]))}
101
- `),0}},nn={name:"tasks get",summary:"Show one task",usage:"Usage: hlix tasks get <task-id> [--json]",supportsJson:!0,args:{min:1,max:1},async run(e){let t=en(e,"task"),n=await e.requireClient().tasks.get(t);if(e.json)return e.stdout(w(S(nn.name,n))),0;return e.stdout(`${O([["id",J(n,"id")],["status",J(n,"status")],["title",J(n,"title")],["project",J(n,"projectId")],["description",J(n,"description")]])}
102
- `),0}},rn={name:"tasks review",summary:"Show the verified review evidence for a task",usage:"Usage: hlix tasks review <task-id> [--json]",supportsJson:!0,args:{min:1,max:1},async run(e){let t=en(e,"task"),n=await e.requireClient().tasks.review(t);if(e.json)return e.stdout(w(S(rn.name,n))),0;return e.stdout(`${JSON.stringify(n,null,2)}
103
- `),0}},sn={name:"tasks watch",summary:"Stream a task's status changes until it finishes",usage:["Usage: hlix tasks watch <task-id> [--json]","","Streams the task's server-sent status frames and exits when the task","reaches a terminal status or the server closes the stream.","","With --json, each frame is printed as one envelope per line (JSONL) so a","consumer can read them as they arrive."].join(`
104
- `),supportsJson:!0,args:{min:1,max:1},async run(e){let t=en(e,"task"),n=e.requireClient();for await(let r of n.tasks.stream(t)){let s;try{s=JSON.parse(r.data)}catch{s=r.data}if(e.json)e.stdout(`${JSON.stringify(S(sn.name,s))}
105
+ `),0}},rn={name:"tasks get",summary:"Show one task",usage:"Usage: hlix tasks get <task-id> [--json]",supportsJson:!0,args:{min:1,max:1},async run(e){let t=tn(e,"task"),n=await e.requireClient().tasks.get(t);if(e.json)return e.stdout(w(S(rn.name,n))),0;return e.stdout(`${O([["id",J(n,"id")],["status",J(n,"status")],["title",J(n,"title")],["project",J(n,"projectId")],["description",J(n,"description")]])}
106
+ `),0}},sn={name:"tasks review",summary:"Show the verified review evidence for a task",usage:"Usage: hlix tasks review <task-id> [--json]",supportsJson:!0,args:{min:1,max:1},async run(e){let t=tn(e,"task"),n=await e.requireClient().tasks.review(t);if(e.json)return e.stdout(w(S(sn.name,n))),0;return e.stdout(`${JSON.stringify(n,null,2)}
107
+ `),0}},on={name:"tasks watch",summary:"Stream a task's status changes until it finishes",usage:["Usage: hlix tasks watch <task-id> [--json]","","Streams the task's server-sent status frames and exits when the task","reaches a terminal status or the server closes the stream.","","With --json, each frame is printed as one envelope per line (JSONL) so a","consumer can read them as they arrive."].join(`
108
+ `),supportsJson:!0,args:{min:1,max:1},async run(e){let t=tn(e,"task"),n=e.requireClient();for await(let r of n.tasks.stream(t)){let s;try{s=JSON.parse(r.data)}catch{s=r.data}if(e.json)e.stdout(`${JSON.stringify(S(on.name,s))}
105
109
  `);else{let o=J(s,"status"),i=J(s,"error");e.stdout(i?`error: ${i}
106
110
  `:`${o||r.data}
107
- `)}}return 0}};import{realpath as ci}from"node:fs/promises";import{resolve as li}from"node:path";import{createHash as Kr}from"node:crypto";import{createReadStream as Oo}from"node:fs";import{lstat as Dr,readFile as pt,readdir as Ao,realpath as Jr,stat as Fo}from"node:fs/promises";import{basename as ie,join as qr,relative as Lr,resolve as Ur,sep as No}from"node:path";import{spawnSync as Ho}from"node:child_process";import Mr from"ignore";import{readFile as xo}from"node:fs/promises";import{join as Ro}from"node:path";function Io(e){let t=e.trim();if(!t||/^[|>[{]/.test(t))return null;let n=t.match(/^(["'])([\s\S]*)\1$/);if(!n&&/^["']/.test(t))return null;return(n?n[2].trim():t.replace(/(?:^|\s)#.*$/,"").trim())||null}function Or(e){let t=e.split(/\r?\n/),n=t.findIndex((i)=>/^tasks:\s*(?:#.*)?$/.test(i));if(n===-1)return{tasks:[],partial:/^tasks:\s*\S/m.test(e)};let r=[],s=!1,o=-1;for(let i of t.slice(n+1)){if(!i.trim()||/^\s*#/.test(i))continue;let a=i.length-i.trimStart().length,c=i.match(/^(\s*-(?:\s+|$))(.*)$/);if(c){if(o!==-1&&a>=o)continue;if(r.push({}),o=c[2]?c[1].length:-1,!c[2])continue}else if(a===0)break;else if(r.length===0)continue;else if(o===-1)o=a;else if(a!==o)continue;let l=(c?c[2]:i.trim()).match(/^([A-Za-z_][A-Za-z0-9_-]*):\s*(.*)$/);if(!l)continue;let p=l[1];if(p!=="name"&&p!=="before"&&p!=="init"&&p!=="command")continue;let d=Io(l[2]);if(d===null)s=!0;else r[r.length-1][p]=d}return{tasks:r,partial:s}}async function oe(e,t){try{return await xo(Ro(e,...t.split("/")),"utf8")}catch(n){if(n.code==="ENOENT")return null;throw n}}function Ar(e){try{let t=e.replace(/(^|[^:\\])\/\/.*$/gm,"$1").replace(/\/\*[\s\S]*?\*\//g,"").replace(/,\s*([}\]])/g,"$1");return JSON.parse(t)}catch{return null}}function te(e){if(typeof e==="string"&&e.trim())return[e.trim()];if(Array.isArray(e))return e.flatMap(te);if(e&&typeof e==="object")return Object.values(e).flatMap(te);return[]}function on(e){if(!e||typeof e!=="object")return[];return Object.keys(e).filter((t)=>/^[A-Za-z_][A-Za-z0-9_]*$/.test(t))}function _o(e,t){let n=new Set,r=[/\bprocess\.env\.([A-Za-z_][A-Za-z0-9_]*)/g,/\bimport\.meta\.env\.([A-Za-z_][A-Za-z0-9_]*)/g,/\bos\.(?:getenv|environ\.get)\(\s*["']([A-Za-z_][A-Za-z0-9_]*)/g,/\bos\.Getenv\(\s*["']([A-Za-z_][A-Za-z0-9_]*)/g,/\bENV\[\s*["']([A-Za-z_][A-Za-z0-9_]*)/g];if(t)r.push(/\$\{([A-Za-z_][A-Za-z0-9_]*)(?::[-?][^}]*)?\}/g);for(let s of r)for(let o of e.matchAll(s))n.add(o[1]);return[...n]}function To(e,t){if(e.has("bun.lock")||e.has("bun.lockb")||t?.startsWith("bun@"))return"bun install --frozen-lockfile";if(e.has("pnpm-lock.yaml")||t?.startsWith("pnpm@"))return"pnpm install --frozen-lockfile";if(e.has("yarn.lock")||t?.startsWith("yarn@"))return"yarn install --immutable";if(e.has("package-lock.json")||e.has("npm-shrinkwrap.json"))return"npm ci";if(e.has("package.json"))return"npm install";return null}function Fr(e){let t=typeof e==="number"?e:Number(e);return Number.isInteger(t)&&t>0&&t<=65535?t:null}function B(e,t,n){if(!e.some((r)=>r.path===t&&r.kind===n))e.push({path:t,kind:n})}async function Nr(e,t,n){let r=[],s=[],o=[],i=[],a=new Map,c=new Set,l=new Set,p=[],d={},m=null,u=0,f=await oe(e,".cursor/environment.json");if(f){B(r,".cursor/environment.json","cursor");let y=Ar(f);if(!y)p.push("Could not parse .cursor/environment.json; it remains quarantined.");else{s.push(...te(y.install));let C=te(y.start);if(C[0])m=C[0];if(Array.isArray(y.terminals))for(let j of y.terminals){if(!j||typeof j!=="object")continue;let R=j;if(typeof R.command!=="string"||!R.command.trim())continue;i.push({name:typeof R.name==="string"&&R.name.trim()?R.name.trim():"Terminal",command:R.command.trim(),...typeof R.cwd==="string"&&R.cwd.trim()?{cwd:R.cwd.trim()}:{}})}}}let g=t.has(".devcontainer/devcontainer.json")?".devcontainer/devcontainer.json":t.has("devcontainer.json")?"devcontainer.json":null;if(g){B(r,g,"devcontainer");let y=Ar(n.get(g)??await oe(e,g)??"");if(!y)p.push(`Could not parse ${g}; it remains quarantined.`);else{s.push(...te(y.onCreateCommand),...te(y.updateContentCommand),...te(y.postCreateCommand));let C=te(y.postStartCommand);if(!m&&C[0])m=C[0];for(let j of on(y.secrets))c.add(j);for(let j of[...on(y.containerEnv),...on(y.remoteEnv)])c.add(j);if(Array.isArray(y.forwardPorts))for(let j of y.forwardPorts){let R=Fr(j);if(R)a.set(R,{port:R,visibility:"private"})}}}if(t.has(".gitpod.yml")){B(r,".gitpod.yml","gitpod");let y=n.get(".gitpod.yml")??await oe(e,".gitpod.yml");if(y===null)p.push("Could not read .gitpod.yml; its task commands were not imported.");else{let C=Or(y);u=C.tasks.filter((j)=>j.before).length;for(let j of C.tasks){if(j.before)s.push(j.before);if(j.init)s.push(j.init);if(!j.command)continue;if(!m)m=j.command;else i.push({name:j.name??"Terminal",command:j.command})}if(C.partial)p.push("Some .gitpod.yml task values are not plain `key: value` scalars and were not imported; review .gitpod.yml before approving cloud setup.")}}for(let y of["Dockerfile","docker-compose.yml","docker-compose.yaml","compose.yml","compose.yaml"])if(t.has(y))B(r,y,"docker");for(let y of["project.toml","nixpacks.toml","railpack.json","Aptfile"])if(t.has(y))B(r,y,"buildpack");for(let y of["fly.toml","railway.json","render.yaml","vercel.json","netlify.toml"])if(t.has(y))B(r,y,"platform");let P=n.get("package.json")??await oe(e,"package.json");if(P){B(r,"package.json","package");try{let y=JSON.parse(P);if(y.engines?.node)d.node=y.engines.node;let C=To(t,y.packageManager);if(C&&s.length===u)s.push(C);if(y.scripts?.build&&o.length===0)o.push(`${y.packageManager?.split("@")[0]??(t.has("bun.lock")?"bun":"npm")} run build`);let j=y.scripts?.dev?`${t.has("bun.lock")?"bun":"npm"} run dev`:null,R=y.scripts?.start?`${t.has("bun.lock")?"bun":"npm"} run start`:j;if(!m&&R)m=R}catch{p.push("Could not parse package.json for environment discovery.")}}if(t.has("uv.lock"))s.push("uv sync --frozen");else if(t.has("poetry.lock"))s.push("poetry install --no-interaction");else if(t.has("requirements.txt"))s.push("python -m pip install -r requirements.txt");if(t.has("go.mod"))s.push("go mod download");if(t.has("Procfile")){B(r,"Procfile","procfile");let C=(n.get("Procfile")??"").split(/\r?\n/).find((j)=>/^web\s*:/.test(j));if(C)m=C.replace(/^web\s*:\s*/,"").trim()||m}let _=[[".node-version","node"],[".nvmrc","node"],[".python-version","python"]];for(let[y,C]of _){let j=(n.get(y)??await oe(e,y))?.trim();if(j)d[C]=j,B(r,y,"tool-version")}let k=n.get(".tool-versions")??await oe(e,".tool-versions");if(k){B(r,".tool-versions","tool-version");for(let y of k.split(/\r?\n/)){let[C,j]=y.trim().split(/\s+/,2);if(!j)continue;if(C==="nodejs")d.node=j;else if(C==="python")d.python=j;else if(C==="bun")d.bun=j}}let F=n.get("mise.toml")??await oe(e,"mise.toml");if(F){B(r,"mise.toml","tool-version");for(let y of F.matchAll(/^\s*(node|python|bun)\s*=\s*["']([^"']+)["']/gm))d[y[1]]=y[2]}for(let[y,C]of n){let j=/(?:^|\/)(?:Dockerfile|Procfile)$/i.test(y)||/\.(?:jsonc?|ya?ml|toml|ini|conf|config|env|sh|bash|zsh|fish)$/i.test(y);for(let R of _o(C,j))l.add(R);for(let R of C.matchAll(/(?:--port(?:=|\s+)|PORT\s*=\s*)(\d{2,5})/g)){let q=Fr(R[1]);if(q)a.set(q,{port:q,visibility:"private"})}}if(r.length===0&&t.size>0)B(r,"repository","detected");let H=(y)=>[...new Set(y.filter(Boolean))],Se=r.length+s.length+(m?1:0);return{sources:r.sort((y,C)=>y.path.localeCompare(C.path)),toolchain:d,install:H(s),build:H(o),start:m,terminals:i,ports:[...a.values()].sort((y,C)=>y.port-C.port),requiredSecretKeys:[...c].sort(),observedSecretKeys:[...l].sort(),confidence:Se>=4?"high":Se>=2?"medium":"low",warnings:p}}var Hr=2;var Lo=25000,Uo=52428800,Mo=524288000,ut=1e4,dt=1048576,ye=10485760,Br=[".git/",".hlix/","node_modules/",".next/",".turbo/",".cache/","dist/","build/","coverage/","__pycache__/",".venv/","venv/","target/",".DS_Store"],ln="Required project environment value was not found locally: ",Bo=/(^|\/)\.env\.(example|sample|template)$/i,zo=/(^|\/)\.env(?:\.[^/]+)?$/i,Ko=/(^|\/)(?:\.envrc|\.netrc|\.npmrc|\.pypirc|credentials(?:\.[^/]+)?(?:\.json|\.toml)?|service-account[^/]*\.json|firebase-adminsdk[^/]*\.json|application_default_credentials\.json|\.docker\/config\.json|\.cargo\/credentials(?:\.toml)?|\.gem\/credentials|\.bundle\/config|(?:pip|pypi)\.conf|\.aws\/credentials|[^/]+\.(?:pem|key|p12|pfx)|[^/]*\.(?:auto\.)?tfvars(?:\.json)?|application[^/]*\.(?:properties|ya?ml)|(?:local|keystore|gradle|secrets?)\.properties|appsettings[^/]*\.json|local\.settings\.json|config\/database\.ya?ml|wrangler\.toml|fly\.toml|serverless\.ya?ml|(?:credentials|secrets?)[^/]*\.(?:json|ya?ml|toml|ini|conf|cfg))$/i,Do=/(^|\/)(?:\.mcp\.json|mcp\.json|claude_desktop_config\.json)$/i,Jo=/(^|\/)(?:AGENTS\.md|CLAUDE\.md|\.cursorrules|\.github\/copilot-instructions\.md)$/i,qo=/(^|\/)(?:\.agents|\.claude)\/skills\//i,Go=/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----|npm_[A-Za-z0-9]{30,}|gh[opusr]_[A-Za-z0-9_]{30,}|glpat-[A-Za-z0-9_-]{20,}|AKIA[0-9A-Z]{16}|AIza[0-9A-Za-z_-]{30,}|(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{16,}|xox[baprs]-[A-Za-z0-9-]{20,}/,Wo=/\.(?:json|ya?ml|toml|ini|conf|config)$/i,Vo=/(?:^|[,{\s])(?:["']?(?:api[_-]?key|access[_-]?token|auth(?:orization)?|client[_-]?secret|password|private[_-]?key|secret|token)["']?)\s*(?::|=)\s*["']?(?!\$\{|process\.env|import\.meta\.env|os\.(?:getenv|environ\.get)|<|replace|example|changeme)[A-Za-z0-9+/_=.:-]{12,}/im,Je=/^HLIX_[A-Za-z0-9_]*$/,an=new Set(["CI","HOME","LANG","LOGNAME","NODE_ENV","OLDPWD","PATH","PORT","PWD","SHELL","SHLVL","TERM","TMPDIR","USER","_"]);function qe(e){return e.split(No).join("/")}function ne(e,t,n=10485760){return Ho("git",["-C",e,...t],{encoding:"utf8",maxBuffer:n,stdio:["ignore","pipe","pipe"]})}async function Xo(e){let t=Kr("sha256");for await(let n of Oo(e))t.update(n);return t.digest("hex")}function cn(e){if(Array.isArray(e))return`[${e.map(cn).join(",")}]`;if(e&&typeof e==="object")return`{${Object.entries(e).sort(([t],[n])=>t.localeCompare(n)).map(([t,n])=>`${JSON.stringify(t)}:${cn(n)}`).join(",")}}`;return JSON.stringify(e)}function Gr(e){let t={};for(let[n,r]of String(e).replace(/^\uFEFF/,"").split(/\r?\n/).entries()){let s=r.trim();if(!s||s.startsWith("#"))continue;let i=(s.startsWith("export ")?s.slice(7).trimStart():s).match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);if(!i)throw Error(`Invalid dotenv assignment on line ${n+1}`);let a=i[2]??"";if(a.startsWith('"')){if(!a.endsWith('"'))throw Error(`Unclosed dotenv quote on line ${n+1}`);a=a.slice(1,-1).replace(/\\n/g,`
108
- `).replace(/\\r/g,"\r")}else if(a.startsWith("'")){if(!a.endsWith("'"))throw Error(`Unclosed dotenv quote on line ${n+1}`);a=a.slice(1,-1)}else a=a.replace(/\s+#.*$/,"").trimEnd();t[i[1]]=a}return t}function Zo(e){let t=null;for(let n=0;n<e.length;n+=1){let r=e[n];if(r==="\\"&&t!=="single"){if(e[n+1]!=="$")return!0;n+=1;continue}if(r==="'"&&t!=="double"){t=t==="single"?null:"single";continue}if(r==='"'&&t!=="single"){t=t==="double"?null:"double";continue}if(t!=="single"&&(r==="$"||r==="`"))return!0;if(t===null&&(r==="<"||r===">")&&e[n+1]==="(")return!0}return t!==null}function Yo(e){let t={},n=new Set,r=new Set;for(let s of String(e).replace(/^\uFEFF/,"").split(/\r?\n/)){let o=s.trim();if(!o||o.startsWith("#"))continue;let a=(o.startsWith("export ")?o.slice(7).trimStart():o).match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);if(!a)continue;let c=a[1],l=a[2]??"";if(n.add(c),Zo(l)){delete t[c],r.add(c);continue}try{let d=Gr(`${c}=${l}`)[c];if(d===void 0)throw Error("missing literal");t[c]=l.trimStart().startsWith("'")?d:d.replace(/\\\$/g,"$"),r.delete(c)}catch{delete t[c],r.add(c)}}return{values:t,keys:[...n].sort(),dynamicKeys:[...r].sort()}}async function Qo(e){let t=ne(e,["rev-parse","--show-toplevel"]);if(t.status!==0)return!1;try{return await Jr(t.stdout.trim())===e}catch{return!1}}function ei(e,t){if(!t)return new Set;let n=ne(e,["ls-files","-z"]);if(n.status!==0)throw Error("Could not enumerate tracked files.");return new Set(n.stdout.split("\x00").filter(Boolean).map(qe))}async function ti(e){let t=Mr().add(Br),n=Mr().add(Br);for(let r of[".gitignore",".hlixignore"])try{let s=qr(e,r);if((await Dr(s)).isFile())n.add(await pt(s,"utf8"))}catch(s){if(s.code!=="ENOENT")throw s}return{hardMatcher:t,matcher:n}}function ni(e){if(Do.test(e))return"mcp";if(qo.test(e))return"skill";if(Jo.test(e))return"agent";return null}function ri(e){if(zo.test(e)&&!Bo.test(e))return"dotenv";if(Ko.test(e))return"credential";return null}function si(e){if(e.has("package.json"))return"typescript";if(e.has("pyproject.toml")||e.has("requirements.txt"))return"python";if(e.has("go.mod"))return"go";if(e.has("Cargo.toml"))return"rust";if(e.has("composer.json"))return"php";if(e.has("Gemfile"))return"ruby";return"other"}function oi(e,t){if(t)return[qe(t)];let n=new Map([[".env",0],[".env.development",1],[".env.local",2],[".env.development.local",3]]),r=e.filter((s)=>n.has(ie(s).toLocaleLowerCase("en-US"))).sort((s,o)=>s.slice(0,-ie(s).length).localeCompare(o.slice(0,-ie(o).length))||n.get(ie(s).toLocaleLowerCase("en-US"))-n.get(ie(o).toLocaleLowerCase("en-US")));return r.length>0?r:e.length===1?[...e]:[]}function ii(e,t){try{let n=JSON.parse(t);if(!n.mcpServers||typeof n.mcpServers!=="object")return[];return Object.entries(n.mcpServers).map(([r,s])=>{let o=s&&typeof s==="object"?s:{},i=o.type==="http"||o.type==="sse"||o.type==="stdio"?o.type:typeof o.command==="string"?"stdio":typeof o.url==="string"?"http":"unknown",a=o.env&&typeof o.env==="object"?o.env:{};return{sourcePath:e,name:r,transport:i,...typeof o.command==="string"?{command:o.command}:{},...Array.isArray(o.args)&&o.args.every((c)=>typeof c==="string")?{args:o.args}:{},...typeof o.url==="string"?{url:o.url}:{},envKeys:Object.keys(a).sort(),enabled:!1}})}catch{return[]}}function zr(e,t){let n=[],r="unknown";for(let s of e.split(/\r?\n/)){if(s.startsWith("@@"))r=s.slice(2);else if(s.trim())n.push({commit:r,path:qe(s.trim()),reason:t});if(n.length>=100)break}return n}function ai(e,t){if(!t)return{head:null,branch:null,refs:[],commitCount:0,complete:!0,findings:[]};let n=ne(e,["rev-parse","HEAD"]).stdout.trim()||null,r=ne(e,["symbolic-ref","--short","-q","HEAD"]),s=r.status===0?r.stdout.trim()||null:null,o=Number.parseInt(ne(e,["rev-list","--count","--all"]).stdout.trim(),10)||0,i=ne(e,["for-each-ref","--format=%(refname)%00%(objectname)","refs/heads","refs/tags"]),a=i.stdout.split(`
109
- `).filter(Boolean).map((m)=>{let[u,f]=m.split("\x00");return{name:u,oid:f}}).filter(({name:m,oid:u})=>/^refs\/(?:heads|tags)\/.+/.test(m)&&/^[0-9a-f]{40,64}$/.test(u)).sort((m,u)=>m.name.localeCompare(u.name)),c=["log","--all",`--max-count=${ut}`,"--pretty=format:@@%H","--name-only"],l=ne(e,[...c,"--",".env",".env.*","*.pem","*.key",".npmrc","*.tfvars"]),p=ne(e,["log","--all",`--max-count=${ut}`,"-G","BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY|npm_[A-Za-z0-9]{30,}|gh[opusr]_[A-Za-z0-9_]{30,}|AKIA[0-9A-Z]{16}|xox[baprs]-[A-Za-z0-9-]{20,}","--pretty=format:@@%H","--name-only"]),d=new Map;for(let m of[...zr(l.stdout,"sensitive-path"),...zr(p.stdout,"secret-pattern")])d.set(`${m.commit}:${m.path}:${m.reason}`,m);return{head:n,branch:s,refs:a,commitCount:o,complete:o<=ut&&a.length<=1000&&i.status===0&&l.status===0&&p.status===0,findings:[...d.values()].slice(0,100)}}async function G(e,t={}){let n=await Jr(Ur(e));if(!(await Fo(n)).isDirectory())throw Error("Import target must be a directory.");let r=await Qo(n),s=ei(n,r),{hardMatcher:o,matcher:i}=await ti(n),a=[],c=[],l=[],p=[],d=[],m=[],u=t.envFile?qe(Lr(n,Ur(n,t.envFile))):void 0,f=u!==void 0&&u!==""&&u!==".."&&!u.startsWith("../");if(t.envFile&&!f)m.push(`Selected environment file must stay inside the project: ${t.envFile}`);let g=new Map,P=new Map,_=new Map,k=new Map,F=[],H=[],Se=new Map,y=t.maxFiles??Lo,C=t.maxFileBytes??Uo,j=t.maxTotalBytes??Mo,R=0,q=0,Un=async(v)=>{let E=await Ao(v,{withFileTypes:!0});E.sort((T,L)=>T.name.localeCompare(L.name));for(let T of E){let L=qr(v,T.name),I=qe(Lr(n,L));if(T.name===".git"){if(I!==".git")m.push(`Nested Git repository is not supported: ${I}`);continue}let z=await Dr(L),Kn=T.isDirectory()?`${I}/`:I,Et=s.has(I),Dn=!Et&&i.ignores(Kn),vs=!Et&&o.ignores(Kn);if(z.isSymbolicLink()){if(d.push({path:I,reason:"symlink"}),!Dn)m.push(`Symlinks are not imported in this release: ${I}`);continue}if(T.isDirectory()){if(vs)continue;await Un(L);continue}let ke=ni(I),je=ri(I);if(Dn&&!ke&&!je)continue;if(!T.isFile()){d.push({path:I,reason:"non-regular-file"});continue}if(a.length+c.length+l.length>=y){m.push(`Project exceeds the ${y} file limit.`);return}if(z.size>C){m.push(`File exceeds the ${C} byte limit: ${I}`);continue}if(R+=z.size,R>j){m.push(`Project exceeds the ${j} byte total limit.`);return}let tt=await Xo(L);if(ke){if(z.size>dt){m.push(`Protected configuration exceeds the ${dt} byte limit: ${I}`);continue}let U=await pt(L);if(q+=U.byteLength,q>ye){m.push(`Protected project files exceed the ${ye} byte total limit.`);continue}if(l.push({path:I,kind:ke,size:z.size,sha256:tt}),H.push({path:I,kind:ke,contentBase64:U.toString("base64")}),ke==="mcp")p.push(...ii(I,U.toString("utf8")));continue}if(je){if(z.size>dt){m.push(`Protected file exceeds the ${dt} byte limit: ${I}`);continue}let U=await pt(L);if(q+=U.byteLength,q>ye){m.push(`Protected project files exceed the ${ye} byte total limit.`);continue}let re=[];if(je==="dotenv")try{let nt=Gr(U),ce={};for(let[ee,le]of Object.entries(nt)){if(Je.test(ee)){m.push(`Hlix control-plane environment keys cannot be imported into a project: ${ee}`);continue}ce[ee]=le}g.set(I,ce),re=Object.keys(ce).sort()}catch{m.push(`Could not parse environment file: ${I}`)}else if(ie(I)===".envrc"){let nt=Yo(U),ce={},ee=new Set,le=[];for(let[N,ws]of Object.entries(nt.values)){if(Je.test(N)){m.push(`Hlix control-plane environment keys cannot be imported into a project: ${N}`);continue}if(an.has(N)){F.push(`Ignored ambient runtime assignment in ${I}: ${N}`);continue}ee.add(N),ce[N]=ws}P.set(I,ce);for(let N of nt.dynamicKeys){if(Je.test(N)){m.push(`Hlix control-plane environment keys cannot be imported into a project: ${N}`);continue}if(an.has(N)){F.push(`Ignored ambient runtime assignment in ${I}: ${N}`);continue}ee.add(N),le.push(N)}if(_.set(I,[...ee].sort()),k.set(I,le.sort()),re=[...ee].sort(),le.length>0)F.push(`Did not execute dynamic .envrc assignments; collect their resolved local values when available: ${le.join(", ")}`)}c.push({path:I,kind:je,keys:re,size:z.size,sha256:tt}),H.push({path:I,kind:je,contentBase64:U.toString("base64")});continue}if(z.size<=1048576){let U=await pt(L),re=U.toString("utf8");if(Se.set(I,re),Go.test(re)||Wo.test(I)&&Vo.test(re)){if(q+=U.byteLength,q>ye){m.push(`Protected project files exceed the ${ye} byte total limit.`);continue}c.push({path:I,kind:"detected-content",keys:[],size:z.size,sha256:tt}),H.push({path:I,kind:"detected-content",contentBase64:U.toString("base64")});continue}}a.push({path:I,size:z.size,sha256:tt,tracked:Et,executable:(z.mode&73)!==0})}};await Un(n),a.sort((v,E)=>v.path.localeCompare(E.path)),c.sort((v,E)=>v.path.localeCompare(E.path)),l.sort((v,E)=>v.path.localeCompare(E.path)),p.sort((v,E)=>`${v.sourcePath}:${v.name}`.localeCompare(`${E.sourcePath}:${E.name}`));let St=oi([...g.keys()].sort(),f?u:void 0);if(t.envFile&&f&&!g.has(St[0]))m.push(`Selected environment file was not found or is not a dotenv file: ${t.envFile}`);let be=new Map;for(let[v,E]of g)for(let T of Object.keys(E))be.set(T,[...be.get(T)??[],v]);for(let[v,E]of _)for(let T of E)be.set(T,[...be.get(T)??[],v]);let ms=[...be].filter(([,v])=>v.length>1).map(([v,E])=>({key:v,paths:E.sort()})).sort((v,E)=>v.key.localeCompare(E.key)),W={};for(let v of St)Object.assign(W,g.get(v)??{});let fs=[...P.keys()].sort((v,E)=>{if(v===".envrc")return 1;if(E===".envrc")return-1;return v.localeCompare(E)}),bt=new Set;for(let v of fs){let E=new Set(k.get(v)??[]);for(let T of _.get(v)??[]){if(E.has(T)){delete W[T],bt.add(T);continue}let L=P.get(v)?.[T];if(L!==void 0)W[T]=L;bt.delete(T)}}let kt=t.historyMode??"abort_on_findings",Q=ai(n,r);if(!Q.complete&&kt!=="preserve")m.push(`Git history scan exceeded ${ut} commits or failed; import requires explicit --history preserve.`);if(Q.findings.length>0&&kt==="abort_on_findings")m.push("Potential secrets exist in Git history. Abort, sanitize the repository, or explicitly use --history preserve.");let Mn=new Set(a.map((v)=>v.path)),gs=await Nr(n,Mn,Se),{observedSecretKeys:hs,...V}=gs;V.warnings.push(...F);let jt=new Set(V.requiredSecretKeys);for(let v of bt)jt.add(v);for(let v of p)for(let E of v.envKeys)jt.add(E);V.requiredSecretKeys=[...jt].sort();for(let v of V.requiredSecretKeys){if(Je.test(v)){m.push(`Hlix control-plane environment keys cannot be imported into a project: ${v}`);continue}if(W[v]!==void 0)continue;let E=t.environment?.[v];if(E===void 0){m.push(`${ln}${v}`);continue}W[v]=E}for(let v of hs){if(Je.test(v)){V.warnings.push(`Ignored reserved Hlix control-plane environment reference: ${v}`);continue}if(an.has(v))continue;if(W[v]!==void 0)continue;let E=t.environment?.[v];if(E===void 0){V.warnings.push(`Observed environment reference has no local value: ${v}`);continue}W[v]=E}V.warnings=[...new Set(V.warnings)].sort();let Bn={schemaVersion:Hr,rootName:t.rootName??ie(n),stack:si(Mn),git:{detected:r,head:Q.head,branch:Q.branch,refs:Q.refs,commitCount:Q.commitCount,historyScanComplete:Q.complete,historyMode:kt},files:a,secretFiles:c,activeEnvFiles:St,secretKeys:Object.keys(W).sort(),envCollisions:ms,quarantinedResources:l,mcpServers:p,historicalSecretFindings:Q.findings,skipped:d,environment:V,totals:{files:a.length,bytes:a.reduce((v,E)=>v+E.size,0)}},zn=cn(Bn),ys=Kr("sha256").update(zn).digest("hex");return{root:n,manifest:Bn,manifestJson:zn,manifestSha256:ys,secretValues:W,protectedFiles:H.sort((v,E)=>v.path.localeCompare(E.path)),blocking:[...new Set(m)]}}var dn={name:"init",summary:"Configure a local folder for Hlix",usage:["Usage: hlix init [folder] [--project <id>] [--json]","","Creates .hlix/config.json, .hlix/.gitignore, and .hlixignore.","Project configuration is safe to commit; local revision state is ignored.",""," --project <id> Bind the folder to an existing cloud project (then `hlix pull`)"].join(`
110
- `),supportsJson:!0,options:["project"],args:{min:0,max:1},async run(e){if(e.args.length>1)throw Error("init accepts at most one folder.");let t=await ci(li(e.cwd,e.args[0]??".")),n=K({env:e.env,flags:e.flags,cwd:t});if(n.conflict)throw new h("workspace_mismatch",n.conflict);if(!n.workspaceId)throw Error("No workspace selected. Run `hlix auth login --workspace <id>` first.");let r=e.requireClient(t);await r.projects.list();let s=pe(t),o=typeof e.flags.project==="string"?e.flags.project:void 0;if(o&&s?.projectId&&s.projectId!==o)throw new h("workspace_mismatch",`This folder is bound to project ${s.projectId}; refusing to rebind it to ${o}.`);if(o)await r.projects.get(o);let i={...s??{schemaVersion:1,workspaceId:n.workspaceId,apiUrl:n.baseUrl},...o?{projectId:o}:{}};xe(t,i);let a=await G(t,{environment:e.env}),c={root:t,config:i,scan:{files:a.manifest.totals.files,bytes:a.manifest.totals.bytes,secretFiles:a.manifest.secretFiles.map((l)=>l.path),quarantinedResources:a.manifest.quarantinedResources.map((l)=>l.path),blocking:a.blocking}};if(e.json)e.stdout(w(S(dn.name,c)));else if(e.stdout(`Initialized ${t}
111
+ `)}}return 0}};import{realpath as pi}from"node:fs/promises";import{resolve as ui}from"node:path";import{createHash as Dr}from"node:crypto";import{createReadStream as No}from"node:fs";import{lstat as Kr,readFile as pt,readdir as Ho,realpath as Jr,stat as Lo}from"node:fs/promises";import{basename as ie,join as qr,relative as Lr,resolve as Ur,sep as Uo}from"node:path";import{spawnSync as Mo}from"node:child_process";import Mr from"ignore";import{readFile as _o}from"node:fs/promises";import{join as Oo}from"node:path";function Ro(e){let t=e.trim();if(!t||/^[|>[{]/.test(t))return null;let n=t.match(/^(["'])([\s\S]*)\1$/);if(!n&&/^["']/.test(t))return null;return(n?n[2].trim():t.replace(/(?:^|\s)#.*$/,"").trim())||null}function Or(e){let t=e.split(/\r?\n/),n=t.findIndex((i)=>/^tasks:\s*(?:#.*)?$/.test(i));if(n===-1)return{tasks:[],partial:/^tasks:\s*\S/m.test(e)};let r=[],s=!1,o=-1;for(let i of t.slice(n+1)){if(!i.trim()||/^\s*#/.test(i))continue;let a=i.length-i.trimStart().length,c=i.match(/^(\s*-(?:\s+|$))(.*)$/);if(c){if(o!==-1&&a>=o)continue;if(r.push({}),o=c[2]?c[1].length:-1,!c[2])continue}else if(a===0)break;else if(r.length===0)continue;else if(o===-1)o=a;else if(a!==o)continue;let l=(c?c[2]:i.trim()).match(/^([A-Za-z_][A-Za-z0-9_-]*):\s*(.*)$/);if(!l)continue;let p=l[1];if(p!=="name"&&p!=="before"&&p!=="init"&&p!=="command")continue;let d=Ro(l[2]);if(d===null)s=!0;else r[r.length-1][p]=d}return{tasks:r,partial:s}}async function oe(e,t){try{return await _o(Oo(e,...t.split("/")),"utf8")}catch(n){if(n.code==="ENOENT")return null;throw n}}function Ar(e){try{let t=e.replace(/(^|[^:\\])\/\/.*$/gm,"$1").replace(/\/\*[\s\S]*?\*\//g,"").replace(/,\s*([}\]])/g,"$1");return JSON.parse(t)}catch{return null}}function te(e){if(typeof e==="string"&&e.trim())return[e.trim()];if(Array.isArray(e))return e.flatMap(te);if(e&&typeof e==="object")return Object.values(e).flatMap(te);return[]}function an(e){if(!e||typeof e!=="object")return[];return Object.keys(e).filter((t)=>/^[A-Za-z_][A-Za-z0-9_]*$/.test(t))}function Ao(e,t){let n=new Set,r=[/\bprocess\.env\.([A-Za-z_][A-Za-z0-9_]*)/g,/\bimport\.meta\.env\.([A-Za-z_][A-Za-z0-9_]*)/g,/\bos\.(?:getenv|environ\.get)\(\s*["']([A-Za-z_][A-Za-z0-9_]*)/g,/\bos\.Getenv\(\s*["']([A-Za-z_][A-Za-z0-9_]*)/g,/\bENV\[\s*["']([A-Za-z_][A-Za-z0-9_]*)/g];if(t)r.push(/\$\{([A-Za-z_][A-Za-z0-9_]*)(?::[-?][^}]*)?\}/g);for(let s of r)for(let o of e.matchAll(s))n.add(o[1]);return[...n]}function Fo(e,t){if(e.has("bun.lock")||e.has("bun.lockb")||t?.startsWith("bun@"))return"bun install --frozen-lockfile";if(e.has("pnpm-lock.yaml")||t?.startsWith("pnpm@"))return"pnpm install --frozen-lockfile";if(e.has("yarn.lock")||t?.startsWith("yarn@"))return"yarn install --immutable";if(e.has("package-lock.json")||e.has("npm-shrinkwrap.json"))return"npm ci";if(e.has("package.json"))return"npm install";return null}function Fr(e){let t=typeof e==="number"?e:Number(e);return Number.isInteger(t)&&t>0&&t<=65535?t:null}function B(e,t,n){if(!e.some((r)=>r.path===t&&r.kind===n))e.push({path:t,kind:n})}async function Nr(e,t,n){let r=[],s=[],o=[],i=[],a=new Map,c=new Set,l=new Set,p=[],d={},m=null,u=0,f=await oe(e,".cursor/environment.json");if(f){B(r,".cursor/environment.json","cursor");let y=Ar(f);if(!y)p.push("Could not parse .cursor/environment.json; it remains quarantined.");else{s.push(...te(y.install));let C=te(y.start);if(C[0])m=C[0];if(Array.isArray(y.terminals))for(let j of y.terminals){if(!j||typeof j!=="object")continue;let T=j;if(typeof T.command!=="string"||!T.command.trim())continue;i.push({name:typeof T.name==="string"&&T.name.trim()?T.name.trim():"Terminal",command:T.command.trim(),...typeof T.cwd==="string"&&T.cwd.trim()?{cwd:T.cwd.trim()}:{}})}}}let g=t.has(".devcontainer/devcontainer.json")?".devcontainer/devcontainer.json":t.has("devcontainer.json")?"devcontainer.json":null;if(g){B(r,g,"devcontainer");let y=Ar(n.get(g)??await oe(e,g)??"");if(!y)p.push(`Could not parse ${g}; it remains quarantined.`);else{s.push(...te(y.onCreateCommand),...te(y.updateContentCommand),...te(y.postCreateCommand));let C=te(y.postStartCommand);if(!m&&C[0])m=C[0];for(let j of an(y.secrets))c.add(j);for(let j of[...an(y.containerEnv),...an(y.remoteEnv)])c.add(j);if(Array.isArray(y.forwardPorts))for(let j of y.forwardPorts){let T=Fr(j);if(T)a.set(T,{port:T,visibility:"private"})}}}if(t.has(".gitpod.yml")){B(r,".gitpod.yml","gitpod");let y=n.get(".gitpod.yml")??await oe(e,".gitpod.yml");if(y===null)p.push("Could not read .gitpod.yml; its task commands were not imported.");else{let C=Or(y);u=C.tasks.filter((j)=>j.before).length;for(let j of C.tasks){if(j.before)s.push(j.before);if(j.init)s.push(j.init);if(!j.command)continue;if(!m)m=j.command;else i.push({name:j.name??"Terminal",command:j.command})}if(C.partial)p.push("Some .gitpod.yml task values are not plain `key: value` scalars and were not imported; review .gitpod.yml before approving cloud setup.")}}for(let y of["Dockerfile","docker-compose.yml","docker-compose.yaml","compose.yml","compose.yaml"])if(t.has(y))B(r,y,"docker");for(let y of["project.toml","nixpacks.toml","railpack.json","Aptfile"])if(t.has(y))B(r,y,"buildpack");for(let y of["fly.toml","railway.json","render.yaml","vercel.json","netlify.toml"])if(t.has(y))B(r,y,"platform");let P=n.get("package.json")??await oe(e,"package.json");if(P){B(r,"package.json","package");try{let y=JSON.parse(P);if(y.engines?.node)d.node=y.engines.node;let C=Fo(t,y.packageManager);if(C&&s.length===u)s.push(C);if(y.scripts?.build&&o.length===0)o.push(`${y.packageManager?.split("@")[0]??(t.has("bun.lock")?"bun":"npm")} run build`);let j=y.scripts?.dev?`${t.has("bun.lock")?"bun":"npm"} run dev`:null,T=y.scripts?.start?`${t.has("bun.lock")?"bun":"npm"} run start`:j;if(!m&&T)m=T}catch{p.push("Could not parse package.json for environment discovery.")}}if(t.has("uv.lock"))s.push("uv sync --frozen");else if(t.has("poetry.lock"))s.push("poetry install --no-interaction");else if(t.has("requirements.txt"))s.push("python -m pip install -r requirements.txt");if(t.has("go.mod"))s.push("go mod download");if(t.has("Procfile")){B(r,"Procfile","procfile");let C=(n.get("Procfile")??"").split(/\r?\n/).find((j)=>/^web\s*:/.test(j));if(C)m=C.replace(/^web\s*:\s*/,"").trim()||m}let R=[[".node-version","node"],[".nvmrc","node"],[".python-version","python"]];for(let[y,C]of R){let j=(n.get(y)??await oe(e,y))?.trim();if(j)d[C]=j,B(r,y,"tool-version")}let k=n.get(".tool-versions")??await oe(e,".tool-versions");if(k){B(r,".tool-versions","tool-version");for(let y of k.split(/\r?\n/)){let[C,j]=y.trim().split(/\s+/,2);if(!j)continue;if(C==="nodejs")d.node=j;else if(C==="python")d.python=j;else if(C==="bun")d.bun=j}}let F=n.get("mise.toml")??await oe(e,"mise.toml");if(F){B(r,"mise.toml","tool-version");for(let y of F.matchAll(/^\s*(node|python|bun)\s*=\s*["']([^"']+)["']/gm))d[y[1]]=y[2]}for(let[y,C]of n){let j=/(?:^|\/)(?:Dockerfile|Procfile)$/i.test(y)||/\.(?:jsonc?|ya?ml|toml|ini|conf|config|env|sh|bash|zsh|fish)$/i.test(y);for(let T of Ao(C,j))l.add(T);for(let T of C.matchAll(/(?:--port(?:=|\s+)|PORT\s*=\s*)(\d{2,5})/g)){let q=Fr(T[1]);if(q)a.set(q,{port:q,visibility:"private"})}}if(r.length===0&&t.size>0)B(r,"repository","detected");let H=(y)=>[...new Set(y.filter(Boolean))],ke=r.length+s.length+(m?1:0);return{sources:r.sort((y,C)=>y.path.localeCompare(C.path)),toolchain:d,install:H(s),build:H(o),start:m,terminals:i,ports:[...a.values()].sort((y,C)=>y.port-C.port),requiredSecretKeys:[...c].sort(),observedSecretKeys:[...l].sort(),confidence:ke>=4?"high":ke>=2?"medium":"low",warnings:p}}var Hr=2;var Bo=25000,zo=52428800,Do=524288000,ut=1e4,dt=1048576,we=10485760,Br=[".git/",".hlix/","node_modules/",".next/",".turbo/",".cache/","dist/","build/","coverage/","__pycache__/",".venv/","venv/","target/",".DS_Store"],dn="Required project environment value was not found locally: ",Ko=/(^|\/)\.env\.(example|sample|template)$/i,Jo=/(^|\/)\.env(?:\.[^/]+)?$/i,qo=/(^|\/)(?:\.envrc|\.netrc|\.npmrc|\.pypirc|credentials(?:\.[^/]+)?(?:\.json|\.toml)?|service-account[^/]*\.json|firebase-adminsdk[^/]*\.json|application_default_credentials\.json|\.docker\/config\.json|\.cargo\/credentials(?:\.toml)?|\.gem\/credentials|\.bundle\/config|(?:pip|pypi)\.conf|\.aws\/credentials|[^/]+\.(?:pem|key|p12|pfx)|[^/]*\.(?:auto\.)?tfvars(?:\.json)?|application[^/]*\.(?:properties|ya?ml)|(?:local|keystore|gradle|secrets?)\.properties|appsettings[^/]*\.json|local\.settings\.json|config\/database\.ya?ml|wrangler\.toml|fly\.toml|serverless\.ya?ml|(?:credentials|secrets?)[^/]*\.(?:json|ya?ml|toml|ini|conf|cfg))$/i,Go=/(^|\/)(?:\.mcp\.json|mcp\.json|claude_desktop_config\.json)$/i,Wo=/(^|\/)(?:AGENTS\.md|CLAUDE\.md|\.cursorrules|\.github\/copilot-instructions\.md)$/i,Vo=/(^|\/)(?:\.agents|\.claude)\/skills\//i,Xo=/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----|npm_[A-Za-z0-9]{30,}|gh[opusr]_[A-Za-z0-9_]{30,}|glpat-[A-Za-z0-9_-]{20,}|AKIA[0-9A-Z]{16}|AIza[0-9A-Za-z_-]{30,}|(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{16,}|xox[baprs]-[A-Za-z0-9-]{20,}/,Yo=/\.(?:json|ya?ml|toml|ini|conf|config)$/i,Zo=/(?:^|[,{\s])(?:["']?(?:api[_-]?key|access[_-]?token|auth(?:orization)?|client[_-]?secret|password|private[_-]?key|secret|token)["']?)\s*(?::|=)\s*["']?(?!\$\{|process\.env|import\.meta\.env|os\.(?:getenv|environ\.get)|<|replace|example|changeme)[A-Za-z0-9+/_=.:-]{12,}/im,Je=/^HLIX_[A-Za-z0-9_]*$/,cn=new Set(["CI","HOME","LANG","LOGNAME","NODE_ENV","OLDPWD","PATH","PORT","PWD","SHELL","SHLVL","TERM","TMPDIR","USER","_"]);function qe(e){return e.split(Uo).join("/")}function ne(e,t,n=10485760){return Mo("git",["-C",e,...t],{encoding:"utf8",maxBuffer:n,stdio:["ignore","pipe","pipe"]})}async function Qo(e){let t=Dr("sha256");for await(let n of No(e))t.update(n);return t.digest("hex")}function ln(e){if(Array.isArray(e))return`[${e.map(ln).join(",")}]`;if(e&&typeof e==="object")return`{${Object.entries(e).sort(([t],[n])=>t.localeCompare(n)).map(([t,n])=>`${JSON.stringify(t)}:${ln(n)}`).join(",")}}`;return JSON.stringify(e)}function Gr(e){let t={};for(let[n,r]of String(e).replace(/^\uFEFF/,"").split(/\r?\n/).entries()){let s=r.trim();if(!s||s.startsWith("#"))continue;let i=(s.startsWith("export ")?s.slice(7).trimStart():s).match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);if(!i)throw Error(`Invalid dotenv assignment on line ${n+1}`);let a=i[2]??"";if(a.startsWith('"')){if(!a.endsWith('"'))throw Error(`Unclosed dotenv quote on line ${n+1}`);a=a.slice(1,-1).replace(/\\n/g,`
112
+ `).replace(/\\r/g,"\r")}else if(a.startsWith("'")){if(!a.endsWith("'"))throw Error(`Unclosed dotenv quote on line ${n+1}`);a=a.slice(1,-1)}else a=a.replace(/\s+#.*$/,"").trimEnd();t[i[1]]=a}return t}function ei(e){let t=null;for(let n=0;n<e.length;n+=1){let r=e[n];if(r==="\\"&&t!=="single"){if(e[n+1]!=="$")return!0;n+=1;continue}if(r==="'"&&t!=="double"){t=t==="single"?null:"single";continue}if(r==='"'&&t!=="single"){t=t==="double"?null:"double";continue}if(t!=="single"&&(r==="$"||r==="`"))return!0;if(t===null&&(r==="<"||r===">")&&e[n+1]==="(")return!0}return t!==null}function ti(e){let t={},n=new Set,r=new Set;for(let s of String(e).replace(/^\uFEFF/,"").split(/\r?\n/)){let o=s.trim();if(!o||o.startsWith("#"))continue;let a=(o.startsWith("export ")?o.slice(7).trimStart():o).match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);if(!a)continue;let c=a[1],l=a[2]??"";if(n.add(c),ei(l)){delete t[c],r.add(c);continue}try{let d=Gr(`${c}=${l}`)[c];if(d===void 0)throw Error("missing literal");t[c]=l.trimStart().startsWith("'")?d:d.replace(/\\\$/g,"$"),r.delete(c)}catch{delete t[c],r.add(c)}}return{values:t,keys:[...n].sort(),dynamicKeys:[...r].sort()}}async function ni(e){let t=ne(e,["rev-parse","--show-toplevel"]);if(t.status!==0)return!1;try{return await Jr(t.stdout.trim())===e}catch{return!1}}function ri(e,t){if(!t)return new Set;let n=ne(e,["ls-files","-z"]);if(n.status!==0)throw Error("Could not enumerate tracked files.");return new Set(n.stdout.split("\x00").filter(Boolean).map(qe))}async function si(e){let t=Mr().add(Br),n=Mr().add(Br);for(let r of[".gitignore",".hlixignore"])try{let s=qr(e,r);if((await Kr(s)).isFile())n.add(await pt(s,"utf8"))}catch(s){if(s.code!=="ENOENT")throw s}return{hardMatcher:t,matcher:n}}function oi(e){if(Go.test(e))return"mcp";if(Vo.test(e))return"skill";if(Wo.test(e))return"agent";return null}function ii(e){if(Jo.test(e)&&!Ko.test(e))return"dotenv";if(qo.test(e))return"credential";return null}function ai(e){if(e.has("package.json"))return"typescript";if(e.has("pyproject.toml")||e.has("requirements.txt"))return"python";if(e.has("go.mod"))return"go";if(e.has("Cargo.toml"))return"rust";if(e.has("composer.json"))return"php";if(e.has("Gemfile"))return"ruby";return"other"}function ci(e,t){if(t)return[qe(t)];let n=new Map([[".env",0],[".env.development",1],[".env.local",2],[".env.development.local",3]]),r=e.filter((s)=>n.has(ie(s).toLocaleLowerCase("en-US"))).sort((s,o)=>s.slice(0,-ie(s).length).localeCompare(o.slice(0,-ie(o).length))||n.get(ie(s).toLocaleLowerCase("en-US"))-n.get(ie(o).toLocaleLowerCase("en-US")));return r.length>0?r:e.length===1?[...e]:[]}function li(e,t){try{let n=JSON.parse(t);if(!n.mcpServers||typeof n.mcpServers!=="object")return[];return Object.entries(n.mcpServers).map(([r,s])=>{let o=s&&typeof s==="object"?s:{},i=o.type==="http"||o.type==="sse"||o.type==="stdio"?o.type:typeof o.command==="string"?"stdio":typeof o.url==="string"?"http":"unknown",a=o.env&&typeof o.env==="object"?o.env:{};return{sourcePath:e,name:r,transport:i,...typeof o.command==="string"?{command:o.command}:{},...Array.isArray(o.args)&&o.args.every((c)=>typeof c==="string")?{args:o.args}:{},...typeof o.url==="string"?{url:o.url}:{},envKeys:Object.keys(a).sort(),enabled:!1}})}catch{return[]}}function zr(e,t){let n=[],r="unknown";for(let s of e.split(/\r?\n/)){if(s.startsWith("@@"))r=s.slice(2);else if(s.trim())n.push({commit:r,path:qe(s.trim()),reason:t});if(n.length>=100)break}return n}function di(e,t){if(!t)return{head:null,branch:null,refs:[],commitCount:0,complete:!0,findings:[]};let n=ne(e,["rev-parse","HEAD"]).stdout.trim()||null,r=ne(e,["symbolic-ref","--short","-q","HEAD"]),s=r.status===0?r.stdout.trim()||null:null,o=Number.parseInt(ne(e,["rev-list","--count","--all"]).stdout.trim(),10)||0,i=ne(e,["for-each-ref","--format=%(refname)%00%(objectname)","refs/heads","refs/tags"]),a=i.stdout.split(`
113
+ `).filter(Boolean).map((m)=>{let[u,f]=m.split("\x00");return{name:u,oid:f}}).filter(({name:m,oid:u})=>/^refs\/(?:heads|tags)\/.+/.test(m)&&/^[0-9a-f]{40,64}$/.test(u)).sort((m,u)=>m.name.localeCompare(u.name)),c=["log","--all",`--max-count=${ut}`,"--pretty=format:@@%H","--name-only"],l=ne(e,[...c,"--",".env",".env.*","*.pem","*.key",".npmrc","*.tfvars"]),p=ne(e,["log","--all",`--max-count=${ut}`,"-G","BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY|npm_[A-Za-z0-9]{30,}|gh[opusr]_[A-Za-z0-9_]{30,}|AKIA[0-9A-Z]{16}|xox[baprs]-[A-Za-z0-9-]{20,}","--pretty=format:@@%H","--name-only"]),d=new Map;for(let m of[...zr(l.stdout,"sensitive-path"),...zr(p.stdout,"secret-pattern")])d.set(`${m.commit}:${m.path}:${m.reason}`,m);return{head:n,branch:s,refs:a,commitCount:o,complete:o<=ut&&a.length<=1000&&i.status===0&&l.status===0&&p.status===0,findings:[...d.values()].slice(0,100)}}async function G(e,t={}){let n=await Jr(Ur(e));if(!(await Lo(n)).isDirectory())throw Error("Import target must be a directory.");let r=await ni(n),s=ri(n,r),{hardMatcher:o,matcher:i}=await si(n),a=[],c=[],l=[],p=[],d=[],m=[],u=t.envFile?qe(Lr(n,Ur(n,t.envFile))):void 0,f=u!==void 0&&u!==""&&u!==".."&&!u.startsWith("../");if(t.envFile&&!f)m.push(`Selected environment file must stay inside the project: ${t.envFile}`);let g=new Map,P=new Map,R=new Map,k=new Map,F=[],H=[],ke=new Map,y=t.maxFiles??Bo,C=t.maxFileBytes??zo,j=t.maxTotalBytes??Do,T=0,q=0,Mn=async(v)=>{let E=await Ho(v,{withFileTypes:!0});E.sort((_,L)=>_.name.localeCompare(L.name));for(let _ of E){let L=qr(v,_.name),I=qe(Lr(n,L));if(_.name===".git"){if(I!==".git")m.push(`Nested Git repository is not supported: ${I}`);continue}let z=await Kr(L),Kn=_.isDirectory()?`${I}/`:I,Et=s.has(I),Jn=!Et&&i.ignores(Kn),vs=!Et&&o.ignores(Kn);if(z.isSymbolicLink()){if(d.push({path:I,reason:"symlink"}),!Jn)m.push(`Symlinks are not imported in this release: ${I}`);continue}if(_.isDirectory()){if(vs)continue;await Mn(L);continue}let Ee=oi(I),Pe=ii(I);if(Jn&&!Ee&&!Pe)continue;if(!_.isFile()){d.push({path:I,reason:"non-regular-file"});continue}if(a.length+c.length+l.length>=y){m.push(`Project exceeds the ${y} file limit.`);return}if(z.size>C){m.push(`File exceeds the ${C} byte limit: ${I}`);continue}if(T+=z.size,T>j){m.push(`Project exceeds the ${j} byte total limit.`);return}let tt=await Qo(L);if(Ee){if(z.size>dt){m.push(`Protected configuration exceeds the ${dt} byte limit: ${I}`);continue}let U=await pt(L);if(q+=U.byteLength,q>we){m.push(`Protected project files exceed the ${we} byte total limit.`);continue}if(l.push({path:I,kind:Ee,size:z.size,sha256:tt}),H.push({path:I,kind:Ee,contentBase64:U.toString("base64")}),Ee==="mcp")p.push(...li(I,U.toString("utf8")));continue}if(Pe){if(z.size>dt){m.push(`Protected file exceeds the ${dt} byte limit: ${I}`);continue}let U=await pt(L);if(q+=U.byteLength,q>we){m.push(`Protected project files exceed the ${we} byte total limit.`);continue}let re=[];if(Pe==="dotenv")try{let nt=Gr(U),ce={};for(let[ee,le]of Object.entries(nt)){if(Je.test(ee)){m.push(`Hlix control-plane environment keys cannot be imported into a project: ${ee}`);continue}ce[ee]=le}g.set(I,ce),re=Object.keys(ce).sort()}catch{m.push(`Could not parse environment file: ${I}`)}else if(ie(I)===".envrc"){let nt=ti(U),ce={},ee=new Set,le=[];for(let[N,ws]of Object.entries(nt.values)){if(Je.test(N)){m.push(`Hlix control-plane environment keys cannot be imported into a project: ${N}`);continue}if(cn.has(N)){F.push(`Ignored ambient runtime assignment in ${I}: ${N}`);continue}ee.add(N),ce[N]=ws}P.set(I,ce);for(let N of nt.dynamicKeys){if(Je.test(N)){m.push(`Hlix control-plane environment keys cannot be imported into a project: ${N}`);continue}if(cn.has(N)){F.push(`Ignored ambient runtime assignment in ${I}: ${N}`);continue}ee.add(N),le.push(N)}if(R.set(I,[...ee].sort()),k.set(I,le.sort()),re=[...ee].sort(),le.length>0)F.push(`Did not execute dynamic .envrc assignments; collect their resolved local values when available: ${le.join(", ")}`)}c.push({path:I,kind:Pe,keys:re,size:z.size,sha256:tt}),H.push({path:I,kind:Pe,contentBase64:U.toString("base64")});continue}if(z.size<=1048576){let U=await pt(L),re=U.toString("utf8");if(ke.set(I,re),Xo.test(re)||Yo.test(I)&&Zo.test(re)){if(q+=U.byteLength,q>we){m.push(`Protected project files exceed the ${we} byte total limit.`);continue}c.push({path:I,kind:"detected-content",keys:[],size:z.size,sha256:tt}),H.push({path:I,kind:"detected-content",contentBase64:U.toString("base64")});continue}}a.push({path:I,size:z.size,sha256:tt,tracked:Et,executable:(z.mode&73)!==0})}};await Mn(n),a.sort((v,E)=>v.path.localeCompare(E.path)),c.sort((v,E)=>v.path.localeCompare(E.path)),l.sort((v,E)=>v.path.localeCompare(E.path)),p.sort((v,E)=>`${v.sourcePath}:${v.name}`.localeCompare(`${E.sourcePath}:${E.name}`));let bt=ci([...g.keys()].sort(),f?u:void 0);if(t.envFile&&f&&!g.has(bt[0]))m.push(`Selected environment file was not found or is not a dotenv file: ${t.envFile}`);let je=new Map;for(let[v,E]of g)for(let _ of Object.keys(E))je.set(_,[...je.get(_)??[],v]);for(let[v,E]of R)for(let _ of E)je.set(_,[...je.get(_)??[],v]);let ms=[...je].filter(([,v])=>v.length>1).map(([v,E])=>({key:v,paths:E.sort()})).sort((v,E)=>v.key.localeCompare(E.key)),W={};for(let v of bt)Object.assign(W,g.get(v)??{});let fs=[...P.keys()].sort((v,E)=>{if(v===".envrc")return 1;if(E===".envrc")return-1;return v.localeCompare(E)}),St=new Set;for(let v of fs){let E=new Set(k.get(v)??[]);for(let _ of R.get(v)??[]){if(E.has(_)){delete W[_],St.add(_);continue}let L=P.get(v)?.[_];if(L!==void 0)W[_]=L;St.delete(_)}}let kt=t.historyMode??"abort_on_findings",Q=di(n,r);if(!Q.complete&&kt!=="preserve")m.push(`Git history scan exceeded ${ut} commits or failed; import requires explicit --history preserve.`);if(Q.findings.length>0&&kt==="abort_on_findings")m.push("Potential secrets exist in Git history. Abort, sanitize the repository, or explicitly use --history preserve.");let Bn=new Set(a.map((v)=>v.path)),gs=await Nr(n,Bn,ke),{observedSecretKeys:hs,...V}=gs;V.warnings.push(...F);let jt=new Set(V.requiredSecretKeys);for(let v of St)jt.add(v);for(let v of p)for(let E of v.envKeys)jt.add(E);V.requiredSecretKeys=[...jt].sort();for(let v of V.requiredSecretKeys){if(Je.test(v)){m.push(`Hlix control-plane environment keys cannot be imported into a project: ${v}`);continue}if(W[v]!==void 0)continue;let E=t.environment?.[v];if(E===void 0){m.push(`${dn}${v}`);continue}W[v]=E}for(let v of hs){if(Je.test(v)){V.warnings.push(`Ignored reserved Hlix control-plane environment reference: ${v}`);continue}if(cn.has(v))continue;if(W[v]!==void 0)continue;let E=t.environment?.[v];if(E===void 0){V.warnings.push(`Observed environment reference has no local value: ${v}`);continue}W[v]=E}V.warnings=[...new Set(V.warnings)].sort();let zn={schemaVersion:Hr,rootName:t.rootName??ie(n),stack:ai(Bn),git:{detected:r,head:Q.head,branch:Q.branch,refs:Q.refs,commitCount:Q.commitCount,historyScanComplete:Q.complete,historyMode:kt},files:a,secretFiles:c,activeEnvFiles:bt,secretKeys:Object.keys(W).sort(),envCollisions:ms,quarantinedResources:l,mcpServers:p,historicalSecretFindings:Q.findings,skipped:d,environment:V,totals:{files:a.length,bytes:a.reduce((v,E)=>v+E.size,0)}},Dn=ln(zn),ys=Dr("sha256").update(Dn).digest("hex");return{root:n,manifest:zn,manifestJson:Dn,manifestSha256:ys,secretValues:W,protectedFiles:H.sort((v,E)=>v.path.localeCompare(E.path)),blocking:[...new Set(m)]}}var pn={name:"init",summary:"Configure a local folder for Hlix",usage:["Usage: hlix init [folder] [--project <id>] [--json]","","Creates .hlix/config.json, .hlix/.gitignore, and .hlixignore.","Project configuration is safe to commit; local revision state is ignored.",""," --project <id> Bind the folder to an existing cloud project (then `hlix pull`)"].join(`
114
+ `),supportsJson:!0,options:["project"],args:{min:0,max:1},async run(e){if(e.args.length>1)throw Error("init accepts at most one folder.");let t=await pi(ui(e.cwd,e.args[0]??".")),n=D({env:e.env,flags:e.flags,cwd:t});if(n.conflict)throw new h("workspace_mismatch",n.conflict);if(!n.workspaceId)throw Error("No workspace selected. Run `hlix auth login --workspace <id>` first.");let r=e.requireClient(t);await r.projects.list();let s=pe(t),o=typeof e.flags.project==="string"?e.flags.project:void 0;if(o&&s?.projectId&&s.projectId!==o)throw new h("workspace_mismatch",`This folder is bound to project ${s.projectId}; refusing to rebind it to ${o}.`);if(o)await r.projects.get(o);let i={...s??{schemaVersion:1,workspaceId:n.workspaceId,apiUrl:n.baseUrl},...o?{projectId:o}:{}};Re(t,i);let a=await G(t,{environment:e.env}),c={root:t,config:i,scan:{files:a.manifest.totals.files,bytes:a.manifest.totals.bytes,secretFiles:a.manifest.secretFiles.map((l)=>l.path),quarantinedResources:a.manifest.quarantinedResources.map((l)=>l.path),blocking:a.blocking}};if(e.json)e.stdout(w(S(pn.name,c)));else if(e.stdout(`Initialized ${t}
111
115
  Project: ${i.projectId??"not imported yet"}
112
116
  Workspace: ${i.workspaceId}
113
117
  `),a.blocking.length)e.stdout(`
114
118
  Review before import:
115
119
  ${a.blocking.map((l)=>`- ${l}`).join(`
116
120
  `)}
117
- `);return 0}};import{createHash as vi}from"node:crypto";import{readFile as wi,realpath as Si}from"node:fs/promises";import{basename as bi,resolve as ki}from"node:path";import{createHash as di}from"node:crypto";import{createReadStream as pi}from"node:fs";import{chmod as pn,copyFile as ui,lstat as Wr,mkdir as Vr,mkdtemp as mi,readdir as fi,rm as un}from"node:fs/promises";import{tmpdir as gi}from"node:os";import{dirname as hi,join as ae}from"node:path";import{spawnSync as Ge}from"node:child_process";function Z(e,t){let n=Ge("git",["-C",e,...t],{encoding:"utf8",maxBuffer:20971520,stdio:["ignore","pipe","pipe"]});if(n.status!==0){let r=n.stderr.trim().split(`
118
- `).at(-1)??"git command failed";throw Error(r)}return n.stdout.trim()}async function Xr(e){let t=di("sha256");for await(let n of pi(e))t.update(n);return t.digest("hex")}async function yi(e){for(let t of await fi(e)){if(t===".git")continue;await un(ae(e,t),{recursive:!0,force:!0})}}async function mt(e){if(e.blocking.length>0)throw Error(`Project scan has blocking findings:
121
+ `);return 0}};import{createHash as Si}from"node:crypto";import{readFile as ki,realpath as ji}from"node:fs/promises";import{basename as Ei,resolve as Pi}from"node:path";import{createHash as mi}from"node:crypto";import{createReadStream as fi}from"node:fs";import{chmod as un,copyFile as gi,lstat as Wr,mkdir as Vr,mkdtemp as hi,readdir as yi,rm as mn}from"node:fs/promises";import{tmpdir as vi}from"node:os";import{dirname as wi,join as ae}from"node:path";import{spawnSync as Ge}from"node:child_process";function Y(e,t){let n=Ge("git",["-C",e,...t],{encoding:"utf8",maxBuffer:20971520,stdio:["ignore","pipe","pipe"]});if(n.status!==0){let r=n.stderr.trim().split(`
122
+ `).at(-1)??"git command failed";throw Error(r)}return n.stdout.trim()}async function Xr(e){let t=mi("sha256");for await(let n of fi(e))t.update(n);return t.digest("hex")}async function bi(e){for(let t of await yi(e)){if(t===".git")continue;await mn(ae(e,t),{recursive:!0,force:!0})}}async function mt(e){if(e.blocking.length>0)throw Error(`Project scan has blocking findings:
119
123
  - ${e.blocking.join(`
120
- - `)}`);let t=await mi(ae(gi(),"hlix-snapshot-"));await pn(t,448);let n=ae(t,"repo"),r=ae(t,"source.git"),s=ae(t,"project.bundle");try{if(e.manifest.git.detected){let d=Ge("git",["clone","--mirror","--no-hardlinks",e.root,r],{encoding:"utf8",stdio:["ignore","pipe","pipe"]});if(d.status!==0)throw Error(d.stderr.trim()||"Could not mirror repository.");let m=new Map(Z(r,["for-each-ref","--format=%(refname)%00%(objectname)","refs/heads","refs/tags"]).split(`
121
- `).filter(Boolean).map((f)=>f.split("\x00",2)));for(let f of e.manifest.git.refs)if(m.get(f.name)!==f.oid)throw Error(`Git ref changed after scan: ${f.name}`);let u=Ge("git",["clone","--no-hardlinks",r,n],{encoding:"utf8",stdio:["ignore","pipe","pipe"]});if(u.status!==0)throw Error(u.stderr.trim()||"Could not create snapshot clone.");if(!e.manifest.git.head)throw Error("Git repository has no HEAD commit.");Z(n,["checkout","-B","main",e.manifest.git.head])}else await Vr(n,{recursive:!0,mode:448}),Z(n,["init","-b","main"]);await yi(n);for(let d of e.manifest.files){let m=ae(e.root,...d.path.split("/")),u=await Wr(m);if(!u.isFile()||u.isSymbolicLink())throw Error(`Source changed after scan: ${d.path}`);if(u.size!==d.size||await Xr(m)!==d.sha256)throw Error(`Source changed after scan: ${d.path}`);let f=ae(n,...d.path.split("/"));await Vr(hi(f),{recursive:!0,mode:493}),await ui(m,f),await pn(f,d.executable?493:420)}Z(n,["config","user.name","Hlix Import"]),Z(n,["config","user.email","import@hlix.ai"]),Z(n,["add","-A"]),Z(n,["commit","--allow-empty","-m","chore(hlix): import snapshot"]);let o=Z(n,["rev-parse","HEAD"]),i=e.manifest.git.refs.filter((d)=>d.name!=="refs/heads/main");if(i.length>0){let d=Ge("git",["-C",n,"update-ref","--stdin"],{encoding:"utf8",input:i.map((m)=>`update ${m.name} ${m.oid}`).join(`
124
+ - `)}`);let t=await hi(ae(vi(),"hlix-snapshot-"));await un(t,448);let n=ae(t,"repo"),r=ae(t,"source.git"),s=ae(t,"project.bundle");try{if(e.manifest.git.detected){let d=Ge("git",["clone","--mirror","--no-hardlinks",e.root,r],{encoding:"utf8",stdio:["ignore","pipe","pipe"]});if(d.status!==0)throw Error(d.stderr.trim()||"Could not mirror repository.");let m=new Map(Y(r,["for-each-ref","--format=%(refname)%00%(objectname)","refs/heads","refs/tags"]).split(`
125
+ `).filter(Boolean).map((f)=>f.split("\x00",2)));for(let f of e.manifest.git.refs)if(m.get(f.name)!==f.oid)throw Error(`Git ref changed after scan: ${f.name}`);let u=Ge("git",["clone","--no-hardlinks",r,n],{encoding:"utf8",stdio:["ignore","pipe","pipe"]});if(u.status!==0)throw Error(u.stderr.trim()||"Could not create snapshot clone.");if(!e.manifest.git.head)throw Error("Git repository has no HEAD commit.");Y(n,["checkout","-B","main",e.manifest.git.head])}else await Vr(n,{recursive:!0,mode:448}),Y(n,["init","-b","main"]);await bi(n);for(let d of e.manifest.files){let m=ae(e.root,...d.path.split("/")),u=await Wr(m);if(!u.isFile()||u.isSymbolicLink())throw Error(`Source changed after scan: ${d.path}`);if(u.size!==d.size||await Xr(m)!==d.sha256)throw Error(`Source changed after scan: ${d.path}`);let f=ae(n,...d.path.split("/"));await Vr(wi(f),{recursive:!0,mode:493}),await gi(m,f),await un(f,d.executable?493:420)}Y(n,["config","user.name","Hlix Import"]),Y(n,["config","user.email","import@hlix.ai"]),Y(n,["add","-A"]),Y(n,["commit","--allow-empty","-m","chore(hlix): import snapshot"]);let o=Y(n,["rev-parse","HEAD"]),i=e.manifest.git.refs.filter((d)=>d.name!=="refs/heads/main");if(i.length>0){let d=Ge("git",["-C",n,"update-ref","--stdin"],{encoding:"utf8",input:i.map((m)=>`update ${m.name} ${m.oid}`).join(`
122
126
  `)+`
123
127
  `,stdio:["pipe","pipe","pipe"]});if(d.status!==0)throw Error(d.stderr.trim()||"Could not recreate the approved Git refs.")}let a=i.map((d)=>d.name),c=Ge("git",["-C",n,"bundle","create",s,"--stdin"],{encoding:"utf8",input:["refs/heads/main",...a].join(`
124
128
  `)+`
125
- `,stdio:["pipe","pipe","pipe"]});if(c.status!==0)throw Error(c.stderr.trim()||"Could not create the approved Git bundle.");Z(n,["bundle","verify",s]),await pn(s,384);let l=(await Wr(s)).size,p=await Xr(s);return{bundlePath:s,bundleSha256:p,bundleSize:l,commitSha:o,dispose:()=>un(t,{recursive:!0,force:!0})}}catch(o){throw await un(t,{recursive:!0,force:!0}),o}}function We(e,t){let n=e[t];return typeof n==="string"&&n.trim()?n.trim():void 0}function ji(e,t){return vi("sha256").update(`project-import-v1\x00${e}\x00${t}`).digest("hex")}function Ei(e){let t=e.manifest.environment.install,n=e.manifest.secretFiles.length+e.manifest.quarantinedResources.length;if(t.length===0&&n===0&&e.manifest.secretKeys.length===0)return null;let r=["Hlix will upload this project and encrypted protected files to your selected workspace."];if(t.length>0)r.push("Detected cloud setup commands:",...t.map((s)=>`- ${s}`));if(e.manifest.secretKeys.length>0)r.push("Project secret keys available to cloud tasks:",...e.manifest.secretKeys.map((s)=>`- ${s}`));if(e.manifest.quarantinedResources.length>0)r.push("Quarantined resources (preserved but not activated):",...e.manifest.quarantinedResources.map((s)=>`- ${s.kind}: ${s.path}`));if(e.manifest.environment.warnings.length>0)r.push("Environment warnings:",...e.manifest.environment.warnings.map((s)=>`- ${s}`));return r.push("Setup runs inside the isolated Coding Workspace and may access project secrets."),r.join(`
129
+ `,stdio:["pipe","pipe","pipe"]});if(c.status!==0)throw Error(c.stderr.trim()||"Could not create the approved Git bundle.");Y(n,["bundle","verify",s]),await un(s,384);let l=(await Wr(s)).size,p=await Xr(s);return{bundlePath:s,bundleSha256:p,bundleSize:l,commitSha:o,dispose:()=>mn(t,{recursive:!0,force:!0})}}catch(o){throw await mn(t,{recursive:!0,force:!0}),o}}function We(e,t){let n=e[t];return typeof n==="string"&&n.trim()?n.trim():void 0}function Ci(e,t){return Si("sha256").update(`project-import-v1\x00${e}\x00${t}`).digest("hex")}function $i(e){let t=e.manifest.environment.install,n=e.manifest.secretFiles.length+e.manifest.quarantinedResources.length;if(t.length===0&&n===0&&e.manifest.secretKeys.length===0)return null;let r=["Hlix will upload this project and encrypted protected files to your selected workspace."];if(t.length>0)r.push("Detected cloud setup commands:",...t.map((s)=>`- ${s}`));if(e.manifest.secretKeys.length>0)r.push("Project secret keys available to cloud tasks:",...e.manifest.secretKeys.map((s)=>`- ${s}`));if(e.manifest.quarantinedResources.length>0)r.push("Quarantined resources (preserved but not activated):",...e.manifest.quarantinedResources.map((s)=>`- ${s.kind}: ${s.path}`));if(e.manifest.environment.warnings.length>0)r.push("Environment warnings:",...e.manifest.environment.warnings.map((s)=>`- ${s}`));return r.push("Setup runs inside the isolated Coding Workspace and may access project secrets."),r.join(`
126
130
  `)}var ft={name:"import",summary:"Import a local project into your Hlix workspace",usage:["Usage: hlix import [folder] [options]","","Options:"," --dry-run Scan and report without uploading"," --env-file <path> Override automatic development dotenv precedence"," --history <mode> abort-on-findings (default) or preserve"," --name <name> Cloud project name (defaults to folder name)"," --stack <stack> Override detected stack"," --yes Approve the reviewed upload and cloud setup"," --json Machine-readable output (never contains secret values)"].join(`
127
- `),supportsJson:!0,options:["dry-run","env-file","history","name","stack","yes"],args:{min:0,max:1},async run(e){if(e.args.length>1)throw Error("import accepts at most one folder.");let t=await Si(ki(e.cwd,e.args[0]??".")),n=K({env:e.env,flags:e.flags,cwd:t});if(n.conflict)throw new h("workspace_mismatch",n.conflict);if(!n.workspaceId||!n.credential)throw new h("workspace_required","No workspace selected. Run `hlix auth login --workspace <id>` first.");let r=pe(t);if(r?.projectId)throw new h("already_imported","This folder is already bound to an Hlix project. Use `hlix push`.");let s=We(e.flags,"history");if(s&&s!=="preserve"&&s!=="abort-on-findings")throw Error("--history must be `abort-on-findings` or `preserve`.");if(!r&&e.flags["dry-run"]!==!0)xe(t,{schemaVersion:1,workspaceId:n.workspaceId,apiUrl:n.baseUrl});let o=await G(t,{...We(e.flags,"env-file")?{envFile:We(e.flags,"env-file")}:{},environment:e.env,historyMode:s==="preserve"?"preserve":"abort_on_findings"});if(e.flags["dry-run"]!==!0&&o.blocking.length===0){let c=Ei(o);if(c&&e.flags.yes!==!0){if(e.json||!e.confirm)throw new h("approval_required","Import needs approval for protected files or cloud setup. Review with `hlix import --dry-run`, then repeat with `--yes`.");if(!await e.confirm(c))throw new h("cancelled","Import cancelled.")}}let i={root:t,name:We(e.flags,"name")??bi(t),stack:We(e.flags,"stack")??o.manifest.stack,files:o.manifest.totals.files,bytes:o.manifest.totals.bytes,activeEnvFiles:o.manifest.activeEnvFiles,secretKeys:o.manifest.secretKeys,protectedFiles:o.manifest.secretFiles.length+o.manifest.quarantinedResources.length,environment:o.manifest.environment,historicalSecretFindings:o.manifest.historicalSecretFindings,quarantinedResources:o.manifest.quarantinedResources,mcpServers:o.manifest.mcpServers,skipped:o.manifest.skipped,blocking:o.blocking,manifestSha256:o.manifestSha256};if(e.flags["dry-run"]===!0){if(e.json)e.stdout(w(S(ft.name,i)));else{let c=[...o.manifest.secretFiles.map((l)=>`${l.kind}: ${l.path}`),...o.manifest.quarantinedResources.map((l)=>`${l.kind}: ${l.path}`)];e.stdout([`Project: ${i.name}`,`Stack: ${i.stack}`,`Files: ${i.files}`,`Bytes: ${i.bytes}`,`Environment confidence: ${i.environment.confidence}`,`History findings: ${i.historicalSecretFindings.length}`,"","Environment evidence:",...i.environment.sources.length?i.environment.sources.map((l)=>`- ${l.kind}: ${l.path}`):["- none detected"],"","Cloud setup commands:",...i.environment.install.length?i.environment.install.map((l)=>`- ${l}`):["- none detected"],"","Required secret keys:",...i.environment.requiredSecretKeys.length?i.environment.requiredSecretKeys.map((l)=>`- ${l}`):["- none detected"],"","Collected secret keys:",...i.secretKeys.length?i.secretKeys.map((l)=>`- ${l}`):["- none detected"],"","Protected and quarantined paths:",...c.length?c.map((l)=>`- ${l}`):["- none"],"","Environment warnings:",...i.environment.warnings.length?i.environment.warnings.map((l)=>`- ${l}`):["- none"],...i.blocking.length?["","Blocking findings:",...i.blocking.map((l)=>`- ${l}`)]:[]].join(`
131
+ `),supportsJson:!0,options:["dry-run","env-file","history","name","stack","yes"],args:{min:0,max:1},async run(e){if(e.args.length>1)throw Error("import accepts at most one folder.");let t=await ji(Pi(e.cwd,e.args[0]??".")),n=D({env:e.env,flags:e.flags,cwd:t});if(n.conflict)throw new h("workspace_mismatch",n.conflict);if(!n.workspaceId||!n.credential)throw new h("workspace_required","No workspace selected. Run `hlix auth login` first.");let r=pe(t);if(r?.projectId)throw new h("already_imported","This folder is already bound to an Hlix project. Use `hlix push`.");let s=We(e.flags,"history");if(s&&s!=="preserve"&&s!=="abort-on-findings")throw Error("--history must be `abort-on-findings` or `preserve`.");if(!r&&e.flags["dry-run"]!==!0)Re(t,{schemaVersion:1,workspaceId:n.workspaceId,apiUrl:n.baseUrl});let o=await G(t,{...We(e.flags,"env-file")?{envFile:We(e.flags,"env-file")}:{},environment:e.env,historyMode:s==="preserve"?"preserve":"abort_on_findings"});if(e.flags["dry-run"]!==!0&&o.blocking.length===0){let c=$i(o);if(c&&e.flags.yes!==!0){if(e.json||!e.confirm)throw new h("approval_required","Import needs approval for protected files or cloud setup. Review with `hlix import --dry-run`, then repeat with `--yes`.");if(!await e.confirm(c))throw new h("cancelled","Import cancelled.")}}let i={root:t,name:We(e.flags,"name")??Ei(t),stack:We(e.flags,"stack")??o.manifest.stack,files:o.manifest.totals.files,bytes:o.manifest.totals.bytes,activeEnvFiles:o.manifest.activeEnvFiles,secretKeys:o.manifest.secretKeys,protectedFiles:o.manifest.secretFiles.length+o.manifest.quarantinedResources.length,environment:o.manifest.environment,historicalSecretFindings:o.manifest.historicalSecretFindings,quarantinedResources:o.manifest.quarantinedResources,mcpServers:o.manifest.mcpServers,skipped:o.manifest.skipped,blocking:o.blocking,manifestSha256:o.manifestSha256};if(e.flags["dry-run"]===!0){if(e.json)e.stdout(w(S(ft.name,i)));else{let c=[...o.manifest.secretFiles.map((l)=>`${l.kind}: ${l.path}`),...o.manifest.quarantinedResources.map((l)=>`${l.kind}: ${l.path}`)];e.stdout([`Project: ${i.name}`,`Stack: ${i.stack}`,`Files: ${i.files}`,`Bytes: ${i.bytes}`,`Environment confidence: ${i.environment.confidence}`,`History findings: ${i.historicalSecretFindings.length}`,"","Environment evidence:",...i.environment.sources.length?i.environment.sources.map((l)=>`- ${l.kind}: ${l.path}`):["- none detected"],"","Cloud setup commands:",...i.environment.install.length?i.environment.install.map((l)=>`- ${l}`):["- none detected"],"","Required secret keys:",...i.environment.requiredSecretKeys.length?i.environment.requiredSecretKeys.map((l)=>`- ${l}`):["- none detected"],"","Collected secret keys:",...i.secretKeys.length?i.secretKeys.map((l)=>`- ${l}`):["- none detected"],"","Protected and quarantined paths:",...c.length?c.map((l)=>`- ${l}`):["- none"],"","Environment warnings:",...i.environment.warnings.length?i.environment.warnings.map((l)=>`- ${l}`):["- none"],...i.blocking.length?["","Blocking findings:",...i.blocking.map((l)=>`- ${l}`)]:[]].join(`
128
132
  `)+`
129
133
  `)}return o.blocking.length?1:0}if(o.blocking.length)throw new h("scan_blocked",`Project scan blocked import:
130
134
  - ${o.blocking.join(`
131
- - `)}`);let a=await mt(o);try{let c=e.requireClient(t),l=await c.imports.create({idempotencyKey:ji(o.manifestSha256,a.bundleSha256),name:i.name,stack:i.stack,defaultBranch:"main",historyMode:o.manifest.git.historyMode,manifest:o.manifest,manifestSha256:o.manifestSha256,bundleSha256:a.bundleSha256,bundleSize:a.bundleSize,commitSha:a.commitSha});if(l.import.status==="pending_upload"){if(!l.upload)throw Error(`Import ${l.import.id} is ${l.import.status} but has no upload target.`);await c.imports.uploadBundle(l.upload,new Blob([Uint8Array.from(await wi(a.bundlePath))]),{onProgress:(f,g)=>{if(!e.json)e.stderr(`Uploading ${f}/${g} bytes\r`)}})}let d=(l.import.status==="ready"?{import:l.import}:await c.imports.finalize(l.import.id,{secrets:o.secretValues,protectedFiles:o.protectedFiles})).import,m=d.projectId??d.requestedProjectId;if(!m||!d.revisionId||!d.generation)throw Error("Import completed without project revision metadata.");xe(t,{schemaVersion:1,projectId:m,workspaceId:n.workspaceId,apiUrl:n.baseUrl}),Re(t,{schemaVersion:1,revisionId:d.revisionId,generation:d.generation,commitSha:a.commitSha,manifestSha256:o.manifestSha256,historyMode:o.manifest.git.historyMode,rootName:o.manifest.rootName});let u={projectId:m,revisionId:d.revisionId,generation:d.generation,commitSha:a.commitSha,files:o.manifest.totals.files,bytes:o.manifest.totals.bytes};if(e.json)e.stdout(w(S(ft.name,u)));else e.stderr(`
135
+ - `)}`);let a=await mt(o);try{let c=e.requireClient(t),l=await c.imports.create({idempotencyKey:Ci(o.manifestSha256,a.bundleSha256),name:i.name,stack:i.stack,defaultBranch:"main",historyMode:o.manifest.git.historyMode,manifest:o.manifest,manifestSha256:o.manifestSha256,bundleSha256:a.bundleSha256,bundleSize:a.bundleSize,commitSha:a.commitSha});if(l.import.status==="pending_upload"){if(!l.upload)throw Error(`Import ${l.import.id} is ${l.import.status} but has no upload target.`);await c.imports.uploadBundle(l.upload,new Blob([Uint8Array.from(await ki(a.bundlePath))]),{onProgress:(f,g)=>{if(!e.json)e.stderr(`Uploading ${f}/${g} bytes\r`)}})}let d=(l.import.status==="ready"?{import:l.import}:await c.imports.finalize(l.import.id,{secrets:o.secretValues,protectedFiles:o.protectedFiles})).import,m=d.projectId??d.requestedProjectId;if(!m||!d.revisionId||!d.generation)throw Error("Import completed without project revision metadata.");Re(t,{schemaVersion:1,projectId:m,workspaceId:n.workspaceId,apiUrl:n.baseUrl}),_e(t,{schemaVersion:1,revisionId:d.revisionId,generation:d.generation,commitSha:a.commitSha,manifestSha256:o.manifestSha256,historyMode:o.manifest.git.historyMode,rootName:o.manifest.rootName});let u={projectId:m,revisionId:d.revisionId,generation:d.generation,commitSha:a.commitSha,files:o.manifest.totals.files,bytes:o.manifest.totals.bytes};if(e.json)e.stdout(w(S(ft.name,u)));else e.stderr(`
132
136
  `),e.stdout(`Imported ${i.name}
133
137
  Project ID: ${m}
134
138
  Revision: ${d.generation}
135
- `);return 0}finally{await a.dispose()}}};var mn={name:"standards",summary:"Show the standards other agent tools left in this folder",usage:["Usage: hlix standards [--cwd <dir>] [--json]","","Reads the instruction files, skills, slash commands, MCP servers and","subagents this project already carries for Claude Code, Cursor, Windsurf,","Gemini, Codex, Cline, Copilot and VS Code, and shows where each came from.","Hlix Code loads all of it at startup; nothing has to be copied or rewritten.","","Server urls, headers and environment values are never printed."].join(`
136
- `),supportsJson:!0,async run(e){let t=Ir(e.cwd,Pr(e.env),{env:e.env});if(e.json)return e.stdout(w(S(mn.name,{instructions:t.instructions.map((n)=>({path:n.path,source:n.source,scope:n.scope,characters:n.content.length,...n.note?{note:n.note}:{}})),skills:t.skills,commands:[...t.commands.map((n)=>({path:n.path,source:n.source,scope:n.scope})),...t.generatedCommands.map((n)=>({path:n.path,source:n.source,scope:n.scope,command:n.name}))],mcpServers:t.mcpServers.map((n)=>({path:n.path,source:n.source,scope:n.scope,name:n.name,transport:"command"in n.config?"stdio":"http"})),subagents:t.subagents.map((n)=>({path:n.path,source:n.source,scope:n.scope,name:n.name,description:n.description,...n.model?{model:n.model}:{}})),skipped:t.skipped}))),0;return e.stdout(Rr(t,e.cwd)),0}};var Pi=(e)=>e instanceof Error?e.message:String(e);async function Ci(e,t,n,r,s){try{let o=await G(t,{historyMode:n,environment:e.env,rootName:r});return{files:o.manifest.totals.files,manifestSha256:o.manifestSha256,changed:s?o.manifestSha256!==s:null,blocking:o.blocking,error:null}}catch(o){return{files:null,manifestSha256:null,changed:null,blocking:[],error:Pi(o)}}}var fn={name:"status",summary:"Show the workspace, folder binding, and local-vs-cloud drift",usage:["Usage: hlix status [--cwd <dir>] [--json]","","Reports the resolved workspace and API with the source that decided each,","whether this folder is bound to a project, and whether the working tree or","the cloud head has moved since the last sync. Every finding is a line in","the output, so the command itself always exits 0; only an argument error","(rejected before it runs) exits 2."].join(`
137
- `),supportsJson:!0,async run(e){let t=K({env:e.env,flags:e.flags,cwd:e.cwd}),n=t.binding,r=n?at(n.root):null,s=n?await Ci(e,n.root,r?.historyMode??"preserve",r?.rootName,r?.manifestSha256):null,o=null;if(n?.config.projectId&&t.credential&&!t.conflict)try{let c=(await e.requireClient().revisions.head(n.config.projectId)).revision;o={revisionId:c.id,generation:c.generation,changed:r?c.id!==r.revisionId||c.generation!==r.generation:null,error:null}}catch(c){o={revisionId:"",generation:0,changed:null,error:Mt(c).code}}let i={cwd:e.cwd,workspace:{id:t.workspaceId,source:t.workspaceSource},api:{baseUrl:t.baseUrl,source:t.baseUrlSource},credential:{present:t.credential!==null,source:t.credentialSource,path:t.credentialPath},conflict:t.conflict,project:n?{root:n.root,projectId:n.config.projectId??null,workspaceId:n.config.workspaceId,apiUrl:n.config.apiUrl}:null,revision:r?{id:r.revisionId,generation:r.generation,commitSha:r.commitSha}:null,local:s,cloud:o};if(e.json)return e.stdout(w(S(fn.name,i))),0;let a=[["folder",e.cwd],["workspace",t.workspaceId?`${t.workspaceId} (from ${t.workspaceSource})`:"none — run `hlix auth login --workspace <id>`"],["api",`${t.baseUrl} (from ${t.baseUrlSource})`],["credential",t.credential?t.credentialSource==="env"?`environment (${t.credential?.sessionToken?"HLIX_SESSION_TOKEN":"HLIX_API_KEY"})`:`file (${t.credentialPath})`:"none — run `hlix auth login`"],["project",n?n.config.projectId??`initialized at ${n.root}, not imported yet`:"none — run `hlix import .` to bind this folder"]];if(r)a.push(["revision",`generation ${r.generation} (${r.revisionId})`]);if(s){if(a.push(["local",s.error?`could not scan: ${s.error}`:s.changed===null?`${s.files} files, no synced base revision`:s.changed?`${s.files} files, modified since the last sync`:`${s.files} files, matches the last sync`]),s.blocking.length>0)a.push(["blocking",s.blocking.join("; ")])}if(o)a.push(["cloud",o.error?`not checked: ${o.error}`:o.changed?`generation ${o.generation} available — run \`hlix pull\``:`generation ${o.generation}, up to date`]);if(t.conflict)a.push(["conflict",t.conflict]);return e.stdout(`${O(a)}
138
- `),0}};import{spawnSync as Zr}from"node:child_process";var gn={name:"terminal",summary:"Open a shell into the project's Coding Workspace",usage:["Usage: hlix terminal [project-id] [--print] [--web] [--json]","","With no id, the project this folder is bound to is used."," --print Show the ssh command and browser url instead of connecting"," --web Open the browser terminal instead of ssh"].join(`
139
- `),supportsJson:!0,options:["print","web"],args:{min:0,max:1},async run(e){let t=e.args[0]??A(e.cwd)?.config.projectId;if(!t)throw new h("missing_argument","A project id is required, or run this inside a folder bound to a project.");let n=await e.requireClient().projects.terminal(t);if(e.json)return e.stdout(w(S(gn.name,n))),n.available?0:1;if(!n.available){let i=n.environmentState?` (environment: ${n.environmentState})`:"";throw new h("not_found",`${n.reason??"Terminal unavailable"}${i}`)}let r=e.flags.print===!0,s=e.flags.web===!0;if(r||s&&!n.webTerminalUrl||!s&&!n.sshCommand)return e.stdout(`${O([["ssh",n.sshCommand??"not available"],["browser",n.webTerminalUrl??"not available"]])}
140
- `),0;if(s){if(Zr(process.platform==="darwin"?"open":"xdg-open",[n.webTerminalUrl],{stdio:"ignore"}).status!==0)e.stdout(`${n.webTerminalUrl}
141
- `);return 0}return Zr("sh",["-c",n.sshCommand],{stdio:"inherit"}).status??1}};import{createHash as Bi}from"node:crypto";import{readFile as zi,realpath as Ki}from"node:fs/promises";import{createHash as $i}from"node:crypto";import{constants as gt}from"node:fs";import{chmod as Yr,copyFile as Ii,lstat as hn,mkdir as xi,mkdtemp as Ri,open as _i,realpath as Ti,rename as Oi,rm as Xe,writeFile as Ai}from"node:fs/promises";import{tmpdir as Fi}from"node:os";import{dirname as ns,join as Y,relative as Ni,resolve as Hi,sep as Qr}from"node:path";import{spawnSync as Li}from"node:child_process";function rs(e){let t=e;if(typeof t==="string")try{t=JSON.parse(t)}catch{return{}}if(!t||typeof t!=="object")return{};let n=t,r=n.git&&typeof n.git==="object"?n.git:{},s=r.historyMode==="preserve"||r.historyMode==="abort_on_findings"?r.historyMode:void 0,o=typeof n.rootName==="string"&&n.rootName.trim()?n.rootName:void 0;return{historyMode:s,rootName:o}}function ss(e){let t=e;if(typeof t==="string")try{t=JSON.parse(t)}catch{return[]}if(!t||typeof t!=="object")return[];let n=t.files;if(!Array.isArray(n))return[];return n.flatMap((r)=>{if(!r||typeof r!=="object")return[];let s=r;return typeof s.path==="string"&&typeof s.sha256==="string"?[{path:s.path,sha256:s.sha256}]:[]})}function Ve(e,t){let n=Li("git",["-C",e,...t],{encoding:"utf8",maxBuffer:52428800,stdio:["ignore","pipe","pipe"]});if(n.status!==0)throw Error(n.stderr.trim().split(`
142
- `).at(-1)??"Git command failed");return n.stdout.trim()}function es(e){return $i("sha256").update(e).digest("hex")}async function yn(e,t){let n=await Ti(e),r=Hi(n,...t.split("/"));if(r!==n&&!r.startsWith(n+Qr))throw Error(`Protected path escapes the project: ${t}`);let s=Ni(n,ns(r)),o=n;for(let i of s.split(Qr).filter(Boolean)){o=Y(o,i);try{let a=await hn(o);if(!a.isDirectory()||a.isSymbolicLink())throw Error(`Protected path crosses a non-directory: ${t}`)}catch(a){if(a.code!=="ENOENT")throw a;await xi(o,{mode:448})}}return r}async function ts(e,t,n){let r=await yn(e,t);try{let i=await hn(r);if(!i.isFile()||i.isSymbolicLink())throw Error(`Refusing to replace non-regular protected file: ${t}`)}catch(i){if(i.code!=="ENOENT")throw i}let s=Y(ns(r),`.hlix-pull-${crypto.randomUUID()}.tmp`),o=await _i(s,gt.O_WRONLY|gt.O_CREAT|gt.O_EXCL|gt.O_NOFOLLOW,384);try{await o.writeFile(n),await o.sync()}finally{await o.close()}try{await Oi(s,r)}catch(i){throw await Xe(s,{force:!0}),i}}async function Ui(e,t){let n=await yn(e,t);try{let r=await hn(n);if(!r.isFile()||r.isSymbolicLink())throw Error(`Refusing to replace non-regular project file: ${t}`)}catch(r){if(r.code!=="ENOENT")throw r}}async function os(e,t,n,r,s){let o=await Ri(Y(Fi(),"hlix-pull-"));await Yr(o,448);let i=Y(o,"project.bundle"),a=Y(o,"checkout");try{let c=Buffer.from(await r.arrayBuffer());if(c.byteLength!==n.bundleSize||es(c)!==n.bundleSha256)throw Error("Downloaded revision bundle failed integrity verification.");if(await Ai(i,c,{mode:384}),Ve(o,["clone","--no-hardlinks","--branch","main",i,a]),Ve(a,["bundle","verify",i]),Ve(a,["rev-parse","HEAD"])!==n.commitSha)throw Error("Downloaded revision bundle does not match the cloud commit.");let l=n.manifest,p=new Map;for(let u of[...l.secretFiles,...l.quarantinedResources])p.set(u.path,u);if(s.files.length!==p.size)throw Error("Cloud protected files do not match the revision manifest.");let d=new Map;for(let u of s.files){let f=p.get(u.path),g=Buffer.from(u.contentBase64,"base64");if(g.toString("base64").replace(/=+$/,"")!==u.contentBase64.replace(/=+$/,"")||!f||f.kind!==u.kind||g.byteLength!==f.size||es(g)!==f.sha256)throw Error(`Cloud protected file failed integrity verification: ${u.path}`);d.set(u.path,g)}let m=new Set([...l.files.map((u)=>u.path),...t.manifest.secretFiles.map((u)=>u.path),...t.manifest.quarantinedResources.map((u)=>u.path),...d.keys()]);for(let u of[...m].sort())await Ui(e,u);for(let[u,f]of d)await ts(a,u,f);if(t.manifest.git.detected){Ve(e,["fetch",i,"refs/heads/main"]),Ve(e,["reset","--hard","FETCH_HEAD"]);let u=new Set(l.files.map((f)=>f.path));for(let f of t.manifest.files)if(!u.has(f.path))await Xe(Y(e,...f.path.split("/")),{force:!0})}else{for(let u of t.manifest.files)await Xe(Y(e,...u.path.split("/")),{force:!0});for(let u of l.files){let f=await yn(e,u.path);await Ii(Y(a,...u.path.split("/")),f),await Yr(f,u.executable?493:420)}}for(let u of[...t.manifest.secretFiles,...t.manifest.quarantinedResources])if(!d.has(u.path))await Xe(Y(e,...u.path.split("/")),{force:!0});for(let[u,f]of d)await ts(e,u,f)}finally{await Xe(o,{recursive:!0,force:!0})}}function ve(e,t,n){let r=new Map(ss(n.manifest).map((c)=>[c.path,c.sha256])),s=new Map(e.manifest.files.map((c)=>[c.path,c.sha256])),o=0,i=0;for(let[c,l]of s){let p=r.get(c);if(p===void 0)o+=1;else if(p!==l)i+=1}let a=0;for(let c of r.keys())if(!s.has(c))a+=1;return{localChanged:!t.manifestSha256||e.manifestSha256!==t.manifestSha256,cloudChanged:n.id!==t.revisionId||n.generation!==t.generation,local:{revisionId:t.revisionId,generation:t.generation},cloud:{revisionId:n.id,generation:n.generation,commitSha:n.commitSha},files:{local:s.size,cloud:r.size,localOnly:o,cloudOnly:a,differing:i}}}function vn(e,t,n){let{localChanged:r,cloudChanged:s}=t;if(e==="push")return s?"conflict":r?"push":"none";if(e==="pull"){if(!s)return"none";return r&&!n?"conflict":"pull"}if(r&&s)return"conflict";return r?"push":s?"pull":"none"}function wn(e,t,n){return e==="pull"&&t.localChanged&&!n}var Mi={push:{push:"Would push the local changes as a new cloud revision.",pull:"",none:"Nothing to push — local matches the last synced revision.",conflict:"Would refuse: the cloud changed since this folder's base revision."},pull:{push:"",pull:"Would replace local files with the cloud revision.",none:"Nothing to pull — the cloud head is the local base revision.",conflict:"Would refuse: local files changed. Re-run with --force to replace them."},sync:{push:"Would push the local changes as a new cloud revision.",pull:"Would pull the cloud revision into this folder.",none:"Already in sync.",conflict:"Would refuse: local and cloud both changed since the last sync."}};function is(e,t,n,r){let s=n.files;return[`${e} --dry-run: ${Mi[e][t]}`,...r?["Requires --yes (or interactive approval) to execute."]:[],"",O([["local",`generation ${n.local.generation} (${n.local.revisionId})${n.localChanged?" — modified":""}`],["cloud",`generation ${n.cloud.generation} (${n.cloud.revisionId})${n.cloudChanged?" — ahead":""}`],["files",`${s.local} local, ${s.cloud} cloud — ${s.localOnly} local-only, ${s.cloudOnly} cloud-only, ${s.differing} differing`]])].join(`
143
- `)}function Di(e,t,n){return Bi("sha256").update(`project-push-v1\x00${e}\x00${t}\x00${n}`).digest("hex")}var Ji={schemaVersion:1,revisionId:"",generation:0,commitSha:""};async function we(e,{allowUnsynced:t=!1}={}){let n=A(e);if(!n?.config.projectId)throw new h("not_initialized","This folder is not bound to an imported Hlix project. Run `hlix import .` first.");let r=at(n.root)??(t?Ji:null);if(!r)throw new h("not_initialized","This folder is bound to a project but has never been pulled. Run `hlix pull` first.");return{root:await Ki(n.root),config:n.config,state:r}}async function Ze(e,t,n,r){let s=await G(e,{historyMode:n,environment:t,rootName:r});if(s.blocking.length>0)throw new h("scan_blocked",`Project scan blocked sync:
139
+ `);return 0}finally{await a.dispose()}}};var fn={name:"standards",summary:"Show the standards other agent tools left in this folder",usage:["Usage: hlix standards [--cwd <dir>] [--json]","","Reads the instruction files, skills, slash commands, MCP servers and","subagents this project already carries for Claude Code, Cursor, Windsurf,","Gemini, Codex, Cline, Copilot and VS Code, and shows where each came from.","Hlix Code loads all of it at startup; nothing has to be copied or rewritten.","","Server urls, headers and environment values are never printed."].join(`
140
+ `),supportsJson:!0,async run(e){let t=Ir(e.cwd,Pr(e.env),{env:e.env});if(e.json)return e.stdout(w(S(fn.name,{instructions:t.instructions.map((n)=>({path:n.path,source:n.source,scope:n.scope,characters:n.content.length,...n.note?{note:n.note}:{}})),skills:t.skills,commands:[...t.commands.map((n)=>({path:n.path,source:n.source,scope:n.scope})),...t.generatedCommands.map((n)=>({path:n.path,source:n.source,scope:n.scope,command:n.name}))],mcpServers:t.mcpServers.map((n)=>({path:n.path,source:n.source,scope:n.scope,name:n.name,transport:"command"in n.config?"stdio":"http"})),subagents:t.subagents.map((n)=>({path:n.path,source:n.source,scope:n.scope,name:n.name,description:n.description,...n.model?{model:n.model}:{}})),skipped:t.skipped}))),0;return e.stdout(Tr(t,e.cwd)),0}};var Ii=(e)=>e instanceof Error?e.message:String(e);async function xi(e,t,n,r,s){try{let o=await G(t,{historyMode:n,environment:e.env,rootName:r});return{files:o.manifest.totals.files,manifestSha256:o.manifestSha256,changed:s?o.manifestSha256!==s:null,blocking:o.blocking,error:null}}catch(o){return{files:null,manifestSha256:null,changed:null,blocking:[],error:Ii(o)}}}var gn={name:"status",summary:"Show the workspace, folder binding, and local-vs-cloud drift",usage:["Usage: hlix status [--cwd <dir>] [--json]","","Reports the resolved workspace and API with the source that decided each,","whether this folder is bound to a project, and whether the working tree or","the cloud head has moved since the last sync. Every finding is a line in","the output, so the command itself always exits 0; only an argument error","(rejected before it runs) exits 2."].join(`
141
+ `),supportsJson:!0,async run(e){let t=D({env:e.env,flags:e.flags,cwd:e.cwd}),n=t.binding,r=n?at(n.root):null,s=n?await xi(e,n.root,r?.historyMode??"preserve",r?.rootName,r?.manifestSha256):null,o=null;if(n?.config.projectId&&t.credential&&!t.conflict)try{let c=(await e.requireClient().revisions.head(n.config.projectId)).revision;o={revisionId:c.id,generation:c.generation,changed:r?c.id!==r.revisionId||c.generation!==r.generation:null,error:null}}catch(c){o={revisionId:"",generation:0,changed:null,error:Bt(c).code}}let i={cwd:e.cwd,workspace:{id:t.workspaceId,source:t.workspaceSource},api:{baseUrl:t.baseUrl,source:t.baseUrlSource},credential:{present:t.credential!==null,source:t.credentialSource,path:t.credentialPath},conflict:t.conflict,project:n?{root:n.root,projectId:n.config.projectId??null,workspaceId:n.config.workspaceId,apiUrl:n.config.apiUrl}:null,revision:r?{id:r.revisionId,generation:r.generation,commitSha:r.commitSha}:null,local:s,cloud:o};if(e.json)return e.stdout(w(S(gn.name,i))),0;let a=[["folder",e.cwd],["workspace",t.workspaceId?`${t.workspaceId} (from ${t.workspaceSource})`:"none — run `hlix auth login --workspace <id>`"],["api",`${t.baseUrl} (from ${t.baseUrlSource})`],["credential",t.credential?t.credentialSource==="env"?`environment (${t.credential?.sessionToken?"HLIX_SESSION_TOKEN":"HLIX_API_KEY"})`:`file (${t.credentialPath})`:"none — run `hlix auth login`"],["project",n?n.config.projectId??`initialized at ${n.root}, not imported yet`:"none — run `hlix import .` to bind this folder"]];if(r)a.push(["revision",`generation ${r.generation} (${r.revisionId})`]);if(s){if(a.push(["local",s.error?`could not scan: ${s.error}`:s.changed===null?`${s.files} files, no synced base revision`:s.changed?`${s.files} files, modified since the last sync`:`${s.files} files, matches the last sync`]),s.blocking.length>0)a.push(["blocking",s.blocking.join("; ")])}if(o)a.push(["cloud",o.error?`not checked: ${o.error}`:o.changed?`generation ${o.generation} available — run \`hlix pull\``:`generation ${o.generation}, up to date`]);if(t.conflict)a.push(["conflict",t.conflict]);return e.stdout(`${O(a)}
142
+ `),0}};import{spawnSync as Yr}from"node:child_process";var hn={name:"terminal",summary:"Open a shell into the project's Coding Workspace",usage:["Usage: hlix terminal [project-id] [--print] [--web] [--json]","","With no id, the project this folder is bound to is used."," --print Show the ssh command and browser url instead of connecting"," --web Open the browser terminal instead of ssh"].join(`
143
+ `),supportsJson:!0,options:["print","web"],args:{min:0,max:1},async run(e){let t=e.args[0]??A(e.cwd)?.config.projectId;if(!t)throw new h("missing_argument","A project id is required, or run this inside a folder bound to a project.");let n=await e.requireClient().projects.terminal(t);if(e.json)return e.stdout(w(S(hn.name,n))),n.available?0:1;if(!n.available){let i=n.environmentState?` (environment: ${n.environmentState})`:"";throw new h("not_found",`${n.reason??"Terminal unavailable"}${i}`)}let r=e.flags.print===!0,s=e.flags.web===!0;if(r||s&&!n.webTerminalUrl||!s&&!n.sshCommand)return e.stdout(`${O([["ssh",n.sshCommand??"not available"],["browser",n.webTerminalUrl??"not available"]])}
144
+ `),0;if(s){if(Yr(process.platform==="darwin"?"open":"xdg-open",[n.webTerminalUrl],{stdio:"ignore"}).status!==0)e.stdout(`${n.webTerminalUrl}
145
+ `);return 0}return Yr("sh",["-c",n.sshCommand],{stdio:"inherit"}).status??1}};import{createHash as Ki}from"node:crypto";import{readFile as Ji,realpath as qi}from"node:fs/promises";import{createHash as Ti}from"node:crypto";import{constants as gt}from"node:fs";import{chmod as Zr,copyFile as Ri,lstat as yn,mkdir as _i,mkdtemp as Oi,open as Ai,realpath as Fi,rename as Ni,rm as Xe,writeFile as Hi}from"node:fs/promises";import{tmpdir as Li}from"node:os";import{dirname as ns,join as Z,relative as Ui,resolve as Mi,sep as Qr}from"node:path";import{spawnSync as Bi}from"node:child_process";function rs(e){let t=e;if(typeof t==="string")try{t=JSON.parse(t)}catch{return{}}if(!t||typeof t!=="object")return{};let n=t,r=n.git&&typeof n.git==="object"?n.git:{},s=r.historyMode==="preserve"||r.historyMode==="abort_on_findings"?r.historyMode:void 0,o=typeof n.rootName==="string"&&n.rootName.trim()?n.rootName:void 0;return{historyMode:s,rootName:o}}function ss(e){let t=e;if(typeof t==="string")try{t=JSON.parse(t)}catch{return[]}if(!t||typeof t!=="object")return[];let n=t.files;if(!Array.isArray(n))return[];return n.flatMap((r)=>{if(!r||typeof r!=="object")return[];let s=r;return typeof s.path==="string"&&typeof s.sha256==="string"?[{path:s.path,sha256:s.sha256}]:[]})}function Ve(e,t){let n=Bi("git",["-C",e,...t],{encoding:"utf8",maxBuffer:52428800,stdio:["ignore","pipe","pipe"]});if(n.status!==0)throw Error(n.stderr.trim().split(`
146
+ `).at(-1)??"Git command failed");return n.stdout.trim()}function es(e){return Ti("sha256").update(e).digest("hex")}async function vn(e,t){let n=await Fi(e),r=Mi(n,...t.split("/"));if(r!==n&&!r.startsWith(n+Qr))throw Error(`Protected path escapes the project: ${t}`);let s=Ui(n,ns(r)),o=n;for(let i of s.split(Qr).filter(Boolean)){o=Z(o,i);try{let a=await yn(o);if(!a.isDirectory()||a.isSymbolicLink())throw Error(`Protected path crosses a non-directory: ${t}`)}catch(a){if(a.code!=="ENOENT")throw a;await _i(o,{mode:448})}}return r}async function ts(e,t,n){let r=await vn(e,t);try{let i=await yn(r);if(!i.isFile()||i.isSymbolicLink())throw Error(`Refusing to replace non-regular protected file: ${t}`)}catch(i){if(i.code!=="ENOENT")throw i}let s=Z(ns(r),`.hlix-pull-${crypto.randomUUID()}.tmp`),o=await Ai(s,gt.O_WRONLY|gt.O_CREAT|gt.O_EXCL|gt.O_NOFOLLOW,384);try{await o.writeFile(n),await o.sync()}finally{await o.close()}try{await Ni(s,r)}catch(i){throw await Xe(s,{force:!0}),i}}async function zi(e,t){let n=await vn(e,t);try{let r=await yn(n);if(!r.isFile()||r.isSymbolicLink())throw Error(`Refusing to replace non-regular project file: ${t}`)}catch(r){if(r.code!=="ENOENT")throw r}}async function os(e,t,n,r,s){let o=await Oi(Z(Li(),"hlix-pull-"));await Zr(o,448);let i=Z(o,"project.bundle"),a=Z(o,"checkout");try{let c=Buffer.from(await r.arrayBuffer());if(c.byteLength!==n.bundleSize||es(c)!==n.bundleSha256)throw Error("Downloaded revision bundle failed integrity verification.");if(await Hi(i,c,{mode:384}),Ve(o,["clone","--no-hardlinks","--branch","main",i,a]),Ve(a,["bundle","verify",i]),Ve(a,["rev-parse","HEAD"])!==n.commitSha)throw Error("Downloaded revision bundle does not match the cloud commit.");let l=n.manifest,p=new Map;for(let u of[...l.secretFiles,...l.quarantinedResources])p.set(u.path,u);if(s.files.length!==p.size)throw Error("Cloud protected files do not match the revision manifest.");let d=new Map;for(let u of s.files){let f=p.get(u.path),g=Buffer.from(u.contentBase64,"base64");if(g.toString("base64").replace(/=+$/,"")!==u.contentBase64.replace(/=+$/,"")||!f||f.kind!==u.kind||g.byteLength!==f.size||es(g)!==f.sha256)throw Error(`Cloud protected file failed integrity verification: ${u.path}`);d.set(u.path,g)}let m=new Set([...l.files.map((u)=>u.path),...t.manifest.secretFiles.map((u)=>u.path),...t.manifest.quarantinedResources.map((u)=>u.path),...d.keys()]);for(let u of[...m].sort())await zi(e,u);for(let[u,f]of d)await ts(a,u,f);if(t.manifest.git.detected){Ve(e,["fetch",i,"refs/heads/main"]),Ve(e,["reset","--hard","FETCH_HEAD"]);let u=new Set(l.files.map((f)=>f.path));for(let f of t.manifest.files)if(!u.has(f.path))await Xe(Z(e,...f.path.split("/")),{force:!0})}else{for(let u of t.manifest.files)await Xe(Z(e,...u.path.split("/")),{force:!0});for(let u of l.files){let f=await vn(e,u.path);await Ri(Z(a,...u.path.split("/")),f),await Zr(f,u.executable?493:420)}}for(let u of[...t.manifest.secretFiles,...t.manifest.quarantinedResources])if(!d.has(u.path))await Xe(Z(e,...u.path.split("/")),{force:!0});for(let[u,f]of d)await ts(e,u,f)}finally{await Xe(o,{recursive:!0,force:!0})}}function be(e,t,n){let r=new Map(ss(n.manifest).map((c)=>[c.path,c.sha256])),s=new Map(e.manifest.files.map((c)=>[c.path,c.sha256])),o=0,i=0;for(let[c,l]of s){let p=r.get(c);if(p===void 0)o+=1;else if(p!==l)i+=1}let a=0;for(let c of r.keys())if(!s.has(c))a+=1;return{localChanged:!t.manifestSha256||e.manifestSha256!==t.manifestSha256,cloudChanged:n.id!==t.revisionId||n.generation!==t.generation,local:{revisionId:t.revisionId,generation:t.generation},cloud:{revisionId:n.id,generation:n.generation,commitSha:n.commitSha},files:{local:s.size,cloud:r.size,localOnly:o,cloudOnly:a,differing:i}}}function wn(e,t,n){let{localChanged:r,cloudChanged:s}=t;if(e==="push")return s?"conflict":r?"push":"none";if(e==="pull"){if(!s)return"none";return r&&!n?"conflict":"pull"}if(r&&s)return"conflict";return r?"push":s?"pull":"none"}function bn(e,t,n){return e==="pull"&&t.localChanged&&!n}var Di={push:{push:"Would push the local changes as a new cloud revision.",pull:"",none:"Nothing to push — local matches the last synced revision.",conflict:"Would refuse: the cloud changed since this folder's base revision."},pull:{push:"",pull:"Would replace local files with the cloud revision.",none:"Nothing to pull — the cloud head is the local base revision.",conflict:"Would refuse: local files changed. Re-run with --force to replace them."},sync:{push:"Would push the local changes as a new cloud revision.",pull:"Would pull the cloud revision into this folder.",none:"Already in sync.",conflict:"Would refuse: local and cloud both changed since the last sync."}};function is(e,t,n,r){let s=n.files;return[`${e} --dry-run: ${Di[e][t]}`,...r?["Requires --yes (or interactive approval) to execute."]:[],"",O([["local",`generation ${n.local.generation} (${n.local.revisionId})${n.localChanged?" — modified":""}`],["cloud",`generation ${n.cloud.generation} (${n.cloud.revisionId})${n.cloudChanged?" — ahead":""}`],["files",`${s.local} local, ${s.cloud} cloud — ${s.localOnly} local-only, ${s.cloudOnly} cloud-only, ${s.differing} differing`]])].join(`
147
+ `)}function Gi(e,t,n){return Ki("sha256").update(`project-push-v1\x00${e}\x00${t}\x00${n}`).digest("hex")}var Wi={schemaVersion:1,revisionId:"",generation:0,commitSha:""};async function Se(e,{allowUnsynced:t=!1}={}){let n=A(e);if(!n?.config.projectId)throw new h("not_initialized","This folder is not bound to an imported Hlix project. Run `hlix import .` first.");let r=at(n.root)??(t?Wi:null);if(!r)throw new h("not_initialized","This folder is bound to a project but has never been pulled. Run `hlix pull` first.");return{root:await qi(n.root),config:n.config,state:r}}async function Ye(e,t,n,r){let s=await G(e,{historyMode:n,environment:t,rootName:r});if(s.blocking.length>0)throw new h("scan_blocked",`Project scan blocked sync:
144
148
  - ${s.blocking.join(`
145
- - `)}`);return s}async function Sn(e,t,n,r){let{state:s,config:o}=await we(r,{allowUnsynced:n==="pull"}),i=e.requireClient(),[a,c]=await Promise.all([Ze(r,e.env,s.historyMode??"preserve",s.rootName),i.revisions.head(o.projectId)]),l=ve(a,s,c.revision),p=vn(n,l,e.flags.force===!0),d=wn(p,l,e.flags.yes===!0);if(e.json)e.stdout(w(S(t,{dryRun:!0,action:p,approvalRequired:d,...l})));else e.stdout(`${is(n,p,l,d)}
146
- `);return p==="conflict"?1:0}async function qi(e,t){if(e.flags.yes===!0)return;if(e.json||!e.confirm)throw new h("approval_required","`pull --force` replaces local files. Review with `hlix pull --dry-run`, then repeat with `--yes`.");let n=[`hlix pull --force will replace this folder with cloud revision ${t.cloud.generation}.`,`Local-only files to delete: ${t.files.localOnly}`,`Files to replace with the cloud copy: ${t.files.differing}`,"Local changes that were never pushed cannot be recovered by Hlix."].join(`
147
- `);if(!await e.confirm(n))throw new h("cancelled","Pull cancelled.")}async function as(e,t,n,r){let{state:s,config:o}=await we(e),i=t.requireClient(),a=s.historyMode??"preserve",c=n??await Ze(e,t.env,a,s.rootName),l=r??(await i.revisions.head(o.projectId)).revision;if(l.id!==s.revisionId||l.generation!==s.generation)throw new h("conflict","Cloud changed since the local base. Run `hlix pull` or resolve with `hlix sync`.");if(s.manifestSha256&&c.manifestSha256===s.manifestSha256)return{action:"none",revisionId:s.revisionId,generation:s.generation};let p=await mt(c);try{let d=await i.revisions.createUpload(o.projectId,{idempotencyKey:Di(s.revisionId,c.manifestSha256,p.bundleSha256),expectedRevisionId:s.revisionId,expectedGeneration:s.generation,manifest:c.manifest,manifestSha256:c.manifestSha256,bundleSha256:p.bundleSha256,bundleSize:p.bundleSize,commitSha:p.commitSha});if(d.revisionUpload.status==="pending_upload"){if(!d.upload)throw Error("Revision upload has no bundle target.");await i.revisions.uploadBundle(d.upload,new Blob([Uint8Array.from(await zi(p.bundlePath))]),{onProgress:(u,f)=>{if(!t.json)t.stderr(`Uploading ${u}/${f} bytes\r`)}})}let m=await i.revisions.finalize(o.projectId,d.revisionUpload.id,{secrets:c.secretValues,protectedFiles:c.protectedFiles});if(!m.revision)throw Error("Revision finalized without head metadata.");return Re(e,{schemaVersion:1,revisionId:m.revision.id,generation:m.revision.generation,commitSha:m.revision.commitSha,manifestSha256:m.revision.manifestSha256,historyMode:a,rootName:s.rootName??c.manifest.rootName}),{action:"push",...m.revision}}finally{await p.dispose()}}async function cs(e,t,n,r,s){let{state:o,config:i}=await we(e,{allowUnsynced:!0}),a=t.requireClient(),c=o.historyMode??"preserve",l=r??await Ze(e,t.env,c,o.rootName),p=s??(await a.revisions.head(i.projectId)).revision;if(p.id===o.revisionId&&p.generation===o.generation)return{action:"none",revisionId:o.revisionId,generation:o.generation};let d=o.manifestSha256?l.manifestSha256!==o.manifestSha256:(()=>{let{files:k}=ve(l,o,p);return k.localOnly+k.differing>0})();if(d&&!n)throw new h("conflict","Local files changed since the last sync. Push them, or use `hlix pull --force` to replace them.");if(d)await qi(t,ve(l,o,p));let[m,u]=await Promise.all([a.revisions.downloadBundle(i.projectId,p.id),a.revisions.protectedFiles(i.projectId)]);await os(e,l,p,m,u);let f=rs(p.manifest),g=f.historyMode??c,P=f.rootName??o.rootName??l.manifest.rootName,_=await Ze(e,t.env,g,P);return Re(e,{schemaVersion:1,revisionId:p.id,generation:p.generation,commitSha:p.commitSha,manifestSha256:_.manifestSha256,historyMode:g,rootName:P}),{action:"pull",revisionId:p.id,generation:p.generation,commitSha:p.commitSha}}function bn(e,t,n){if(e.json)e.stdout(w(S(t,n)));else if("action"in n&&n.action==="none")e.stdout(`Already in sync.
149
+ - `)}`);return s}async function Sn(e,t,n,r){let{state:s,config:o}=await Se(r,{allowUnsynced:n==="pull"}),i=e.requireClient(),[a,c]=await Promise.all([Ye(r,e.env,s.historyMode??"preserve",s.rootName),i.revisions.head(o.projectId)]),l=be(a,s,c.revision),p=wn(n,l,e.flags.force===!0),d=bn(p,l,e.flags.yes===!0);if(e.json)e.stdout(w(S(t,{dryRun:!0,action:p,approvalRequired:d,...l})));else e.stdout(`${is(n,p,l,d)}
150
+ `);return p==="conflict"?1:0}async function Vi(e,t){if(e.flags.yes===!0)return;if(e.json||!e.confirm)throw new h("approval_required","`pull --force` replaces local files. Review with `hlix pull --dry-run`, then repeat with `--yes`.");let n=[`hlix pull --force will replace this folder with cloud revision ${t.cloud.generation}.`,`Local-only files to delete: ${t.files.localOnly}`,`Files to replace with the cloud copy: ${t.files.differing}`,"Local changes that were never pushed cannot be recovered by Hlix."].join(`
151
+ `);if(!await e.confirm(n))throw new h("cancelled","Pull cancelled.")}async function as(e,t,n,r){let{state:s,config:o}=await Se(e),i=t.requireClient(),a=s.historyMode??"preserve",c=n??await Ye(e,t.env,a,s.rootName),l=r??(await i.revisions.head(o.projectId)).revision;if(l.id!==s.revisionId||l.generation!==s.generation)throw new h("conflict","Cloud changed since the local base. Run `hlix pull` or resolve with `hlix sync`.");if(s.manifestSha256&&c.manifestSha256===s.manifestSha256)return{action:"none",revisionId:s.revisionId,generation:s.generation};let p=await mt(c);try{let d=await i.revisions.createUpload(o.projectId,{idempotencyKey:Gi(s.revisionId,c.manifestSha256,p.bundleSha256),expectedRevisionId:s.revisionId,expectedGeneration:s.generation,manifest:c.manifest,manifestSha256:c.manifestSha256,bundleSha256:p.bundleSha256,bundleSize:p.bundleSize,commitSha:p.commitSha});if(d.revisionUpload.status==="pending_upload"){if(!d.upload)throw Error("Revision upload has no bundle target.");await i.revisions.uploadBundle(d.upload,new Blob([Uint8Array.from(await Ji(p.bundlePath))]),{onProgress:(u,f)=>{if(!t.json)t.stderr(`Uploading ${u}/${f} bytes\r`)}})}let m=await i.revisions.finalize(o.projectId,d.revisionUpload.id,{secrets:c.secretValues,protectedFiles:c.protectedFiles});if(!m.revision)throw Error("Revision finalized without head metadata.");return _e(e,{schemaVersion:1,revisionId:m.revision.id,generation:m.revision.generation,commitSha:m.revision.commitSha,manifestSha256:m.revision.manifestSha256,historyMode:a,rootName:s.rootName??c.manifest.rootName}),{action:"push",...m.revision}}finally{await p.dispose()}}async function cs(e,t,n,r,s){let{state:o,config:i}=await Se(e,{allowUnsynced:!0}),a=t.requireClient(),c=o.historyMode??"preserve",l=r??await Ye(e,t.env,c,o.rootName),p=s??(await a.revisions.head(i.projectId)).revision;if(p.id===o.revisionId&&p.generation===o.generation)return{action:"none",revisionId:o.revisionId,generation:o.generation};let d=o.manifestSha256?l.manifestSha256!==o.manifestSha256:(()=>{let{files:k}=be(l,o,p);return k.localOnly+k.differing>0})();if(d&&!n)throw new h("conflict","Local files changed since the last sync. Push them, or use `hlix pull --force` to replace them.");if(d)await Vi(t,be(l,o,p));let[m,u]=await Promise.all([a.revisions.downloadBundle(i.projectId,p.id),a.revisions.protectedFiles(i.projectId)]);await os(e,l,p,m,u);let f=rs(p.manifest),g=f.historyMode??c,P=f.rootName??o.rootName??l.manifest.rootName,R=await Ye(e,t.env,g,P);return _e(e,{schemaVersion:1,revisionId:p.id,generation:p.generation,commitSha:p.commitSha,manifestSha256:R.manifestSha256,historyMode:g,rootName:P}),{action:"pull",revisionId:p.id,generation:p.generation,commitSha:p.commitSha}}function kn(e,t,n){if(e.json)e.stdout(w(S(t,n)));else if("action"in n&&n.action==="none")e.stdout(`Already in sync.
148
152
  `);else e.stdout(`${String("action"in n?n.action:"sync")} complete.
149
- `)}var ht={name:"push",summary:"Push local changes as an immutable cloud revision",usage:"Usage: hlix push [--dry-run] [--json]",supportsJson:!0,options:["dry-run"],async run(e){if(e.args.length)throw Error("push accepts no positional arguments.");let{root:t}=await we(e.cwd);if(e.flags["dry-run"]===!0)return Sn(e,ht.name,"push",t);return bn(e,ht.name,await as(t,e)),0}},yt={name:"pull",summary:"Pull the cloud head into the local project",usage:["Usage: hlix pull [--force] [--yes] [--dry-run] [--json]",""," --force Replace local changes with the cloud revision"," --yes Skip the confirmation --force otherwise requires"," --dry-run Report the divergence and change nothing"].join(`
150
- `),supportsJson:!0,options:["force","yes","dry-run"],async run(e){if(e.args.length)throw Error("pull accepts no positional arguments.");let{root:t}=await we(e.cwd,{allowUnsynced:!0});if(e.flags["dry-run"]===!0)return Sn(e,yt.name,"pull",t);return bn(e,yt.name,await cs(t,e,e.flags.force===!0)),0}},vt={name:"sync",summary:"Reconcile local and cloud changes without guessing conflicts",usage:"Usage: hlix sync [--dry-run] [--json]",supportsJson:!0,options:["dry-run"],async run(e){if(e.args.length)throw Error("sync accepts no positional arguments.");let{root:t,state:n,config:r}=await we(e.cwd);if(e.flags["dry-run"]===!0)return Sn(e,vt.name,"sync",t);let s=e.requireClient(),[o,i]=await Promise.all([Ze(t,e.env,n.historyMode??"preserve",n.rootName),s.revisions.head(r.projectId)]),a=i.revision,c=ve(o,n,a);if(c.localChanged&&c.cloudChanged)throw new h("conflict","Both local and cloud changed since the last sync. Pull or push explicitly after reviewing the conflict.");let l=c.localChanged?await as(t,e,o,a):c.cloudChanged?await cs(t,e,!1,o,a):{action:"none",revisionId:n.revisionId,generation:n.generation};return bn(e,vt.name,l),0}};import{lstat as ls,readFile as Gi,realpath as Wi}from"node:fs/promises";import{basename as kn,dirname as Vi,extname as Xi,join as Zi,parse as ds,resolve as jn}from"node:path";function Ye(e,t){let n=e.flags[t];return typeof n==="string"&&n.trim()?n.trim():void 0}function En(e){let t=A(e);if(!t?.config.projectId)throw new h("not_initialized","This folder is not bound to an Hlix project. Run `hlix import .` first.");return{root:t.root,projectId:t.config.projectId}}async function Pn(e,t){let n=await ls(e);if(n.isSymbolicLink()||!n.isFile())throw Error(`Refusing to import a non-regular file: ${e}`);if(n.size>t)throw Error(`Import file exceeds ${t} bytes: ${e}`);return{path:await Wi(e),content:await Gi(e,"utf8")}}function Cn(e,t,n,r){if(e.json)e.stdout(w(S(t,n)));else e.stdout(`${r}
151
- `)}var $n={name:"skill import",summary:"Activate a local skill for the bound cloud project",usage:"Usage: hlix skill import <SKILL.md|folder> [--name <slug>] [--json]",supportsJson:!0,options:["name"],args:{min:1,max:1},async run(e){if(e.args.length!==1)throw Error("skill import requires one file or folder.");let t=En(e.cwd),n=jn(e.cwd,e.args[0]),r=await ls(n);if(r.isSymbolicLink())throw Error(`Refusing to import a symlink: ${n}`);let s=r.isDirectory()?Zi(n,"SKILL.md"):n,o=await Pn(s,200000),i=r.isDirectory()?kn(n):kn(s)==="SKILL.md"?kn(Vi(s)):ds(s).name,a=Ye(e,"name")??i;if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(a))throw Error("Skill name must be a lowercase kebab-case slug.");let c=await e.requireClient().resources.importSkill(t.projectId,{slug:a,content:o.content});return Cn(e,$n.name,c.skill,`Imported skill ${a}`),0}},In={name:"agent import",summary:"Create a project-scoped agent from a local Markdown brief",usage:"Usage: hlix agent import <markdown-file> [--name <name>] [--runtime <runtime>] [--duty <duty>] [--profile <profile>] [--json]",supportsJson:!0,options:["name","runtime","duty","profile"],args:{min:1,max:1},async run(e){if(e.args.length!==1)throw Error("agent import requires one Markdown file.");let t=En(e.cwd),n=jn(e.cwd,e.args[0]);if(![".md",".mdx"].includes(Xi(n).toLowerCase()))throw Error("Agent imports must be Markdown files.");let r=await Pn(n,20000),s=Ye(e,"runtime")??"hlix";if(!["claude-code","codex","cursor-agent","hlix"].includes(s))throw Error("--runtime must be claude-code, codex, cursor-agent, or hlix.");let o=Ye(e,"duty")??"executor";if(o!=="executor"&&o!=="intake")throw Error("--duty must be executor or intake.");let i=Ye(e,"name")??ds(n).name.replace(/[-_]+/g," "),a=await e.requireClient().resources.importAgent(t.projectId,{name:i,instructions:r.content,runtimeKind:s,duty:o});return Cn(e,In.name,a.agent,a.agent.duty==="intake"?`Imported agent ${a.agent.name} as this project's intake agent`:`Imported agent ${a.agent.name}`),0}},xn={name:"mcp import",summary:"Explicitly activate one validated local MCP server",usage:"Usage: hlix mcp import <.mcp.json> [--server <name>] [--allow-stdio] [--json]",supportsJson:!0,options:["server","allow-stdio"],args:{min:1,max:1},async run(e){if(e.args.length!==1)throw Error("mcp import requires one MCP JSON file.");let t=En(e.cwd),n=await Pn(jn(e.cwd,e.args[0]),200000),r;try{r=JSON.parse(n.content)}catch{throw Error("MCP config is not valid JSON.")}let s=Object.entries(r.mcpServers??{});if(s.length===0)throw Error("MCP config contains no servers.");let o=Ye(e,"server");if(!o&&s.length>1)throw Error("MCP config contains multiple servers; select one with --server <name>.");let i=o?s.find(([g])=>g===o):s[0];if(!i)throw Error(`MCP server not found: ${o}`);let[a,c]=i,l=c.type==="http"||c.type==="sse"?c.type:typeof c.command==="string"?"stdio":typeof c.url==="string"?"http":null;if(!l)throw Error(`MCP server ${a} has no supported transport.`);if(l==="stdio"&&e.flags["allow-stdio"]!==!0)throw Error("Stdio MCP servers execute a local command in the cloud; repeat with --allow-stdio.");let p=c.env&&typeof c.env==="object"&&!Array.isArray(c.env)?c.env:{},d=c.headers&&typeof c.headers==="object"&&!Array.isArray(c.headers)?c.headers:{};if(Object.values(d).some((g)=>typeof g!=="string"))throw Error(`MCP server ${a} headers must be strings.`);let m=Object.values(d).flatMap((g)=>[...g.matchAll(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g)].map((P)=>P[1]));if(Object.keys(d).length>0&&m.length===0)throw Error("MCP remote headers must use ${KEY} placeholders; literal credentials are refused.");let u=/^(?:(?:Bearer|Basic|Token) )?\$\{[A-Za-z_][A-Za-z0-9_]*\}$/i;if(Object.values(d).some((g)=>!u.test(g)))throw Error("MCP remote headers must be ${KEY} or an approved auth scheme followed by ${KEY}.");let f=await e.requireClient().resources.importMcp(t.projectId,{name:a,transport:l,...typeof c.command==="string"?{command:c.command}:{},...Array.isArray(c.args)&&c.args.every((g)=>typeof g==="string")?{args:c.args}:{},...typeof c.url==="string"?{url:c.url}:{},...Object.keys(d).length>0?{headers:d}:{},envKeys:[...new Set([...Object.keys(p),...m])].sort()});return Cn(e,xn.name,f.mcpServer,`Imported MCP server ${a}`),0}};import{spawnSync as Yi}from"node:child_process";import{chmod as Qi,realpath as ea,writeFile as ta}from"node:fs/promises";import{basename as na,dirname as ra,relative as sa,resolve as us,sep as oa}from"node:path";var ps=64;function et(e){let t=A(e.cwd),r=(typeof e.flags.project==="string"?e.flags.project:void 0)??t?.config.projectId;if(!r)throw new h("not_initialized","This folder is not bound to a Hlix project. Run `hlix import .`, or pass --project <id>.");return{projectId:r,root:t?.root??e.cwd}}var Qe=(e,t)=>typeof e[t]==="string"?e[t]:void 0,Rn={name:"secrets list",summary:"Show every secret the project holds, masked, with its source file",usage:["Usage: hlix secrets list [--project <id>] [--json]","","One row per (key, source file). Values are masked to their last four","characters and there is no flag that unmasks them — `hlix secrets export`","is the one command that returns plaintext, and it is audited."].join(`
153
+ `)}var ht={name:"push",summary:"Push local changes as an immutable cloud revision",usage:"Usage: hlix push [--dry-run] [--json]",supportsJson:!0,options:["dry-run"],async run(e){if(e.args.length)throw Error("push accepts no positional arguments.");let{root:t}=await Se(e.cwd);if(e.flags["dry-run"]===!0)return Sn(e,ht.name,"push",t);return kn(e,ht.name,await as(t,e)),0}},yt={name:"pull",summary:"Pull the cloud head into the local project",usage:["Usage: hlix pull [--force] [--yes] [--dry-run] [--json]",""," --force Replace local changes with the cloud revision"," --yes Skip the confirmation --force otherwise requires"," --dry-run Report the divergence and change nothing"].join(`
154
+ `),supportsJson:!0,options:["force","yes","dry-run"],async run(e){if(e.args.length)throw Error("pull accepts no positional arguments.");let{root:t}=await Se(e.cwd,{allowUnsynced:!0});if(e.flags["dry-run"]===!0)return Sn(e,yt.name,"pull",t);return kn(e,yt.name,await cs(t,e,e.flags.force===!0)),0}},vt={name:"sync",summary:"Reconcile local and cloud changes without guessing conflicts",usage:"Usage: hlix sync [--dry-run] [--json]",supportsJson:!0,options:["dry-run"],async run(e){if(e.args.length)throw Error("sync accepts no positional arguments.");let{root:t,state:n,config:r}=await Se(e.cwd);if(e.flags["dry-run"]===!0)return Sn(e,vt.name,"sync",t);let s=e.requireClient(),[o,i]=await Promise.all([Ye(t,e.env,n.historyMode??"preserve",n.rootName),s.revisions.head(r.projectId)]),a=i.revision,c=be(o,n,a);if(c.localChanged&&c.cloudChanged)throw new h("conflict","Both local and cloud changed since the last sync. Pull or push explicitly after reviewing the conflict.");let l=c.localChanged?await as(t,e,o,a):c.cloudChanged?await cs(t,e,!1,o,a):{action:"none",revisionId:n.revisionId,generation:n.generation};return kn(e,vt.name,l),0}};import{lstat as ls,readFile as Xi,realpath as Yi}from"node:fs/promises";import{basename as jn,dirname as Zi,extname as Qi,join as ea,parse as ds,resolve as En}from"node:path";function Ze(e,t){let n=e.flags[t];return typeof n==="string"&&n.trim()?n.trim():void 0}function Pn(e){let t=A(e);if(!t?.config.projectId)throw new h("not_initialized","This folder is not bound to an Hlix project. Run `hlix import .` first.");return{root:t.root,projectId:t.config.projectId}}async function Cn(e,t){let n=await ls(e);if(n.isSymbolicLink()||!n.isFile())throw Error(`Refusing to import a non-regular file: ${e}`);if(n.size>t)throw Error(`Import file exceeds ${t} bytes: ${e}`);return{path:await Yi(e),content:await Xi(e,"utf8")}}function $n(e,t,n,r){if(e.json)e.stdout(w(S(t,n)));else e.stdout(`${r}
155
+ `)}var In={name:"skill import",summary:"Activate a local skill for the bound cloud project",usage:"Usage: hlix skill import <SKILL.md|folder> [--name <slug>] [--json]",supportsJson:!0,options:["name"],args:{min:1,max:1},async run(e){if(e.args.length!==1)throw Error("skill import requires one file or folder.");let t=Pn(e.cwd),n=En(e.cwd,e.args[0]),r=await ls(n);if(r.isSymbolicLink())throw Error(`Refusing to import a symlink: ${n}`);let s=r.isDirectory()?ea(n,"SKILL.md"):n,o=await Cn(s,200000),i=r.isDirectory()?jn(n):jn(s)==="SKILL.md"?jn(Zi(s)):ds(s).name,a=Ze(e,"name")??i;if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(a))throw Error("Skill name must be a lowercase kebab-case slug.");let c=await e.requireClient().resources.importSkill(t.projectId,{slug:a,content:o.content});return $n(e,In.name,c.skill,`Imported skill ${a}`),0}},xn={name:"agent import",summary:"Create a project-scoped agent from a local Markdown brief",usage:"Usage: hlix agent import <markdown-file> [--name <name>] [--runtime <runtime>] [--duty <duty>] [--profile <profile>] [--json]",supportsJson:!0,options:["name","runtime","duty","profile"],args:{min:1,max:1},async run(e){if(e.args.length!==1)throw Error("agent import requires one Markdown file.");let t=Pn(e.cwd),n=En(e.cwd,e.args[0]);if(![".md",".mdx"].includes(Qi(n).toLowerCase()))throw Error("Agent imports must be Markdown files.");let r=await Cn(n,20000),s=Ze(e,"runtime")??"hlix";if(!["claude-code","codex","cursor-agent","hlix"].includes(s))throw Error("--runtime must be claude-code, codex, cursor-agent, or hlix.");let o=Ze(e,"duty")??"executor";if(o!=="executor"&&o!=="intake")throw Error("--duty must be executor or intake.");let i=Ze(e,"name")??ds(n).name.replace(/[-_]+/g," "),a=await e.requireClient().resources.importAgent(t.projectId,{name:i,instructions:r.content,runtimeKind:s,duty:o});return $n(e,xn.name,a.agent,a.agent.duty==="intake"?`Imported agent ${a.agent.name} as this project's intake agent`:`Imported agent ${a.agent.name}`),0}},Tn={name:"mcp import",summary:"Explicitly activate one validated local MCP server",usage:"Usage: hlix mcp import <.mcp.json> [--server <name>] [--allow-stdio] [--json]",supportsJson:!0,options:["server","allow-stdio"],args:{min:1,max:1},async run(e){if(e.args.length!==1)throw Error("mcp import requires one MCP JSON file.");let t=Pn(e.cwd),n=await Cn(En(e.cwd,e.args[0]),200000),r;try{r=JSON.parse(n.content)}catch{throw Error("MCP config is not valid JSON.")}let s=Object.entries(r.mcpServers??{});if(s.length===0)throw Error("MCP config contains no servers.");let o=Ze(e,"server");if(!o&&s.length>1)throw Error("MCP config contains multiple servers; select one with --server <name>.");let i=o?s.find(([g])=>g===o):s[0];if(!i)throw Error(`MCP server not found: ${o}`);let[a,c]=i,l=c.type==="http"||c.type==="sse"?c.type:typeof c.command==="string"?"stdio":typeof c.url==="string"?"http":null;if(!l)throw Error(`MCP server ${a} has no supported transport.`);if(l==="stdio"&&e.flags["allow-stdio"]!==!0)throw Error("Stdio MCP servers execute a local command in the cloud; repeat with --allow-stdio.");let p=c.env&&typeof c.env==="object"&&!Array.isArray(c.env)?c.env:{},d=c.headers&&typeof c.headers==="object"&&!Array.isArray(c.headers)?c.headers:{};if(Object.values(d).some((g)=>typeof g!=="string"))throw Error(`MCP server ${a} headers must be strings.`);let m=Object.values(d).flatMap((g)=>[...g.matchAll(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g)].map((P)=>P[1]));if(Object.keys(d).length>0&&m.length===0)throw Error("MCP remote headers must use ${KEY} placeholders; literal credentials are refused.");let u=/^(?:(?:Bearer|Basic|Token) )?\$\{[A-Za-z_][A-Za-z0-9_]*\}$/i;if(Object.values(d).some((g)=>!u.test(g)))throw Error("MCP remote headers must be ${KEY} or an approved auth scheme followed by ${KEY}.");let f=await e.requireClient().resources.importMcp(t.projectId,{name:a,transport:l,...typeof c.command==="string"?{command:c.command}:{},...Array.isArray(c.args)&&c.args.every((g)=>typeof g==="string")?{args:c.args}:{},...typeof c.url==="string"?{url:c.url}:{},...Object.keys(d).length>0?{headers:d}:{},envKeys:[...new Set([...Object.keys(p),...m])].sort()});return $n(e,Tn.name,f.mcpServer,`Imported MCP server ${a}`),0}};import{spawnSync as ta}from"node:child_process";import{chmod as na,realpath as ra,writeFile as sa}from"node:fs/promises";import{basename as oa,dirname as ia,relative as aa,resolve as us,sep as ca}from"node:path";var ps=64;function et(e){let t=A(e.cwd),r=(typeof e.flags.project==="string"?e.flags.project:void 0)??t?.config.projectId;if(!r)throw new h("not_initialized","This folder is not bound to a Hlix project. Run `hlix import .`, or pass --project <id>.");return{projectId:r,root:t?.root??e.cwd}}var Qe=(e,t)=>typeof e[t]==="string"?e[t]:void 0,Rn={name:"secrets list",summary:"Show every secret the project holds, masked, with its source file",usage:["Usage: hlix secrets list [--project <id>] [--json]","","One row per (key, source file). Values are masked to their last four","characters and there is no flag that unmasks them — `hlix secrets export`","is the one command that returns plaintext, and it is audited."].join(`
152
156
  `),supportsJson:!0,options:["project"],async run(e){let{projectId:t}=et(e),n=await e.requireClient().secrets.listEntries(t);if(e.json)return e.stdout(w(S(Rn.name,n))),0;if(n.entries.length===0)e.stdout(`No secrets stored for this project.
153
157
  `);else e.stdout(`${X(["key","source","format","value","updated"],n.entries.map((r)=>[r.key,r.source,r.format||"-",r.maskedValue,r.updatedAt?.slice(0,10)??"-"]))}
154
158
  `);for(let r of n.warnings)e.stderr(`warning: ${r}
155
159
  `);return 0}},_n={name:"secrets set",summary:"Create or replace one secret in the store",usage:["Usage: hlix secrets set <KEY> [value] [--from-stdin] [--source <file>] [--project <id>] [--json]",""," --from-stdin Read the value from stdin instead of the argument, so it"," never reaches shell history or `ps`. Use this for real"," credentials: `pbpaste | hlix secrets set API_KEY --from-stdin`."," --source The file the value belongs to, e.g. apps/api/.env.local."," Omitted means the project root .env.","","Exactly one trailing newline is stripped from stdin, so a piped value does","not acquire the shell's."].join(`
156
160
  `),supportsJson:!0,options:["from-stdin","source","project"],args:{min:1,max:2},async run(e){let{projectId:t}=et(e),n=e.args[0],r=e.flags["from-stdin"]===!0;if(r&&e.args.length>1)throw new h("invalid_usage","Pass the value as an argument or with --from-stdin, not both.");if(!r&&e.args.length<2)throw new h("missing_argument","A value is required. Pass it as an argument, or pipe it with --from-stdin.");let s;if(r){if(!e.readStdin)throw new h("invalid_usage","--from-stdin is not available in this context.");s=(await e.readStdin()).replace(/\r?\n$/,"")}else s=e.args[1];let o=Qe(e.flags,"source"),i=await e.requireClient().secrets.upsertEntries(t,{entries:[{key:n,value:s,...o?{source:o}:{}}]});if(e.json)return e.stdout(w(S(_n.name,i))),i.written>0?0:1;if(i.written===0)throw new h("bad_request",`The store refused ${n}: --source must be a project-relative file path.`);return e.stdout(`${O([["key",n],["source",o??".env"]])}
157
- `),0}},Tn={name:"secrets delete",summary:"Remove one secret from the store",usage:["Usage: hlix secrets delete <KEY> [--source <file>] [--project <id>] [--json]","","Without --source the key is removed from EVERY file that declares it,",'which is what "delete this secret" usually means. Removing nothing exits 1.'].join(`
158
- `),supportsJson:!0,options:["source","project"],args:{min:1,max:1},async run(e){let{projectId:t}=et(e),n=e.args[0],r=Qe(e.flags,"source"),s=await e.requireClient().secrets.deleteEntry(t,n,r);if(e.json)return e.stdout(w(S(Tn.name,s))),s.removed>0?0:1;if(s.removed===0)return e.stderr(`No stored secret named ${n}${r?` in ${r}`:""}.
161
+ `),0}},On={name:"secrets delete",summary:"Remove one secret from the store",usage:["Usage: hlix secrets delete <KEY> [--source <file>] [--project <id>] [--json]","","Without --source the key is removed from EVERY file that declares it,",'which is what "delete this secret" usually means. Removing nothing exits 1.'].join(`
162
+ `),supportsJson:!0,options:["source","project"],args:{min:1,max:1},async run(e){let{projectId:t}=et(e),n=e.args[0],r=Qe(e.flags,"source"),s=await e.requireClient().secrets.deleteEntry(t,n,r);if(e.json)return e.stdout(w(S(On.name,s))),s.removed>0?0:1;if(s.removed===0)return e.stderr(`No stored secret named ${n}${r?` in ${r}`:""}.
159
163
  `),1;return e.stdout(`Removed ${s.removed} entr${s.removed===1?"y":"ies"} for ${n}.
160
164
  `),0}},wt={name:"secrets import",summary:"Load this folder's secret files into the project secrets store",usage:["Usage: hlix secrets import [file...] [--project <id>] [--json]","","With no arguments, every secret file the project scanner detects. Naming","files narrows it to those; a named file the scanner does not consider a","secret is refused rather than uploaded.","","The files are uploaded as bytes and the server parses them, so every shape","it knows lands here: dotenv and .envrc, Terraform variables, Java","properties, Spring YAML, .NET appsettings, Azure Functions local settings,","npm credentials, Rails database.yml, wrangler/fly TOML and Serverless all","become readable entries under their own path. An opaque credential (a","private key, a keystore, a service-account JSON) is kept byte-exact","instead. A file whose plaintext this platform does not hold — SOPS,","Ansible Vault, git-crypt — and a .env.example are reported as skipped.","","A file that holds key/value pairs REPLACES what the store held for that","path: the file on this machine is the truth."].join(`
161
- `),supportsJson:!0,options:["project"],args:{min:0,max:64},async run(e){let{projectId:t,root:n}=et(e),r=await G(n,{historyMode:"preserve",environment:e.env}),s=r.blocking.filter((d)=>!d.startsWith(ln));if(s.length>0)throw new h("scan_blocked",`Project scan blocked the import:
165
+ `),supportsJson:!0,options:["project"],args:{min:0,max:64},async run(e){let{projectId:t,root:n}=et(e),r=await G(n,{historyMode:"preserve",environment:e.env}),s=r.blocking.filter((d)=>!d.startsWith(dn));if(s.length>0)throw new h("scan_blocked",`Project scan blocked the import:
162
166
  - ${s.join(`
163
- - `)}`);let o=r.protectedFiles.filter((d)=>d.kind==="dotenv"||d.kind==="credential"),i=await ea(e.cwd),a=e.args.map((d)=>sa(r.root,us(i,d)).split(oa).join("/")),c=a.filter((d)=>!o.some((m)=>m.path===d));if(c.length>0)throw new h("invalid_usage",`Not a secret file in this project: ${c.join(", ")}`);let l=a.length>0?o.filter((d)=>a.includes(d.path)):o;if(l.length===0)return e.stdout(e.json?w(S(wt.name,{imported:[],skipped:[],warnings:[],written:0,rejected:[]})):`No secret files found in this project.
167
+ - `)}`);let o=r.protectedFiles.filter((d)=>d.kind==="dotenv"||d.kind==="credential"),i=await ra(e.cwd),a=e.args.map((d)=>aa(r.root,us(i,d)).split(ca).join("/")),c=a.filter((d)=>!o.some((m)=>m.path===d));if(c.length>0)throw new h("invalid_usage",`Not a secret file in this project: ${c.join(", ")}`);let l=a.length>0?o.filter((d)=>a.includes(d.path)):o;if(l.length===0)return e.stdout(e.json?w(S(wt.name,{imported:[],skipped:[],warnings:[],written:0,rejected:[]})):`No secret files found in this project.
164
168
  `),0;if(l.length>ps)throw new h("invalid_usage",`${l.length} secret files exceeds the ${ps} the store accepts in one request. Name the files to import, a batch at a time.`);let p=await e.requireClient().secrets.importFiles(t,l.map((d)=>({path:d.path,contentBase64:d.contentBase64})));if(e.json)return e.stdout(w(S(wt.name,p))),0;if(p.imported.length>0)e.stdout(`${X(["source","format","stored"],p.imported.map((d)=>[d.path,d.format||"-",d.kind==="file"?"as file":`${d.entries} entr${d.entries===1?"y":"ies"}`]))}
165
169
  `);e.stdout(`${p.written} value${p.written===1?"":"s"} stored.
166
170
  `);for(let d of p.skipped)e.stderr(`skipped ${d.path}: ${d.reason}
167
171
  `);for(let d of p.warnings)e.stderr(`warning: ${d}
168
172
  `);for(let d of p.rejected)e.stderr(`rejected ${d}: the store refused its source path
169
- `);return 0}};function ia(e){return Yi("git",["-C",ra(e),"ls-files","--error-unmatch","--",na(e)],{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).status===0}var On={name:"secrets export",summary:"Render one source file back out of the store, values in clear",usage:["Usage: hlix secrets export [--source <file>] [--format <id>] [--out <path>] [--project <id>] [--json]",""," --source Which stored file to render. Omitted means the root .env."," --format Re-render it as a different shape (dotenv, tfvars, …)."," Omitted means the shape the values were parsed as."," --out Write it to this path, mode 0600, instead of stdout. A path"," git TRACKS is refused: an exported file carries plaintext and"," must not become a commit.","","This is the one command that returns secret values, and the server writes","an audit row for every call."].join(`
170
- `),supportsJson:!0,options:["source","format","out","project"],async run(e){let{projectId:t}=et(e),n=Qe(e.flags,"source"),r=Qe(e.flags,"format"),s=Qe(e.flags,"out"),o=s===void 0?void 0:us(e.cwd,s);if(o!==void 0&&ia(o))throw new h("invalid_usage",`Refusing to overwrite a git-tracked file with secret values: ${o}`);let i=await e.requireClient().secrets.exportEntries(t,{...n?{source:n}:{},...r?{format:r}:{}});if(o!==void 0)await ta(o,i,{mode:384}),await Qi(o,384);if(e.json)return e.stdout(w(S(On.name,{source:n??null,format:r??null,out:o??null,bytes:Buffer.byteLength(i),...o===void 0?{content:i}:{}}))),0;if(o===void 0)e.stdout(i);else e.stdout(`${O([["wrote",o],["mode","0600"],["bytes",String(Buffer.byteLength(i))]])}
171
- `);return 0}};function An(e,t){let n=e[t];if(typeof n!=="string"||n.trim()==="")throw new h("missing_argument",`--${t} is required.`);return n}var Fn={name:"cycles create",summary:"Propose a cycle, which starts the project working on it",usage:["Usage: hlix cycles create <project-id> --title <t> --description <d> [--json]","","This is the command that DISPATCHES work. The proposal enters the project's","own loop, which plans the cycle, creates its tasks and starts the coders —","using the project's harness (see `hlix harness get`).","","`adopted` is true when the loop took it on this call, false when it was","recorded and will be planned on the next pass. Neither is an error. The API","returns no cycle id: the roadmap owns cycles, so find it with `hlix tasks","list --project <id>` once planning has run."].join(`
172
- `),supportsJson:!0,options:["title","description"],args:{min:1,max:1},async run(e){let t=e.args[0],n=An(e.flags,"title"),r=An(e.flags,"description"),s=await e.requireClient().cycles.propose({projectId:t,title:n,description:r});if(e.json)return e.stdout(w(S(Fn.name,s))),0;return e.stdout(`${O([["project",t],["title",n],["status",s.adopted?"adopted — the project is planning it now":"recorded — it will be planned on the next pass"]])}
173
- `),0}},Nn={name:"tasks create",summary:"Add a task to a project's board",usage:["Usage: hlix tasks create <project-id> --description <d> [--title <t>] [--json]","","Creates the task row. It does NOT start it: standalone task execution is","not implemented server-side and answers 501 by design. Work is dispatched","by its cycle — use `hlix cycles create` for that."].join(`
174
- `),supportsJson:!0,options:["title","description"],args:{min:1,max:1},async run(e){let t=e.args[0],n=An(e.flags,"description"),r=typeof e.flags.title==="string"?e.flags.title:void 0,s=await e.requireClient().tasks.create({projectId:t,description:n,...r?{title:r}:{}});if(e.json)return e.stdout(w(S(Nn.name,s))),0;return e.stdout(`${O([["task",s.id],["project",t],["status",s.status??"queued"],["note","not started — dispatch with `hlix cycles create`"]])}
175
- `),0}},Hn={name:"harness get",summary:"Show which coder runs, and which setting chose it",usage:["Usage: hlix harness get [project-id] [--json]","","With a project id, what that project would run. Without one, the","workspace-wide answer. `source` names the setting that decided: a project","preference, the workspace preference, or the system default."].join(`
176
- `),supportsJson:!0,args:{min:0,max:1},async run(e){let t=e.args[0],n=e.requireClient(),r=t?await n.modelConfig.resolvedProjectHarness(t):await n.modelConfig.resolvedHarness();if(e.json)return e.stdout(w(S(Hn.name,r))),0;return e.stdout(`${O([["scope",t?`project ${t}`:"workspace"],["harness",r.harness],["source",r.source]])}
177
- `),0}},Ln={name:"harness set",summary:"Choose the coder a project or the workspace runs",usage:[`Usage: hlix harness set <${fe.join("|")}> [project-id] [--org] [--json]`,"","With a project id, sets that project's preference. With --org, the","workspace-wide one that projects fall back to. This is a PERSISTENT server","setting that every future run on that scope uses, and it is audited.","","It is not the same thing as the local `harness` config key, which only","picks the coder Hlix Code spawns on this machine."].join(`
178
- `),supportsJson:!0,options:["org"],args:{min:1,max:2},async run(e){let t=e.args[0];if(!fe.includes(t))throw new h("invalid_usage",`harness must be one of ${fe.join(", ")}; got "${t}".`);let n=e.args[1],r=e.flags.org===!0;if(n&&r)throw new h("invalid_usage","Name a project or pass --org, not both: they are different scopes.");if(!n&&!r)throw new h("invalid_usage","Name the project to set, or pass --org for the whole workspace.");let s=e.requireClient(),o=n?await s.modelConfig.setProjectHarness(n,t):await s.modelConfig.setHarness(t);if(e.json)return e.stdout(w(S(Ln.name,o))),0;return e.stdout(`${O([["scope",n?`project ${n}`:"workspace"],["harness",t]])}
179
- `),0}};var Hd=[Gt,Wt,he,fn,gn,mn,Vt,Xt,Zt,dn,ft,vt,yt,ht,$n,In,xn,Rn,_n,Tn,wt,On,Yt,Qt,tn,nn,rn,sn,Nn,Fn,Hn,Ln];
180
- export{h as a,ca as b,A as c,K as d,Zs as e,tc as f,mr as g,fe as h,pc as i,Kt as j,Pr as k,Ir as l,yc as m,vc as n,wc as o,Hd as p};
173
+ `);return 0}};function la(e){return ta("git",["-C",ia(e),"ls-files","--error-unmatch","--",oa(e)],{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).status===0}var An={name:"secrets export",summary:"Render one source file back out of the store, values in clear",usage:["Usage: hlix secrets export [--source <file>] [--format <id>] [--out <path>] [--project <id>] [--json]",""," --source Which stored file to render. Omitted means the root .env."," --format Re-render it as a different shape (dotenv, tfvars, …)."," Omitted means the shape the values were parsed as."," --out Write it to this path, mode 0600, instead of stdout. A path"," git TRACKS is refused: an exported file carries plaintext and"," must not become a commit.","","This is the one command that returns secret values, and the server writes","an audit row for every call."].join(`
174
+ `),supportsJson:!0,options:["source","format","out","project"],async run(e){let{projectId:t}=et(e),n=Qe(e.flags,"source"),r=Qe(e.flags,"format"),s=Qe(e.flags,"out"),o=s===void 0?void 0:us(e.cwd,s);if(o!==void 0&&la(o))throw new h("invalid_usage",`Refusing to overwrite a git-tracked file with secret values: ${o}`);let i=await e.requireClient().secrets.exportEntries(t,{...n?{source:n}:{},...r?{format:r}:{}});if(o!==void 0)await sa(o,i,{mode:384}),await na(o,384);if(e.json)return e.stdout(w(S(An.name,{source:n??null,format:r??null,out:o??null,bytes:Buffer.byteLength(i),...o===void 0?{content:i}:{}}))),0;if(o===void 0)e.stdout(i);else e.stdout(`${O([["wrote",o],["mode","0600"],["bytes",String(Buffer.byteLength(i))]])}
175
+ `);return 0}};function Fn(e,t){let n=e[t];if(typeof n!=="string"||n.trim()==="")throw new h("missing_argument",`--${t} is required.`);return n}var Nn={name:"cycles create",summary:"Propose a cycle, which starts the project working on it",usage:["Usage: hlix cycles create <project-id> --title <t> --description <d> [--json]","","This is the command that DISPATCHES work. The proposal enters the project's","own loop, which plans the cycle, creates its tasks and starts the coders —","using the project's harness (see `hlix harness get`).","","`adopted` is true when the loop took it on this call, false when it was","recorded and will be planned on the next pass. Neither is an error. The API","returns no cycle id: the roadmap owns cycles, so find it with `hlix tasks","list --project <id>` once planning has run."].join(`
176
+ `),supportsJson:!0,options:["title","description"],args:{min:1,max:1},async run(e){let t=e.args[0],n=Fn(e.flags,"title"),r=Fn(e.flags,"description"),s=await e.requireClient().cycles.propose({projectId:t,title:n,description:r});if(e.json)return e.stdout(w(S(Nn.name,s))),0;return e.stdout(`${O([["project",t],["title",n],["status",s.adopted?"adopted — the project is planning it now":"recorded — it will be planned on the next pass"]])}
177
+ `),0}},Hn={name:"tasks create",summary:"Add a task to a project's board",usage:["Usage: hlix tasks create <project-id> --description <d> [--title <t>] [--json]","","Creates the task row. It does NOT start it: standalone task execution is","not implemented server-side and answers 501 by design. Work is dispatched","by its cycle — use `hlix cycles create` for that."].join(`
178
+ `),supportsJson:!0,options:["title","description"],args:{min:1,max:1},async run(e){let t=e.args[0],n=Fn(e.flags,"description"),r=typeof e.flags.title==="string"?e.flags.title:void 0,s=await e.requireClient().tasks.create({projectId:t,description:n,...r?{title:r}:{}});if(e.json)return e.stdout(w(S(Hn.name,s))),0;return e.stdout(`${O([["task",s.id],["project",t],["status",s.status??"queued"],["note","not started — dispatch with `hlix cycles create`"]])}
179
+ `),0}},Ln={name:"harness get",summary:"Show which coder runs, and which setting chose it",usage:["Usage: hlix harness get [project-id] [--json]","","With a project id, what that project would run. Without one, the","workspace-wide answer. `source` names the setting that decided: a project","preference, the workspace preference, or the system default."].join(`
180
+ `),supportsJson:!0,args:{min:0,max:1},async run(e){let t=e.args[0],n=e.requireClient(),r=t?await n.modelConfig.resolvedProjectHarness(t):await n.modelConfig.resolvedHarness();if(e.json)return e.stdout(w(S(Ln.name,r))),0;return e.stdout(`${O([["scope",t?`project ${t}`:"workspace"],["harness",r.harness],["source",r.source]])}
181
+ `),0}},Un={name:"harness set",summary:"Choose the coder a project or the workspace runs",usage:[`Usage: hlix harness set <${he.join("|")}> [project-id] [--org] [--json]`,"","With a project id, sets that project's preference. With --org, the","workspace-wide one that projects fall back to. This is a PERSISTENT server","setting that every future run on that scope uses, and it is audited.","","It is not the same thing as the local `harness` config key, which only","picks the coder Hlix Code spawns on this machine."].join(`
182
+ `),supportsJson:!0,options:["org"],args:{min:1,max:2},async run(e){let t=e.args[0];if(!he.includes(t))throw new h("invalid_usage",`harness must be one of ${he.join(", ")}; got "${t}".`);let n=e.args[1],r=e.flags.org===!0;if(n&&r)throw new h("invalid_usage","Name a project or pass --org, not both: they are different scopes.");if(!n&&!r)throw new h("invalid_usage","Name the project to set, or pass --org for the whole workspace.");let s=e.requireClient(),o=n?await s.modelConfig.setProjectHarness(n,t):await s.modelConfig.setHarness(t);if(e.json)return e.stdout(w(S(Un.name,o))),0;return e.stdout(`${O([["scope",n?`project ${n}`:"workspace"],["harness",t]])}
183
+ `),0}};var Md=[Wt,Vt,ve,gn,hn,fn,Xt,Yt,Zt,pn,ft,vt,yt,ht,In,xn,Tn,Rn,_n,On,wt,An,Qt,en,nn,rn,sn,on,Hn,Nn,Ln,Un];
184
+ export{h as a,pa as b,A as c,D as d,Ys as e,sc as f,mr as g,he as h,fc as i,Kt as j,Pr as k,Ir as l,bc as m,Sc as n,kc as o,Md as p};
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{b as g,c as y,e as v,f as c,p as o}from"./index-778kjav1.js";import{q as i}from"./index-syeavftx.js";import{emitKeypressEvents as w}from"node:readline";import{createInterface as C}from"node:readline/promises";async function u(r){if(!process.stdin.isTTY||!process.stdin.setRawMode)throw Error("Interactive login requires a terminal. Set HLIX_API_KEY for CI.");return process.stderr.write(r),w(process.stdin),process.stdin.setRawMode(!0),process.stdin.resume(),new Promise((e,t)=>{let s="",a=()=>{process.stdin.off("keypress",p),process.stdin.setRawMode(!1),process.stdin.pause(),process.stderr.write(`
3
- `)},p=(m,n)=>{if(n.ctrl&&n.name==="c"||n.name==="escape"){a(),t(Error("Login cancelled."));return}if(n.name==="return"||n.name==="enter"){a(),e(s);return}if(n.name==="backspace"){s=s.slice(0,-1);return}if(m&&!n.ctrl)s+=m};process.stdin.on("keypress",p)})}async function d(r){if(!process.stdin.isTTY||!process.stderr.isTTY)throw Error("Interactive approval requires a terminal. Review with --dry-run, then pass --yes.");let e=C({input:process.stdin,output:process.stderr});try{let t=(await e.question(`${r}
4
- Continue? [y/N] `)).trim().toLowerCase();return t==="y"||t==="yes"}finally{e.close()}}import{readFileSync as x,realpathSync as f}from"node:fs";import{fileURLToPath as S}from"node:url";function h(){if(i.main==i.module===!0)return!0;let r=process.argv[1];if(!r)return!1;try{return f(r)===f(S(import.meta.url))}catch{return!1}}var l={"-h":"--help","-v":"--version"};function M(r){return r.map((e)=>l[e]??e)}function P(r,e=o){let t=r[0];if(t===void 0)return!1;if(t in l||t==="--help"||t==="--version")return!0;return e.some((s)=>s.name.split(" ")[0]===t)}function I(r,e){if(P(r))return e.cli(M(r));return e.code(r[0]==="code"?r.slice(1):r)}if(h()){let r=await I(process.argv.slice(2),{cli:(e)=>c(o,e,{stdout:(t)=>process.stdout.write(t),stderr:(t)=>process.stderr.write(t),env:process.env,readSecret:u,confirm:d,readStdin:async()=>x(0,"utf8")}),code:async(e)=>(await import("./main-3qf79zn1.js")).runHlixCode(e)});process.exit(r)}export{o as COMMANDS,g as JSON_SCHEMA_VERSION,v as clientFor,I as dispatch,y as findProjectBinding,P as isCliInvocation,M as normalizeCliArgv,c as runCli};
2
+ import{b as g,c as h,e as T,f as p,p as c}from"./index-v9jk44m3.js";import{q as a}from"./index-syeavftx.js";import{emitKeypressEvents as C}from"node:readline";import{createInterface as u}from"node:readline/promises";async function d(r){if(!process.stdin.isTTY||!process.stdin.setRawMode)throw Error("Interactive login requires a terminal. Set HLIX_API_KEY for CI.");return process.stderr.write(r),C(process.stdin),process.stdin.setRawMode(!0),process.stdin.resume(),new Promise((e,t)=>{let s="",i=()=>{process.stdin.off("keypress",n),process.stdin.setRawMode(!1),process.stdin.pause(),process.stderr.write(`
3
+ `)},n=(m,o)=>{if(o.ctrl&&o.name==="c"||o.name==="escape"){i(),t(Error("Login cancelled."));return}if(o.name==="return"||o.name==="enter"){i(),e(s);return}if(o.name==="backspace"){s=s.slice(0,-1);return}if(m&&!o.ctrl)s+=m};process.stdin.on("keypress",n)})}async function l(r,e){if(!process.stdin.isTTY||!process.stderr.isTTY)throw Error("Interactive selection requires a terminal. Pass --workspace <id>.");let t=u({input:process.stdin,output:process.stderr});try{for(let s=0;s<3;s+=1){let i=(await t.question(r)).trim(),n=Number(i);if(Number.isInteger(n)&&n>=1&&n<=e)return n-1;process.stderr.write(`Enter a number between 1 and ${e}.
4
+ `)}throw Error("No workspace selected.")}finally{t.close()}}async function f(r){if(!process.stdin.isTTY||!process.stderr.isTTY)throw Error("Interactive approval requires a terminal. Review with --dry-run, then pass --yes.");let e=u({input:process.stdin,output:process.stderr});try{let t=(await e.question(`${r}
5
+ Continue? [y/N] `)).trim().toLowerCase();return t==="y"||t==="yes"}finally{e.close()}}import{readFileSync as b,realpathSync as w}from"node:fs";import{fileURLToPath as v}from"node:url";function x(){if(a.main==a.module===!0)return!0;let r=process.argv[1];if(!r)return!1;try{return w(r)===w(v(import.meta.url))}catch{return!1}}var y={"-h":"--help","-v":"--version"};function S(r){return r.map((e)=>y[e]??e)}function P(r,e=c){let t=r[0];if(t===void 0)return!1;if(t in y||t==="--help"||t==="--version")return!0;return e.some((s)=>s.name.split(" ")[0]===t)}function E(r,e){if(P(r))return e.cli(S(r));return e.code(r[0]==="code"?r.slice(1):r)}if(x()){let r=await E(process.argv.slice(2),{cli:(e)=>p(c,e,{stdout:(t)=>process.stdout.write(t),stderr:(t)=>process.stderr.write(t),env:process.env,readSecret:d,confirm:f,...process.stdin.isTTY&&process.stderr.isTTY?{promptChoice:l}:{},readStdin:async()=>b(0,"utf8")}),code:async(e)=>(await import("./main-75qgt5n5.js")).runHlixCode(e)});process.exit(r)}export{c as COMMANDS,g as JSON_SCHEMA_VERSION,T as clientFor,E as dispatch,h as findProjectBinding,P as isCliInvocation,S as normalizeCliArgv,p as runCli};
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{a as w,d as te,e as h,f as D,g as C,h as f,i as v,j as fe,k as xe,l as we,m as ye,n as be,o as ke,p as y}from"./index-778kjav1.js";import{q as ht}from"./index-syeavftx.js";import{relative as gt,resolve as ft}from"node:path";import{parseArgs as xt}from"node:util";import{createMastraCode as wt}from"mastracode";import{loadMcpConfig as yt}from"@mastra/code-sdk/mcp/config";import{executeSubagent as bt}from"@mastra/code-sdk/agents/subagents/execute";import{exploreSubagent as kt}from"@mastra/code-sdk/agents/subagents/explore";import{planSubagent as vt}from"@mastra/code-sdk/agents/subagents/plan";import{hasHeadlessFlag as St,parseHeadlessArgs as Ct,runMC as Ht}from"mastracode/headless";import{MastraTUI as jt}from"mastracode/tui";import{mkdirSync as Re,writeFileSync as Ae}from"node:fs";import{join as U}from"node:path";import{createTool as He}from"@mastra/core/tools";import{z as u}from"zod";var b=(e)=>`hlix_${e.split(" ").join("_")}`,je=u.object({args:u.array(u.string()).optional().describe("Positional arguments that follow the command name."),flags:u.record(u.string(),u.union([u.string(),u.boolean()])).optional().describe('Options without the leading dashes, e.g. { "yes": true, "name": "api" }.')}),Ie=u.object({exitCode:u.number(),stdout:u.string(),stderr:u.string()});function Pe(e,t,s){let r=e.name.split(" ").concat(t.args??[]);for(let[o,n]of Object.entries(t.flags??{})){if(n===!1)continue;if(r.push(`--${o}`),typeof n==="string")r.push(n)}if(!t.flags?.cwd)r.push("--cwd",s);if(e.supportsJson&&!t.flags?.json)r.push("--json");return r}async function _e(e,t,s,r=process.env){let o="",n="";return{exitCode:await D([e],Pe(e,t,s),{stdout:(c)=>{o+=c},stderr:(c)=>{n+=c},env:r}),stdout:o,stderr:n}}function B(e){let t={};for(let s of e.commands??y){let r=b(s.name);t[r]=He({id:r,description:`${s.summary}
2
+ import{a as w,d as te,e as h,f as D,g as C,h as f,i as v,j as fe,k as xe,l as we,m as ye,n as be,o as ke,p as y}from"./index-v9jk44m3.js";import{q as ht}from"./index-syeavftx.js";import{relative as gt,resolve as ft}from"node:path";import{parseArgs as xt}from"node:util";import{createMastraCode as wt}from"mastracode";import{loadMcpConfig as yt}from"@mastra/code-sdk/mcp/config";import{executeSubagent as bt}from"@mastra/code-sdk/agents/subagents/execute";import{exploreSubagent as kt}from"@mastra/code-sdk/agents/subagents/explore";import{planSubagent as vt}from"@mastra/code-sdk/agents/subagents/plan";import{hasHeadlessFlag as St,parseHeadlessArgs as Ct,runMC as Ht}from"mastracode/headless";import{MastraTUI as jt}from"mastracode/tui";import{mkdirSync as Re,writeFileSync as Ae}from"node:fs";import{join as U}from"node:path";import{createTool as He}from"@mastra/core/tools";import{z as u}from"zod";var b=(e)=>`hlix_${e.split(" ").join("_")}`,je=u.object({args:u.array(u.string()).optional().describe("Positional arguments that follow the command name."),flags:u.record(u.string(),u.union([u.string(),u.boolean()])).optional().describe('Options without the leading dashes, e.g. { "yes": true, "name": "api" }.')}),Ie=u.object({exitCode:u.number(),stdout:u.string(),stderr:u.string()});function Pe(e,t,s){let r=e.name.split(" ").concat(t.args??[]);for(let[o,n]of Object.entries(t.flags??{})){if(n===!1)continue;if(r.push(`--${o}`),typeof n==="string")r.push(n)}if(!t.flags?.cwd)r.push("--cwd",s);if(e.supportsJson&&!t.flags?.json)r.push("--json");return r}async function _e(e,t,s,r=process.env){let o="",n="";return{exitCode:await D([e],Pe(e,t,s),{stdout:(c)=>{o+=c},stderr:(c)=>{n+=c},env:r}),stdout:o,stderr:n}}function B(e){let t={};for(let s of e.commands??y){let r=b(s.name);t[r]=He({id:r,description:`${s.summary}
3
3
 
4
4
  ${s.usage}`,inputSchema:je,outputSchema:Ie,execute:async(o)=>_e(s,o,e.cwd,e.env)})}return t}var Me=(e)=>`${e.split(" ").join("-")}.md`;function $e(e){return["---",`description: ${e.summary}`,"---","",`Call the tool \`${b(e.name)}\` with the user's arguments: $ARGUMENTS.`,"Show the result.",""].join(`
5
5
  `)}var Oe={"follow.md":["---","description: Watch a cloud task being coded, live","---","","Call the tool `hlix_tasks_follow` with `taskId` set to $ARGUMENTS. It streams the","coder's text and tool calls into this session. Summarise what it did.",""].join(`
@@ -15,6 +15,6 @@ ${s.usage}`,inputSchema:je,outputSchema:Ie,execute:async(o)=>_e(s,o,e.cwd,e.env)
15
15
  `);a={...a,harness:l??{harness:"unknown",source:o?"the project's setting could not be read":"no project bound"}}}let d=ae({wired:oe({cwd:s.cwd,env:process.env}),...r.merged.model?{configured:r.merged.model}:{},...r.sources.model?{configuredSource:r.sources.model}:{}}),I=he(c);process.stdout.write(`${ie(V(I,a.harness),d)}
16
16
  `);let P=ke(n);if(P)process.stdout.write(`${P}
17
17
  `);let _=o?Pt(await _t(s.cwd,o)):"";if(_)process.stdout.write(`${_}
18
- `);q(s.cwd);let R=null,ve=a.harness.harness==="unknown"?"hlix":a.harness.harness,A=G({sandbox:c.choice,cwd:s.cwd,active:ve,unavailable:a.unavailable,...i?{workspace:i}:{},...d?{model:d.id}:{}}),Se=new Set(Object.keys(yt(s.cwd,j).mcpServers??{})),M=Object.fromEntries(n.mcpServers.filter((l)=>!Se.has(l.name)).map((l)=>[l.name,l.config])),O=ye(n.generatedCommands,s.cwd),T=[...n.commands.map((l)=>l.path),...O?[O]:[]],N=Ot(n),E=ne(A,d?.id),F=Nt(n.subagents,E),W=be(n.instructions,s.cwd),{version:Ce}=await import("./package-hbd79e7c.js"),L=await t.boot({configDir:j,cwd:s.cwd,hostInstructions:[It,...c.choice==="cloud"?[Y(a.harness.harness)]:[],...W?[W]:[]].join(`
18
+ `);q(s.cwd);let R=null,ve=a.harness.harness==="unknown"?"hlix":a.harness.harness,A=G({sandbox:c.choice,cwd:s.cwd,active:ve,unavailable:a.unavailable,...i?{workspace:i}:{},...d?{model:d.id}:{}}),Se=new Set(Object.keys(yt(s.cwd,j).mcpServers??{})),M=Object.fromEntries(n.mcpServers.filter((l)=>!Se.has(l.name)).map((l)=>[l.name,l.config])),O=ye(n.generatedCommands,s.cwd),T=[...n.commands.map((l)=>l.path),...O?[O]:[]],N=Ot(n),E=ne(A,d?.id),F=Nt(n.subagents,E),W=be(n.instructions,s.cwd),{version:Ce}=await import("./package-jey6n0rh.js"),L=await t.boot({configDir:j,cwd:s.cwd,hostInstructions:[It,...c.choice==="cloud"?[Y(a.harness.harness)]:[],...W?[W]:[]].join(`
19
19
 
20
20
  `),...Object.keys(M).length>0?{mcpServers:M}:{},...F?{subagents:F}:{},...T.length>0||N.length>0?{initialState:{pluginCommandPaths:T,pluginSkillPaths:N}}:{},extraTools:{...B({cwd:s.cwd}),hlix_tasks_follow:Z({cwd:s.cwd}),hlix_harness:Q({sandbox:c.choice,sandboxLine:I,available:a.available,modesBuilt:A.length>0,session:()=>R,...o?{setProjectHarness:async(l)=>{await h(process.env,{cwd:s.cwd,flags:{}}).modelConfig.setProjectHarness(o,l)}}:{}})},modes:E,...i?{workspace:i}:{}});return R=L.session,t.present(L,e,Ce)}export{Ot as extraSkillPaths,Rt as parseHlixCodeArgs,At as planHarness,Bs as runHlixCode,Pt as secretsStatusLine,Nt as standardsSubagents,Tt as workspaceSkillPaths};
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import"./index-syeavftx.js";var s="@hlix/cli",i="0.4.2",n="SEE LICENSE IN LICENSE",a="Hlix Code and the hlix control-plane CLI.",r=["hlix","cli","agents"],d="https://hlix.ai",p="module",c="./dist/index.js",o={hlix:"./dist/index.js"},l=["dist","skills","LICENSE","THIRD_PARTY_NOTICES"],u={node:">=22.19.0"},b={access:"public"},h={build:"rm -rf dist && bun build src/index.ts --outdir dist --target node --format esm --splitting --packages external --minify --banner '#!/usr/bin/env node'",test:'bun test --isolate src --path-ignore-patterns "**/*.integration.test.ts" --timeout 20000',typecheck:"tsc --noEmit",prepublishOnly:"bun run typecheck && bun run build && bun run test","test:integration":"NODE_ENV=test bun run ../../apps/backend/scripts/with-aimock.ts -- bun run ../../apps/backend/scripts/with-test-db.ts -- bun test --isolate --preload ../../apps/backend/test/helpers/pool-lifecycle.ts --timeout 60000 .integration.test.ts"},m={"@mastra/acp":"^0.4.1","@mastra/code-sdk":"1.7.0","@mastra/core":"1.65.0","@mastra/docker":"^0.7.0",ignore:"7.0.8",mastracode:"0.39.0","openapi-fetch":"^0.17.0",zod:"4.5.4"},g={"@hlix/sdk":"^0.2.0","@types/bun":"latest",typescript:"^7.0.2"},k={name:s,version:i,license:n,description:a,keywords:r,homepage:d,type:p,main:c,bin:o,files:l,engines:u,publishConfig:b,scripts:h,dependencies:m,devDependencies:g};export{o as bin,k as default,m as dependencies,a as description,g as devDependencies,u as engines,l as files,d as homepage,r as keywords,n as license,c as main,s as name,b as publishConfig,h as scripts,p as type,i as version};
2
+ import"./index-syeavftx.js";var s="@hlix/cli",i="0.4.3",n="SEE LICENSE IN LICENSE",a="Hlix Code and the hlix control-plane CLI.",r=["hlix","cli","agents"],d="https://hlix.ai",p="module",c="./dist/index.js",o={hlix:"./dist/index.js"},l=["dist","skills","LICENSE","THIRD_PARTY_NOTICES"],u={node:">=22.19.0"},b={access:"public"},h={build:"rm -rf dist && bun build src/index.ts --outdir dist --target node --format esm --splitting --packages external --minify --banner '#!/usr/bin/env node'",test:'bun test --isolate src --path-ignore-patterns "**/*.integration.test.ts" --timeout 20000',typecheck:"tsc --noEmit",prepublishOnly:"bun run typecheck && bun run build && bun run test","test:integration":"NODE_ENV=test bun run ../../apps/backend/scripts/with-aimock.ts -- bun run ../../apps/backend/scripts/with-test-db.ts -- bun test --isolate --preload ../../apps/backend/test/helpers/pool-lifecycle.ts --timeout 60000 .integration.test.ts"},m={"@mastra/acp":"^0.4.1","@mastra/code-sdk":"1.7.0","@mastra/core":"1.65.0","@mastra/docker":"^0.7.0",ignore:"7.0.8",mastracode:"0.39.0","openapi-fetch":"^0.17.0",zod:"4.5.4"},g={"@hlix/sdk":"^0.2.0","@types/bun":"latest",typescript:"^7.0.2"},k={name:s,version:i,license:n,description:a,keywords:r,homepage:d,type:p,main:c,bin:o,files:l,engines:u,publishConfig:b,scripts:h,dependencies:m,devDependencies:g};export{o as bin,k as default,m as dependencies,a as description,g as devDependencies,u as engines,l as files,d as homepage,r as keywords,n as license,c as main,s as name,b as publishConfig,h as scripts,p as type,i as version};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hlix/cli",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "description": "Hlix Code and the hlix control-plane CLI.",
6
6
  "keywords": [
@@ -12,7 +12,7 @@ if they disagree, so this file cannot advertise something that does not exist.
12
12
  ## Authentication
13
13
 
14
14
  ```bash
15
- hlix auth login --workspace <id> [--base-url <url>]
15
+ hlix auth login [--workspace <id>] [--base-url <url>]
16
16
  hlix auth status [--json] # which credential, from where, does it work
17
17
  hlix auth logout [--yes] [--json] # remove the stored credential file
18
18
  ```
@@ -25,10 +25,16 @@ Reads the key from a hidden terminal prompt, verifies it against the API
25
25
  `HLIX_WORKSPACE_ID` set the target and workspace. Use those in CI rather than
26
26
  running a login step.
27
27
 
28
- `--workspace` is required at login: an API key authenticates a user but names
29
- no workspace, so the caller states one. `hlix auth login` verifies the key
30
- against a real call **before** writing it, so a key that does not work is never
31
- stored.
28
+ `--workspace` is **optional** at login. An API key authenticates a user and
29
+ names no workspace, so the key is read first and then used to list the
30
+ workspaces its owner belongs to (`GET /v1/api/workspaces`, the one endpoint that
31
+ needs no `X-Organization-Id`). With exactly one, that one is used and named on
32
+ stderr; with several, a terminal gets a numbered list to pick from and a
33
+ non-interactive run (`--json`, or no TTY) exits `missing_argument` listing the
34
+ ids so it can be re-run with `--workspace`. A `--workspace` that is not one of
35
+ them exits `workspace_mismatch` naming the ones that are, instead of storing a
36
+ credential that 403s later. `hlix auth login` then verifies the key against a
37
+ real call **before** writing it, so a key that does not work is never stored.
32
38
 
33
39
  `auth status` names the credential's **source** — the environment or the stored
34
40
  file — and probes it against the API. It never prints the key, not even a