@hlix/cli 0.4.2 → 0.4.4

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.4
37
+ npx @hlix/cli@0.4.4 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
 
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{l as s}from"./index-rraz48fm.js";import"./index-y1n35st0.js";import{chmodSync as r,mkdirSync as i}from"node:fs";import{join as a}from"node:path";import{ONBOARDING_VERSION as c}from"@mastra/code-sdk/onboarding/index";import{getSettingsPath as d,loadSettings as m,saveSettings as p}from"@mastra/code-sdk/onboarding/settings";var g=(e=process.env)=>a(s(e),".hlix","code");function A(e,n){let t=Boolean(e.completedAt??e.skippedAt);return{...e,...t?{}:{skippedAt:n},version:Math.max(e.version,c),quietModePreferenceSelected:!0}}function f(e){let n=g(process.env);i(n,{recursive:!0,mode:448}),process.env.MASTRA_APP_DATA_DIR=n,process.env.MASTRACODE_DISABLE_UPDATE_CHECK="1",process.env.MASTRACODE_UPDATE_LATEST_VERSION=e.version;let t=m();t.onboarding=A(t.onboarding,e.now??new Date().toISOString()),p(t);let o=d();return r(n,448),r(o,384),{dataDir:n,settingsPath:o}}export{f as configureHarnessEnvironment,g as harnessDataDir,A as seedOnboarding};
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env node
2
+ import{l as Rr,m as Ar,q as Hr}from"./index-rraz48fm.js";import{r as Rs}from"./index-y1n35st0.js";class f extends Error{code;constructor(e,t){super(t);this.name="CliError",this.code=e}}var Pi=1,k=(e,t)=>({schemaVersion:1,command:e,data:t}),Ee=(e,t)=>({schemaVersion:1,command:e,error:t});function y(e){return`${JSON.stringify(e,null,2)}
3
+ `}function _(e){let t=Math.max(0,...e.map(([n])=>n.length));return e.map(([n,r])=>`${n.padEnd(t)} ${r}`).join(`
4
+ `)}function W(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 ys}from"node:fs";import{dirname as ws,resolve as vs}from"node:path";import{closeSync as bt,constants as Pe,existsSync as Qe,fsyncSync as Mn,lstatSync as St,mkdirSync as os,openSync as Bn,readFileSync as Kn,renameSync as is,statSync as zn,unlinkSync as qn,writeFileSync as as}from"node:fs";import{homedir as cs}from"node:os";import{dirname as ls,join as jt}from"node:path";function ce(e=process.env){let t=e.HLIX_CONFIG_HOME??e.XDG_CONFIG_HOME??jt(cs(),".config");return jt(t,"hlix","credentials.json")}function Dn(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(Kn(ce(e),"utf8"));return n.apiKey&&n.baseUrl?n:null}catch{return null}}function Jn(e=process.env){let t=ce(e);return Qe(t)?t:null}function Et(e=process.env){let t=ce(e);if(!Qe(t))return{path:t,removed:!1,reason:"absent"};let n=St(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&&zn(t).uid!==r)throw Error("Refusing to remove a credential file owned by another user.");let s;try{s=JSON.parse(Kn(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 qn(t),{path:t,removed:!0,reason:"removed"}}function Gn(e,t=process.env){let n=ce(t),r=ls(n);if(os(r,{recursive:!0,mode:448}),St(r).isSymbolicLink())throw Error("Refusing to write credentials through a symlinked directory.");if(Qe(n)){let i=St(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&&zn(n).uid!==a)throw Error("Refusing to replace a credential file owned by another user.")}let s=jt(r,`.credentials.${process.pid}.${crypto.randomUUID()}.tmp`),o;try{o=Bn(s,Pe.O_WRONLY|Pe.O_CREAT|Pe.O_EXCL|Pe.O_NOFOLLOW,384),as(o,`${JSON.stringify(e,null,2)}
6
+ `,"utf8"),Mn(o),bt(o),o=void 0,is(s,n);let i=Bn(r,Pe.O_RDONLY);try{try{Mn(i)}catch(a){let c=a.code;if(c!=="EINVAL"&&c!=="ENOTSUP")throw a}}finally{bt(i)}}catch(i){if(o!==void 0)bt(o);if(Qe(s))qn(s);throw i}return n}import{constants as et,existsSync as tt,lstatSync as Vn,mkdirSync as ds,openSync as ps,closeSync as Wn,fsyncSync as us,readFileSync as Xn,renameSync as ms,unlinkSync as fs,writeFileSync as Pt}from"node:fs";import{dirname as gs,join as Ce,resolve as nt}from"node:path";function hs(e){if(!tt(e))return;let t=Vn(e);if(t.isSymbolicLink()||!t.isFile())throw Error(`Refusing to replace a non-regular Hlix file: ${e}`)}function $e(e,t){let n=gs(e);if(ds(n,{recursive:!0,mode:448}),Vn(n).isSymbolicLink())throw Error(`Refusing to write through a symlinked Hlix directory: ${n}`);hs(e);let r=Ce(n,`.hlix-${process.pid}-${crypto.randomUUID()}.tmp`),s;try{s=ps(r,et.O_WRONLY|et.O_CREAT|et.O_EXCL|et.O_NOFOLLOW,384),Pt(s,`${JSON.stringify(t,null,2)}
7
+ `,"utf8"),us(s),Wn(s),s=void 0,ms(r,e)}catch(o){if(s!==void 0)Wn(s);if(tt(r))fs(r);throw o}}function Ie(e){return Ce(nt(e),".hlix","config.json")}function Yn(e){return Ce(nt(e),".hlix","state.json")}function le(e){try{let t=JSON.parse(Xn(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(nt(e),".hlix",".gitignore");if(!tt(n))Pt(n,`state.json
8
+ `,{mode:420,flag:"wx"});let r=Ce(nt(e),".hlixignore");if(!tt(r))Pt(r,`# Additional project-local paths to exclude from Hlix snapshots.
9
+ `,{mode:420,flag:"wx"})}function _e(e,t){$e(Yn(e),t)}function rt(e){try{let t=JSON.parse(Xn(Yn(e),"utf8"));return t.schemaVersion===1&&t.revisionId&&t.generation>0?t:null}catch{return null}}var Ct="https://server.hlix.ai";function O(e){let t=vs(e);for(;;){let n=le(t);if(n)return{root:t,config:n};let r=ws(t);if(r===t)return null;t=r}}function Qn(e){try{return ys(e).isDirectory()}catch{return!1}}function st(e){if(typeof e!=="string")return;let t=e.trim();return t?t:void 0}var Zn=(e,t)=>e.replace(/\/+$/,"")===t.replace(/\/+$/,"");function B(e){let{env:t,flags:n,cwd:r}=e,s=O(r),o=Dn(t),i=o?t.HLIX_API_KEY||t.HLIX_SESSION_TOKEN?"env":"file":null,a=i==="file"?o:null,c=st(n["base-url"]),l=st(t.HLIX_BASE_URL),p=st(n.workspace),d=st(t.HLIX_WORKSPACE_ID),u=c??l??s?.config.apiUrl??a?.baseUrl??Ct,m=c?"flag":l?"env":s?.config.apiUrl?"project":a?.baseUrl?"credential":"default",w=p??d??s?.config.workspaceId??a?.organizationId??null,b=p?"flag":d?"env":s?.config.workspaceId?"project":a?.organizationId?"credential":null;return{baseUrl:u,baseUrlSource:m,workspaceId:w,workspaceSource:b,credential:o,credentialSource:i,credentialPath:ce(t),binding:s,conflict:ks(s,{flagBaseUrl:c,envBaseUrl:l,flagWorkspace:p,envWorkspace:d})}}function ks(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&&!Zn(t.flagBaseUrl,e.config.apiUrl))return`${n} ${e.config.apiUrl}, but --base-url names ${t.flagBaseUrl}. ${r}`;if(t.envBaseUrl&&!Zn(t.envBaseUrl,e.config.apiUrl))return`${n} ${e.config.apiUrl}, but HLIX_BASE_URL names ${t.envBaseUrl}. ${r}`;return null}import{resolve as As}from"node:path";import{parseArgs as Hs}from"node:util";import bs from"openapi-fetch";function $t(e){return bs({baseUrl:e.baseUrl,headers:e.headers,fetch:e.fetch})}var de=(e)=>({kind:"apiKey",apiKey:e});var It=(e)=>({kind:"bearer",token:e});function Ss(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 js(e){return e?{"X-Organization-Id":e}:{}}function er(e,t){return{...Ss(e),...js(t)}}function Es(e){if(typeof e!=="object"||e===null)return null;let{error:t}=e;return typeof t==="string"?t:null}class U 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 U{issues;constructor(e,t,n){super(e,t);this.issues=n}}class Te extends U{}class Re extends U{}class Ae extends U{}class He extends U{}class Fe extends U{}class Ne extends U{retryAfter;constructor(e,t,n){super(e,t);this.retryAfter=n}}class Ue extends U{}class Le extends U{}class pe extends Error{method;url;constructor(e,t){super(e,{cause:t.cause});this.name="HlixTransportError",this.method=t.method,this.url=t.url}}function Ps(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 Cs(e){let t=e.get("retry-after");if(!t)return null;let n=Number(t);return Number.isFinite(n)&&n>=0?n:null}function ue(e,t,n){let r={status:e.status,body:t,requestId:e.headers.get("x-request-id"),method:n.method,url:n.url},s=Es(t),o=`${n.method} ${n.url} failed with ${e.status}`,i=Ps(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 Te(a,r);case 401:return new Re(a,r);case 403:return new Ae(a,r);case 404:return new He(a,r);case 409:return new Fe(a,r);case 429:return new Ne(a,r,Cs(e.headers));case 501:return new Ue(a,r);default:return e.status>=500?new Le(a,r):new U(a,r)}}var tr=new Set(["GET","HEAD","PUT","DELETE","OPTIONS","TRACE"]);function ot(e){return tr.has(e.toUpperCase())}var $s=new Set([429,500,502,503,504]);function Is(e){return $s.has(e)}var xt={attempts:3,baseDelayMs:200,maxDelayMs:5000};function _t(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 Ot(e){if(!ot(e.method))return!1;if(e.attempt+1>=e.policy.attempts)return!1;return e.status===null||Is(e.status)}var xs=(e)=>new Promise((t)=>setTimeout(t,e));function _s(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 nr(e){let{base:t,policy:n}=e,r=e.sleep??xs,s=e.random??Math.random;return async(o)=>{let i=o.method.toUpperCase(),a=ot(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||!Ot({method:i,attempt:c,policy:n,status:null}))throw new pe(`${i} ${o.url}: ${d instanceof Error?d.message:String(d)}`,{method:i,url:o.url,cause:d});await r(_t(c,n,null,s));continue}if(!Ot({method:i,attempt:c,policy:n,status:p.status}))return p;if(!a)return p;await r(_t(c,n,_s(p),s))}}}function v(e,t){if(e.response.ok)return e.data;throw ue(e.response,e.error??e.data,t)}var Me=(e)=>typeof e==="string"?e:"";function Tt(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:Me(n.delta)};case"reasoning":return{type:"reasoning",delta:Me(n.delta)};case"on_tool_start":return{type:"on_tool_start",name:Me(n.name),input:n.input};case"on_tool_end":return{type:"on_tool_end",name:Me(n.name),output:n.output};case"error":return{type:"error",message:Me(n.message)};default:return null}}var Rt=(e)=>e.type==="done"||e.type==="idle"||e.type==="error";var Os=()=>({event:null,data:[],id:null,retry:null});function rr(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 or(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 sr(e,t){if(t==="")return or(e);if(t.startsWith(":"))return null;let n=t.indexOf(":");if(n===-1)return rr(e,t,""),null;let r=t.slice(0,n),s=t.slice(n+1);if(s.startsWith(" "))s=s.slice(1);return rr(e,r,s),null}function Ts(e){let t=[],n=0;for(let r=0;r<e.length;r+=1){let s=e[r];if(s!==`
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*At(e,t){let n=e.getReader(),r=new TextDecoder,s=Os(),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}=Ts(o);o=d;for(let u of p){let m=sr(s,u);if(m)yield m}if(t?.aborted)return}if(o+=r.decode(),o!==""){let c=sr(s,o);if(c)yield c}let a=or(s);if(a)yield a}finally{t?.removeEventListener("abort",i),n.releaseLock()}}class me{raw;baseUrl;headers;fetcher;constructor(e){this.baseUrl=e.baseUrl.replace(/\/+$/,""),this.headers=er(e.credential,e.organizationId);let t={...xt,...e.retry},n=e.fetch??((r)=>globalThis.fetch(r));this.fetcher=nr({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}`}}workspaces={list:async()=>v(await this.raw.GET("/v1/api/workspaces"),this.at("GET","/v1/api/workspaces"))};projects={list:async()=>v(await this.raw.GET("/v1/api/projects"),this.at("GET","/v1/api/projects")),get:async(e)=>v(await this.raw.GET("/v1/api/projects/{id}",{params:{path:{id:e}}}),this.at("GET",`/v1/api/projects/${e}`)),create:async(e)=>v(await this.raw.POST("/v1/api/projects",{body:e}),this.at("POST","/v1/api/projects")),delete:async(e)=>v(await this.raw.DELETE("/v1/api/projects/{id}",{params:{path:{id:e}}}),this.at("DELETE",`/v1/api/projects/${e}`)),start:async(e,t)=>v(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)=>v(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)=>v(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)=>v(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)=>v(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)=>v(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)=>v(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)=>v(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)=>v(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 ue(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 v(t,this.at("POST","/v1/api/imports"))},get:async(e)=>v(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 v(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)=>v(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)=>v(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 v(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 v(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)=>v(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)=>v(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)=>v(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 ue(e,n,{method:"PUT",url:t})}tasks={list:async(e)=>v(await this.raw.GET("/v1/api/tasks",{params:{query:e??{}}}),this.at("GET","/v1/api/tasks")),get:async(e)=>v(await this.raw.GET("/v1/api/tasks/{id}",{params:{path:{id:e}}}),this.at("GET",`/v1/api/tasks/${e}`)),create:async(e)=>v(await this.raw.POST("/v1/api/tasks",{body:e}),this.at("POST","/v1/api/tasks")),update:async(e,t)=>v(await this.raw.PATCH("/v1/api/tasks/{id}",{params:{path:{id:e}},body:t}),this.at("PATCH",`/v1/api/tasks/${e}`)),listComments:async(e)=>v(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)=>v(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)=>v(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)=>v(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)=>v(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)=>v(await this.raw.PUT("/v1/api/model-config/harness",{body:{harness:e}}),this.at("PUT","/v1/api/model-config/harness")),clearHarness:async()=>v(await this.raw.DELETE("/v1/api/model-config/harness"),this.at("DELETE","/v1/api/model-config/harness")),resolvedHarness:async()=>v(await this.raw.GET("/v1/api/model-config/harness/resolved"),this.at("GET","/v1/api/model-config/harness/resolved")),resolvedProjectHarness:async(e)=>v(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)=>v(await this.raw.GET("/v1/api/cycles",{params:{query:e??{}}}),this.at("GET","/v1/api/cycles")),get:async(e)=>v(await this.raw.GET("/v1/api/cycles/{id}",{params:{path:{id:e}}}),this.at("GET",`/v1/api/cycles/${e}`)),propose:async(e)=>v(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)=>v(await this.raw.GET("/v1/api/client-billing/invoices",{params:{query:e??{}}}),this.at("GET","/v1/api/client-billing/invoices")),get:async(e)=>v(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)=>v(await this.raw.POST("/v1/api/client-billing/invoices",{body:e}),this.at("POST","/v1/api/client-billing/invoices")),issue:async(e)=>v(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)=>v(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)=>v(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={})=>v(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=Tt(s.data);if(!o)continue;if(yield o,Rt(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 ue(s,o,{method:"GET",url:n})}yield*At(s.body,t?.signal)}}function Nt(e){if(e instanceof f)return{code:e.code,status:null};if(e instanceof Oe)return{code:"invalid_request",status:400};if(e instanceof Te)return{code:"bad_request",status:400};if(e instanceof Re)return{code:"unauthenticated",status:401};if(e instanceof Ae)return{code:"forbidden",status:403};if(e instanceof He)return{code:"not_found",status:404};if(e instanceof Fe)return{code:"conflict",status:409};if(e instanceof Ne)return{code:"rate_limited",status:429};if(e instanceof Ue)return{code:"not_implemented",status:501};if(e instanceof Le)return{code:"server_error",status:e.status};if(e instanceof pe)return{code:"unreachable",status:null};return{code:"unknown",status:null}}var Ht=(e)=>e instanceof Error?e.message:String(e);function Fs(e,t){let n=B({env:e,flags:t.flags,cwd:t.cwd});if(n.conflict)throw new f("workspace_mismatch",n.conflict);if(!n.credential)throw new f("unauthenticated","No credential. Run `hlix auth login`, or set HLIX_API_KEY for CI.");return new me({baseUrl:n.baseUrl,credential:n.credential.sessionToken?It(n.credential.sessionToken):de(n.credential.apiKey),...n.workspaceId?{organizationId:n.workspaceId}:{}})}function ir(e){let t=Math.max(...e.map((r)=>r.name.length));return`hlix — the hlix control-plane CLI
13
+
14
+ Usage:
15
+ hlix <command> [options]
16
+
17
+ Commands:
18
+ ${[` hlix ${"".padEnd(t)} Open Hlix Code (interactive)`,...e.map((r)=>` hlix ${r.name.padEnd(t)} ${r.summary}`)].join(`
19
+ `)}
20
+
21
+ Options:
22
+ --json Machine-readable output (a versioned, stable contract)
23
+ --cwd <dir> Operate on another directory instead of the current one
24
+ --workspace <id> Workspace to act in, overriding the folder's binding
25
+ --base-url <url> API to talk to, overriding the folder's binding
26
+ --help Show this help
27
+ --version Show the installed CLI version
28
+
29
+ A command targets the workspace named by, in order: an explicit flag, the
30
+ HLIX_* environment, the nearest .hlix/config.json, then the stored credential.
31
+ Run \`hlix status\` to see which one applied.
32
+ `}function Ns(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 Us(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",...Ft(e,o)?.command.options??[]]),a=null;for(let c of i){let l=Ns(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 Ft(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 wa(e,t,n){if(t.some((E)=>E==="--api-key"||E.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=Hs({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(E){let R=t.includes("--json"),H=Us(e,t,Ht(E));if(R)n.stdout(y(Ee("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:E}=await import("./package-f3wbdpaa.js");return n.stdout(`${E}
35
+ `),0}if(o.length===0||r.values.help===!0){let E=Ft(e,o);return n.stdout(E?`${E.command.usage}
36
+ `:ir(e)),o.length===0&&r.values.help!==!0?1:0}let i=Ft(e,o);if(!i){let E=o.join(" ");if(s)n.stdout(y(Ee(E,{code:"unknown_command",message:`Unknown command: ${E}`,status:null})));else n.stderr(`Unknown command: ${E}
37
+
38
+ ${ir(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(([E,R])=>R!==void 0&&!a.has(E)&&!c.has(E)).map(([E])=>`--${E}`),p=i.command.args??{min:0,max:0},d=i.rest.length<p.min?{code:"missing_argument",message:i.command.usage.split(`
39
+ `)[0]}:i.rest.length>p.max?{code:"invalid_usage",message:i.command.usage.split(`
40
+ `)[0]}:null,u=typeof r.values.cwd==="string"?r.values.cwd:void 0,m=As(u??"."),w=u!==void 0&&!Qn(m)?{code:"invalid_usage",message:`--cwd is not a directory: ${m}`}:null,b=l.length>0?{code:"invalid_usage",message:`Unsupported option for ${i.command.name}: ${l.join(", ")}`}:w??d;if(b){if(s)n.stdout(y(Ee(i.command.name,{...b,status:null})));else n.stderr(`error: ${b.message}
41
+
42
+ ${i.command.usage}
43
+ `);return 2}let T=r.values,D={...n,args:i.rest,json:s,flags:T,cwd:m,requireClient:(E)=>Fs(n.env,{cwd:E??m,flags:T})};try{return await i.command.run(D)}catch(E){let{code:R,status:H}=Nt(E);if(s)n.stdout(y(Ee(i.command.name,{code:R,message:Ht(E),status:H})));else n.stderr(`error: ${Ht(E)}
44
+ `);return R==="unauthenticated"||R==="forbidden"?3:1}}import{readFileSync as Ls}from"node:fs";import{homedir as Ms}from"node:os";import{join as Bs}from"node:path";var ar=["cloud","docker","local"],fe=["claude-code","codex","cursor-agent","hlix"],Ia="hlix",cr={harness:"local and docker sandboxes only",model:"all sandboxes",sandbox:"all sandboxes"},ge=["harness","model","sandbox"],Ut=["projectId","workspaceId","apiUrl"];function Lt(e=process.env){return Bs(e.HLIX_CONFIG_HOME??Ms(),".hlix","config.json")}function lr(e=process.env){try{let t=JSON.parse(Ls(Lt(e),"utf8"));return t.schemaVersion===1?t:null}catch{return null}}function Mt(e,t=process.env){let n=lr(t),r=O(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 Ut){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:Lt(t),project:s?Ie(s):null}}}function dr(e){return[...ge,...Ut].map((n)=>({key:n,value:e.merged[n]??null,source:e.sources[n]??"default"}))}function Ks(e,t){if(e==="sandbox"&&!ar.includes(t))return`sandbox must be one of ${ar.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 Bt(e){if(ge.includes(e))return e;let t=Ut.includes(e);throw new f("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 pr(e,t){let n=Ks(e,t);if(n)throw new f("invalid_usage",n);return t}function ur(e){if(e.scope==="global"){let r=Lt(e.env),s=lr(e.env)??{schemaVersion:1};return $e(r,{...s,[e.key]:e.value}),r}let t=O(e.cwd);if(!t)throw new f("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}async function zs(e,t,n){let r=t.map((a)=>a.id);if(n){if(!r.includes(n))throw new f("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 f("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})
45
+ `),s.id;if(e.json||!e.promptChoice)throw new f("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(`
46
+ `)}
47
+ `);let i=await e.promptChoice(`Workspace [1-${t.length}]: `,t.length);return r[i]}var Kt={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(`
48
+ `),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 f("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??Ct,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 f("invalid_base_url","--base-url must use HTTPS (HTTP is allowed only for localhost).");let i=new me({baseUrl:r,credential:de(n),retry:{attempts:1}}),a=await zs(e,await i.workspaces.list(),t);await new me({baseUrl:r,credential:de(n),organizationId:a,retry:{attempts:1}}).projects.list();let l=Gn({baseUrl:r,apiKey:n,organizationId:a},e.env);if(e.json)e.stdout(y(k(Kt.name,{baseUrl:r,organizationId:a,credentialPath:l})));else e.stdout(`Signed in to ${r}
49
+ Credential stored at ${l}
50
+ `);return 0}},zt={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(`
51
+ `),supportsJson:!0,async run(e){let t=B({env:e.env,flags:e.flags,cwd:e.cwd});if(t.conflict)throw new f("workspace_mismatch",t.conflict);if(!t.credential)throw new f("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}
52
+ `),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(y(k(zt.name,n))),0;return e.stdout(`${_([["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"]])}
53
+ `),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(`
54
+ `),supportsJson:!0,options:["yes"],async run(e){let t=B({env:e.env,flags:e.flags,cwd:e.cwd});if(t.credentialSource==="env"){let r=Jn(e.env);if(!r){let o={removed:!1,reason:"environment",path:null};if(e.json)e.stdout(y(k(he.name,o)));else e.stdout(`HLIX_API_KEY is set in this environment; unset it there to sign out.
55
+ `);return 0}if(e.flags.yes!==!0){let o={removed:!1,reason:"environment",path:r};if(e.json)e.stdout(y(k(he.name,o)));else e.stdout(`HLIX_API_KEY is set in this environment; unset it there to sign out.
56
+ A stored credential also exists at ${r} — repeat with --yes to remove it.
57
+ `);return 0}let s=Et(e.env);if(e.json)e.stdout(y(k(he.name,s)));else e.stdout(`Removed ${s.path}
58
+ HLIX_API_KEY is still set in this environment; unset it there to finish signing out.
59
+ `);return 0}if(e.flags.yes!==!0&&t.credential){if(e.json||!e.confirm)throw new f("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 f("cancelled","Logout cancelled.")}let n=Et(e.env);if(e.json)e.stdout(y(k(he.name,n)));else e.stdout(n.removed?`Removed ${n.path}
60
+ `:`No stored credential at ${n.path}
61
+ `);return 0}};var mr=ge.join(" | "),qt={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(`
62
+ `),supportsJson:!0,async run(e){let t=Mt(e.cwd,e.env),n=dr(t);if(e.json)return e.stdout(y(k(qt.name,{settings:n,paths:t.paths}))),0;return e.stdout(`${W(["setting","value","source","applies to"],n.map((r)=>[r.key,r.value??"-",r.source,cr[r.key]??"this folder's binding"]))}
63
+ `),e.stdout(`
64
+ global ${t.paths.global}
65
+ `),e.stdout(`project ${t.paths.project??"- (this folder is not bound to hlix)"}
66
+ `),0}},Dt={name:"config get",summary:"Print one setting's effective value",usage:[`Usage: hlix config get <${mr}> [--cwd <dir>] [--json]`,"","Prints the value the cascade resolves for one key, or exits 1 when no","file names it."].join(`
67
+ `),supportsJson:!0,args:{min:1,max:1},async run(e){let t=Bt(e.args[0]),n=Mt(e.cwd,e.env),r=n.merged[t]??null,s=n.sources[t]??"default";if(e.json)return e.stdout(y(k(Dt.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>\`.
68
+ `),1;return e.stdout(`${r}
69
+ `),0}},Jt={name:"config set",summary:"Set one setting for this folder, or for the machine with --global",usage:[`Usage: hlix config set <${mr}> <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(`
70
+ `),supportsJson:!0,options:["global"],args:{min:2,max:2},async run(e){let t=Bt(e.args[0]),n=pr(t,e.args[1]),r=e.flags.global===!0?"global":"project",s=ur({key:t,value:n,scope:r,cwd:e.cwd,env:e.env});if(e.json)return e.stdout(y(k(Jt.name,{key:t,value:n,scope:r,path:s}))),0;return e.stdout(`${t} = ${n} (${r}: ${s})
71
+ `),0}};function ne(e,t){if(typeof e!=="object"||e===null)return"";let n=e[t];return n===null||n===void 0?"":String(n)}var Gt={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(y(k(Gt.name,t))),0;let n=Array.isArray(t)?t:[];if(n.length===0)return e.stdout(`No projects.
72
+ `),0;return e.stdout(`${W(["ID","NAME","STACK"],n.map((r)=>[ne(r,"id"),ne(r,"name"),ne(r,"stack")]))}
73
+ `),0}},Wt={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(`
74
+ `),supportsJson:!0,args:{min:0,max:1},async run(e){let t=e.args[0]??O(e.cwd)?.config.projectId;if(!t)throw new f("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(y(k(Wt.name,n))),0;let r=n.repos;return e.stdout(`${_([["id",ne(n,"id")],["name",ne(n,"name")],["stack",ne(n,"stack")],["status",ne(n,"status")],["repos",Array.isArray(r)?String(r.length):""]].filter(([,s])=>s!==""))}
75
+ `),0}};function Vt(e,t){let n=e.args[0];if(!n)throw new f("missing_argument",`A ${t} id is required.`);return n}function fr(e,t){let n=e.flags[t];return typeof n==="string"&&n.trim()?n.trim():void 0}function K(e,t){if(typeof e!=="object"||e===null)return"";let n=e[t];return n===null||n===void 0?"":String(n)}var Xt={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(`
76
+ `),supportsJson:!0,options:["project","status"],async run(e){let t=fr(e,"project")??O(e.cwd)?.config.projectId,n=fr(e,"status"),r=await e.requireClient().tasks.list({...t?{projectId:t}:{},...n?{status:n}:{}});if(e.json)return e.stdout(y(k(Xt.name,r))),0;let s=Array.isArray(r)?r:[];if(s.length===0)return e.stdout(`No tasks.
77
+ `),0;return e.stdout(`${W(["ID","STATUS","TITLE"],s.map((o)=>[K(o,"id"),K(o,"status"),K(o,"title")||K(o,"description").split(`
78
+ `)[0]||""]))}
79
+ `),0}},Yt={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=Vt(e,"task"),n=await e.requireClient().tasks.get(t);if(e.json)return e.stdout(y(k(Yt.name,n))),0;return e.stdout(`${_([["id",K(n,"id")],["status",K(n,"status")],["title",K(n,"title")],["project",K(n,"projectId")],["description",K(n,"description")]])}
80
+ `),0}},Zt={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=Vt(e,"task"),n=await e.requireClient().tasks.review(t);if(e.json)return e.stdout(y(k(Zt.name,n))),0;return e.stdout(`${JSON.stringify(n,null,2)}
81
+ `),0}},Qt={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(`
82
+ `),supportsJson:!0,args:{min:1,max:1},async run(e){let t=Vt(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(k(Qt.name,s))}
83
+ `);else{let o=K(s,"status"),i=K(s,"error");e.stdout(i?`error: ${i}
84
+ `:`${o||r.data}
85
+ `)}}return 0}};import{realpath as Po}from"node:fs/promises";import{resolve as Co}from"node:path";import{createHash as Pr}from"node:crypto";import{createReadStream as Vs}from"node:fs";import{lstat as Cr,readFile as at,readdir as Xs,realpath as $r,stat as Ys}from"node:fs/promises";import{basename as se,join as Ir,relative as kr,resolve as br,sep as Zs}from"node:path";import{spawnSync as Qs}from"node:child_process";import Sr from"ignore";import{readFile as Ds}from"node:fs/promises";import{join as Js}from"node:path";function qs(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 gr(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=qs(l[2]);if(d===null)s=!0;else r[r.length-1][p]=d}return{tasks:r,partial:s}}async function re(e,t){try{return await Ds(Js(e,...t.split("/")),"utf8")}catch(n){if(n.code==="ENOENT")return null;throw n}}function hr(e){try{let t=e.replace(/(^|[^:\\])\/\/.*$/gm,"$1").replace(/\/\*[\s\S]*?\*\//g,"").replace(/,\s*([}\]])/g,"$1");return JSON.parse(t)}catch{return null}}function Q(e){if(typeof e==="string"&&e.trim())return[e.trim()];if(Array.isArray(e))return e.flatMap(Q);if(e&&typeof e==="object")return Object.values(e).flatMap(Q);return[]}function en(e){if(!e||typeof e!=="object")return[];return Object.keys(e).filter((t)=>/^[A-Za-z_][A-Za-z0-9_]*$/.test(t))}function Gs(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 Ws(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 yr(e){let t=typeof e==="number"?e:Number(e);return Number.isInteger(t)&&t>0&&t<=65535?t:null}function L(e,t,n){if(!e.some((r)=>r.path===t&&r.kind===n))e.push({path:t,kind:n})}async function wr(e,t,n){let r=[],s=[],o=[],i=[],a=new Map,c=new Set,l=new Set,p=[],d={},u=null,m=0,w=await re(e,".cursor/environment.json");if(w){L(r,".cursor/environment.json","cursor");let g=hr(w);if(!g)p.push("Could not parse .cursor/environment.json; it remains quarantined.");else{s.push(...Q(g.install));let P=Q(g.start);if(P[0])u=P[0];if(Array.isArray(g.terminals))for(let S of g.terminals){if(!S||typeof S!=="object")continue;let I=S;if(typeof I.command!=="string"||!I.command.trim())continue;i.push({name:typeof I.name==="string"&&I.name.trim()?I.name.trim():"Terminal",command:I.command.trim(),...typeof I.cwd==="string"&&I.cwd.trim()?{cwd:I.cwd.trim()}:{}})}}}let b=t.has(".devcontainer/devcontainer.json")?".devcontainer/devcontainer.json":t.has("devcontainer.json")?"devcontainer.json":null;if(b){L(r,b,"devcontainer");let g=hr(n.get(b)??await re(e,b)??"");if(!g)p.push(`Could not parse ${b}; it remains quarantined.`);else{s.push(...Q(g.onCreateCommand),...Q(g.updateContentCommand),...Q(g.postCreateCommand));let P=Q(g.postStartCommand);if(!u&&P[0])u=P[0];for(let S of en(g.secrets))c.add(S);for(let S of[...en(g.containerEnv),...en(g.remoteEnv)])c.add(S);if(Array.isArray(g.forwardPorts))for(let S of g.forwardPorts){let I=yr(S);if(I)a.set(I,{port:I,visibility:"private"})}}}if(t.has(".gitpod.yml")){L(r,".gitpod.yml","gitpod");let g=n.get(".gitpod.yml")??await re(e,".gitpod.yml");if(g===null)p.push("Could not read .gitpod.yml; its task commands were not imported.");else{let P=gr(g);m=P.tasks.filter((S)=>S.before).length;for(let S of P.tasks){if(S.before)s.push(S.before);if(S.init)s.push(S.init);if(!S.command)continue;if(!u)u=S.command;else i.push({name:S.name??"Terminal",command:S.command})}if(P.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 g of["Dockerfile","docker-compose.yml","docker-compose.yaml","compose.yml","compose.yaml"])if(t.has(g))L(r,g,"docker");for(let g of["project.toml","nixpacks.toml","railpack.json","Aptfile"])if(t.has(g))L(r,g,"buildpack");for(let g of["fly.toml","railway.json","render.yaml","vercel.json","netlify.toml"])if(t.has(g))L(r,g,"platform");let T=n.get("package.json")??await re(e,"package.json");if(T){L(r,"package.json","package");try{let g=JSON.parse(T);if(g.engines?.node)d.node=g.engines.node;let P=Ws(t,g.packageManager);if(P&&s.length===m)s.push(P);if(g.scripts?.build&&o.length===0)o.push(`${g.packageManager?.split("@")[0]??(t.has("bun.lock")?"bun":"npm")} run build`);let S=g.scripts?.dev?`${t.has("bun.lock")?"bun":"npm"} run dev`:null,I=g.scripts?.start?`${t.has("bun.lock")?"bun":"npm"} run start`:S;if(!u&&I)u=I}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")){L(r,"Procfile","procfile");let P=(n.get("Procfile")??"").split(/\r?\n/).find((S)=>/^web\s*:/.test(S));if(P)u=P.replace(/^web\s*:\s*/,"").trim()||u}let D=[[".node-version","node"],[".nvmrc","node"],[".python-version","python"]];for(let[g,P]of D){let S=(n.get(g)??await re(e,g))?.trim();if(S)d[P]=S,L(r,g,"tool-version")}let E=n.get(".tool-versions")??await re(e,".tool-versions");if(E){L(r,".tool-versions","tool-version");for(let g of E.split(/\r?\n/)){let[P,S]=g.trim().split(/\s+/,2);if(!S)continue;if(P==="nodejs")d.node=S;else if(P==="python")d.python=S;else if(P==="bun")d.bun=S}}let R=n.get("mise.toml")??await re(e,"mise.toml");if(R){L(r,"mise.toml","tool-version");for(let g of R.matchAll(/^\s*(node|python|bun)\s*=\s*["']([^"']+)["']/gm))d[g[1]]=g[2]}for(let[g,P]of n){let S=/(?:^|\/)(?:Dockerfile|Procfile)$/i.test(g)||/\.(?:jsonc?|ya?ml|toml|ini|conf|config|env|sh|bash|zsh|fish)$/i.test(g);for(let I of Gs(P,S))l.add(I);for(let I of P.matchAll(/(?:--port(?:=|\s+)|PORT\s*=\s*)(\d{2,5})/g)){let z=yr(I[1]);if(z)a.set(z,{port:z,visibility:"private"})}}if(r.length===0&&t.size>0)L(r,"repository","detected");let H=(g)=>[...new Set(g.filter(Boolean))],ke=r.length+s.length+(u?1:0);return{sources:r.sort((g,P)=>g.path.localeCompare(P.path)),toolchain:d,install:H(s),build:H(o),start:u,terminals:i,ports:[...a.values()].sort((g,P)=>g.port-P.port),requiredSecretKeys:[...c].sort(),observedSecretKeys:[...l].sort(),confidence:ke>=4?"high":ke>=2?"medium":"low",warnings:p}}var vr=2;var eo=25000,to=52428800,no=524288000,ct=1e4,it=1048576,ye=10485760,jr=[".git/",".hlix/","node_modules/",".next/",".turbo/",".cache/","dist/","build/","coverage/","__pycache__/",".venv/","venv/","target/",".DS_Store"],rn="Required project environment value was not found locally: ",ro=/(^|\/)\.env\.(example|sample|template)$/i,so=/(^|\/)\.env(?:\.[^/]+)?$/i,oo=/(^|\/)(?:\.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,io=/(^|\/)(?:\.mcp\.json|mcp\.json|claude_desktop_config\.json)$/i,ao=/(^|\/)(?:AGENTS\.md|CLAUDE\.md|\.cursorrules|\.github\/copilot-instructions\.md)$/i,co=/(^|\/)(?:\.agents|\.claude)\/skills\//i,lo=/-----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,}/,po=/\.(?:json|ya?ml|toml|ini|conf|config)$/i,uo=/(?:^|[,{\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,Be=/^HLIX_[A-Za-z0-9_]*$/,tn=new Set(["CI","HOME","LANG","LOGNAME","NODE_ENV","OLDPWD","PATH","PORT","PWD","SHELL","SHLVL","TERM","TMPDIR","USER","_"]);function Ke(e){return e.split(Zs).join("/")}function ee(e,t,n=10485760){return Qs("git",["-C",e,...t],{encoding:"utf8",maxBuffer:n,stdio:["ignore","pipe","pipe"]})}async function mo(e){let t=Pr("sha256");for await(let n of Vs(e))t.update(n);return t.digest("hex")}function nn(e){if(Array.isArray(e))return`[${e.map(nn).join(",")}]`;if(e&&typeof e==="object")return`{${Object.entries(e).sort(([t],[n])=>t.localeCompare(n)).map(([t,n])=>`${JSON.stringify(t)}:${nn(n)}`).join(",")}}`;return JSON.stringify(e)}function xr(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,`
86
+ `).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 fo(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 go(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),fo(l)){delete t[c],r.add(c);continue}try{let d=xr(`${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 ho(e){let t=ee(e,["rev-parse","--show-toplevel"]);if(t.status!==0)return!1;try{return await $r(t.stdout.trim())===e}catch{return!1}}function yo(e,t){if(!t)return new Set;let n=ee(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(Ke))}async function wo(e){let t=Sr().add(jr),n=Sr().add(jr);for(let r of[".gitignore",".hlixignore"])try{let s=Ir(e,r);if((await Cr(s)).isFile())n.add(await at(s,"utf8"))}catch(s){if(s.code!=="ENOENT")throw s}return{hardMatcher:t,matcher:n}}function vo(e){if(io.test(e))return"mcp";if(co.test(e))return"skill";if(ao.test(e))return"agent";return null}function ko(e){if(so.test(e)&&!ro.test(e))return"dotenv";if(oo.test(e))return"credential";return null}function bo(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 So(e,t){if(t)return[Ke(t)];let n=new Map([[".env",0],[".env.development",1],[".env.local",2],[".env.development.local",3]]),r=e.filter((s)=>n.has(se(s).toLocaleLowerCase("en-US"))).sort((s,o)=>s.slice(0,-se(s).length).localeCompare(o.slice(0,-se(o).length))||n.get(se(s).toLocaleLowerCase("en-US"))-n.get(se(o).toLocaleLowerCase("en-US")));return r.length>0?r:e.length===1?[...e]:[]}function jo(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 Er(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:Ke(s.trim()),reason:t});if(n.length>=100)break}return n}function Eo(e,t){if(!t)return{head:null,branch:null,refs:[],commitCount:0,complete:!0,findings:[]};let n=ee(e,["rev-parse","HEAD"]).stdout.trim()||null,r=ee(e,["symbolic-ref","--short","-q","HEAD"]),s=r.status===0?r.stdout.trim()||null:null,o=Number.parseInt(ee(e,["rev-list","--count","--all"]).stdout.trim(),10)||0,i=ee(e,["for-each-ref","--format=%(refname)%00%(objectname)","refs/heads","refs/tags"]),a=i.stdout.split(`
87
+ `).filter(Boolean).map((u)=>{let[m,w]=u.split("\x00");return{name:m,oid:w}}).filter(({name:u,oid:m})=>/^refs\/(?:heads|tags)\/.+/.test(u)&&/^[0-9a-f]{40,64}$/.test(m)).sort((u,m)=>u.name.localeCompare(m.name)),c=["log","--all",`--max-count=${ct}`,"--pretty=format:@@%H","--name-only"],l=ee(e,[...c,"--",".env",".env.*","*.pem","*.key",".npmrc","*.tfvars"]),p=ee(e,["log","--all",`--max-count=${ct}`,"-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 u of[...Er(l.stdout,"sensitive-path"),...Er(p.stdout,"secret-pattern")])d.set(`${u.commit}:${u.path}:${u.reason}`,u);return{head:n,branch:s,refs:a,commitCount:o,complete:o<=ct&&a.length<=1000&&i.status===0&&l.status===0&&p.status===0,findings:[...d.values()].slice(0,100)}}async function q(e,t={}){let n=await $r(br(e));if(!(await Ys(n)).isDirectory())throw Error("Import target must be a directory.");let r=await ho(n),s=yo(n,r),{hardMatcher:o,matcher:i}=await wo(n),a=[],c=[],l=[],p=[],d=[],u=[],m=t.envFile?Ke(kr(n,br(n,t.envFile))):void 0,w=m!==void 0&&m!==""&&m!==".."&&!m.startsWith("../");if(t.envFile&&!w)u.push(`Selected environment file must stay inside the project: ${t.envFile}`);let b=new Map,T=new Map,D=new Map,E=new Map,R=[],H=[],ke=new Map,g=t.maxFiles??eo,P=t.maxFileBytes??to,S=t.maxTotalBytes??no,I=0,z=0,An=async(h)=>{let j=await Xs(h,{withFileTypes:!0});j.sort((x,F)=>x.name.localeCompare(F.name));for(let x of j){let F=Ir(h,x.name),C=Ke(kr(n,F));if(x.name===".git"){if(C!==".git")u.push(`Nested Git repository is not supported: ${C}`);continue}let M=await Cr(F),Un=x.isDirectory()?`${C}/`:C,kt=s.has(C),Ln=!kt&&i.ignores(Un),rs=!kt&&o.ignores(Un);if(M.isSymbolicLink()){if(d.push({path:C,reason:"symlink"}),!Ln)u.push(`Symlinks are not imported in this release: ${C}`);continue}if(x.isDirectory()){if(rs)continue;await An(F);continue}let Se=vo(C),je=ko(C);if(Ln&&!Se&&!je)continue;if(!x.isFile()){d.push({path:C,reason:"non-regular-file"});continue}if(a.length+c.length+l.length>=g){u.push(`Project exceeds the ${g} file limit.`);return}if(M.size>P){u.push(`File exceeds the ${P} byte limit: ${C}`);continue}if(I+=M.size,I>S){u.push(`Project exceeds the ${S} byte total limit.`);return}let Ye=await mo(F);if(Se){if(M.size>it){u.push(`Protected configuration exceeds the ${it} byte limit: ${C}`);continue}let N=await at(F);if(z+=N.byteLength,z>ye){u.push(`Protected project files exceed the ${ye} byte total limit.`);continue}if(l.push({path:C,kind:Se,size:M.size,sha256:Ye}),H.push({path:C,kind:Se,contentBase64:N.toString("base64")}),Se==="mcp")p.push(...jo(C,N.toString("utf8")));continue}if(je){if(M.size>it){u.push(`Protected file exceeds the ${it} byte limit: ${C}`);continue}let N=await at(F);if(z+=N.byteLength,z>ye){u.push(`Protected project files exceed the ${ye} byte total limit.`);continue}let te=[];if(je==="dotenv")try{let Ze=xr(N),ie={};for(let[Z,ae]of Object.entries(Ze)){if(Be.test(Z)){u.push(`Hlix control-plane environment keys cannot be imported into a project: ${Z}`);continue}ie[Z]=ae}b.set(C,ie),te=Object.keys(ie).sort()}catch{u.push(`Could not parse environment file: ${C}`)}else if(se(C)===".envrc"){let Ze=go(N),ie={},Z=new Set,ae=[];for(let[A,ss]of Object.entries(Ze.values)){if(Be.test(A)){u.push(`Hlix control-plane environment keys cannot be imported into a project: ${A}`);continue}if(tn.has(A)){R.push(`Ignored ambient runtime assignment in ${C}: ${A}`);continue}Z.add(A),ie[A]=ss}T.set(C,ie);for(let A of Ze.dynamicKeys){if(Be.test(A)){u.push(`Hlix control-plane environment keys cannot be imported into a project: ${A}`);continue}if(tn.has(A)){R.push(`Ignored ambient runtime assignment in ${C}: ${A}`);continue}Z.add(A),ae.push(A)}if(D.set(C,[...Z].sort()),E.set(C,ae.sort()),te=[...Z].sort(),ae.length>0)R.push(`Did not execute dynamic .envrc assignments; collect their resolved local values when available: ${ae.join(", ")}`)}c.push({path:C,kind:je,keys:te,size:M.size,sha256:Ye}),H.push({path:C,kind:je,contentBase64:N.toString("base64")});continue}if(M.size<=1048576){let N=await at(F),te=N.toString("utf8");if(ke.set(C,te),lo.test(te)||po.test(C)&&uo.test(te)){if(z+=N.byteLength,z>ye){u.push(`Protected project files exceed the ${ye} byte total limit.`);continue}c.push({path:C,kind:"detected-content",keys:[],size:M.size,sha256:Ye}),H.push({path:C,kind:"detected-content",contentBase64:N.toString("base64")});continue}}a.push({path:C,size:M.size,sha256:Ye,tracked:kt,executable:(M.mode&73)!==0})}};await An(n),a.sort((h,j)=>h.path.localeCompare(j.path)),c.sort((h,j)=>h.path.localeCompare(j.path)),l.sort((h,j)=>h.path.localeCompare(j.path)),p.sort((h,j)=>`${h.sourcePath}:${h.name}`.localeCompare(`${j.sourcePath}:${j.name}`));let ht=So([...b.keys()].sort(),w?m:void 0);if(t.envFile&&w&&!b.has(ht[0]))u.push(`Selected environment file was not found or is not a dotenv file: ${t.envFile}`);let be=new Map;for(let[h,j]of b)for(let x of Object.keys(j))be.set(x,[...be.get(x)??[],h]);for(let[h,j]of D)for(let x of j)be.set(x,[...be.get(x)??[],h]);let Zr=[...be].filter(([,h])=>h.length>1).map(([h,j])=>({key:h,paths:j.sort()})).sort((h,j)=>h.key.localeCompare(j.key)),J={};for(let h of ht)Object.assign(J,b.get(h)??{});let Qr=[...T.keys()].sort((h,j)=>{if(h===".envrc")return 1;if(j===".envrc")return-1;return h.localeCompare(j)}),yt=new Set;for(let h of Qr){let j=new Set(E.get(h)??[]);for(let x of D.get(h)??[]){if(j.has(x)){delete J[x],yt.add(x);continue}let F=T.get(h)?.[x];if(F!==void 0)J[x]=F;yt.delete(x)}}let wt=t.historyMode??"abort_on_findings",Y=Eo(n,r);if(!Y.complete&&wt!=="preserve")u.push(`Git history scan exceeded ${ct} commits or failed; import requires explicit --history preserve.`);if(Y.findings.length>0&&wt==="abort_on_findings")u.push("Potential secrets exist in Git history. Abort, sanitize the repository, or explicitly use --history preserve.");let Hn=new Set(a.map((h)=>h.path)),es=await wr(n,Hn,ke),{observedSecretKeys:ts,...G}=es;G.warnings.push(...R);let vt=new Set(G.requiredSecretKeys);for(let h of yt)vt.add(h);for(let h of p)for(let j of h.envKeys)vt.add(j);G.requiredSecretKeys=[...vt].sort();for(let h of G.requiredSecretKeys){if(Be.test(h)){u.push(`Hlix control-plane environment keys cannot be imported into a project: ${h}`);continue}if(J[h]!==void 0)continue;let j=t.environment?.[h];if(j===void 0){u.push(`${rn}${h}`);continue}J[h]=j}for(let h of ts){if(Be.test(h)){G.warnings.push(`Ignored reserved Hlix control-plane environment reference: ${h}`);continue}if(tn.has(h))continue;if(J[h]!==void 0)continue;let j=t.environment?.[h];if(j===void 0){G.warnings.push(`Observed environment reference has no local value: ${h}`);continue}J[h]=j}G.warnings=[...new Set(G.warnings)].sort();let Fn={schemaVersion:vr,rootName:t.rootName??se(n),stack:bo(Hn),git:{detected:r,head:Y.head,branch:Y.branch,refs:Y.refs,commitCount:Y.commitCount,historyScanComplete:Y.complete,historyMode:wt},files:a,secretFiles:c,activeEnvFiles:ht,secretKeys:Object.keys(J).sort(),envCollisions:Zr,quarantinedResources:l,mcpServers:p,historicalSecretFindings:Y.findings,skipped:d,environment:G,totals:{files:a.length,bytes:a.reduce((h,j)=>h+j.size,0)}},Nn=nn(Fn),ns=Pr("sha256").update(Nn).digest("hex");return{root:n,manifest:Fn,manifestJson:Nn,manifestSha256:ns,secretValues:J,protectedFiles:H.sort((h,j)=>h.path.localeCompare(j.path)),blocking:[...new Set(u)]}}var sn={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(`
88
+ `),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 Po(Co(e.cwd,e.args[0]??".")),n=B({env:e.env,flags:e.flags,cwd:t});if(n.conflict)throw new f("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=le(t),o=typeof e.flags.project==="string"?e.flags.project:void 0;if(o&&s?.projectId&&s.projectId!==o)throw new f("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 q(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(y(k(sn.name,c)));else if(e.stdout(`Initialized ${t}
89
+ Project: ${i.projectId??"not imported yet"}
90
+ Workspace: ${i.workspaceId}
91
+ `),a.blocking.length)e.stdout(`
92
+ Review before import:
93
+ ${a.blocking.map((l)=>`- ${l}`).join(`
94
+ `)}
95
+ `);return 0}};import{createHash as Ho}from"node:crypto";import{readFile as Fo,realpath as No}from"node:fs/promises";import{basename as Uo,resolve as Lo}from"node:path";import{createHash as $o}from"node:crypto";import{createReadStream as Io}from"node:fs";import{chmod as on,copyFile as xo,lstat as _r,mkdir as Or,mkdtemp as _o,readdir as Oo,rm as an}from"node:fs/promises";import{tmpdir as To}from"node:os";import{dirname as Ro,join as oe}from"node:path";import{spawnSync as ze}from"node:child_process";function V(e,t){let n=ze("git",["-C",e,...t],{encoding:"utf8",maxBuffer:20971520,stdio:["ignore","pipe","pipe"]});if(n.status!==0){let r=n.stderr.trim().split(`
96
+ `).at(-1)??"git command failed";throw Error(r)}return n.stdout.trim()}async function Tr(e){let t=$o("sha256");for await(let n of Io(e))t.update(n);return t.digest("hex")}async function Ao(e){for(let t of await Oo(e)){if(t===".git")continue;await an(oe(e,t),{recursive:!0,force:!0})}}async function lt(e){if(e.blocking.length>0)throw Error(`Project scan has blocking findings:
97
+ - ${e.blocking.join(`
98
+ - `)}`);let t=await _o(oe(To(),"hlix-snapshot-"));await on(t,448);let n=oe(t,"repo"),r=oe(t,"source.git"),s=oe(t,"project.bundle");try{if(e.manifest.git.detected){let d=ze("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 u=new Map(V(r,["for-each-ref","--format=%(refname)%00%(objectname)","refs/heads","refs/tags"]).split(`
99
+ `).filter(Boolean).map((w)=>w.split("\x00",2)));for(let w of e.manifest.git.refs)if(u.get(w.name)!==w.oid)throw Error(`Git ref changed after scan: ${w.name}`);let m=ze("git",["clone","--no-hardlinks",r,n],{encoding:"utf8",stdio:["ignore","pipe","pipe"]});if(m.status!==0)throw Error(m.stderr.trim()||"Could not create snapshot clone.");if(!e.manifest.git.head)throw Error("Git repository has no HEAD commit.");V(n,["checkout","-B","main",e.manifest.git.head])}else await Or(n,{recursive:!0,mode:448}),V(n,["init","-b","main"]);await Ao(n);for(let d of e.manifest.files){let u=oe(e.root,...d.path.split("/")),m=await _r(u);if(!m.isFile()||m.isSymbolicLink())throw Error(`Source changed after scan: ${d.path}`);if(m.size!==d.size||await Tr(u)!==d.sha256)throw Error(`Source changed after scan: ${d.path}`);let w=oe(n,...d.path.split("/"));await Or(Ro(w),{recursive:!0,mode:493}),await xo(u,w),await on(w,d.executable?493:420)}V(n,["config","user.name","Hlix Import"]),V(n,["config","user.email","import@hlix.ai"]),V(n,["add","-A"]),V(n,["commit","--allow-empty","-m","chore(hlix): import snapshot"]);let o=V(n,["rev-parse","HEAD"]),i=e.manifest.git.refs.filter((d)=>d.name!=="refs/heads/main");if(i.length>0){let d=ze("git",["-C",n,"update-ref","--stdin"],{encoding:"utf8",input:i.map((u)=>`update ${u.name} ${u.oid}`).join(`
100
+ `)+`
101
+ `,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=ze("git",["-C",n,"bundle","create",s,"--stdin"],{encoding:"utf8",input:["refs/heads/main",...a].join(`
102
+ `)+`
103
+ `,stdio:["pipe","pipe","pipe"]});if(c.status!==0)throw Error(c.stderr.trim()||"Could not create the approved Git bundle.");V(n,["bundle","verify",s]),await on(s,384);let l=(await _r(s)).size,p=await Tr(s);return{bundlePath:s,bundleSha256:p,bundleSize:l,commitSha:o,dispose:()=>an(t,{recursive:!0,force:!0})}}catch(o){throw await an(t,{recursive:!0,force:!0}),o}}function qe(e,t){let n=e[t];return typeof n==="string"&&n.trim()?n.trim():void 0}function Mo(e,t){return Ho("sha256").update(`project-import-v1\x00${e}\x00${t}`).digest("hex")}function Bo(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(`
104
+ `)}var dt={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(`
105
+ `),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 No(Lo(e.cwd,e.args[0]??".")),n=B({env:e.env,flags:e.flags,cwd:t});if(n.conflict)throw new f("workspace_mismatch",n.conflict);if(!n.workspaceId||!n.credential)throw new f("workspace_required","No workspace selected. Run `hlix auth login` first.");let r=le(t);if(r?.projectId)throw new f("already_imported","This folder is already bound to an Hlix project. Use `hlix push`.");let s=qe(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 q(t,{...qe(e.flags,"env-file")?{envFile:qe(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=Bo(o);if(c&&e.flags.yes!==!0){if(e.json||!e.confirm)throw new f("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 f("cancelled","Import cancelled.")}}let i={root:t,name:qe(e.flags,"name")??Uo(t),stack:qe(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(y(k(dt.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(`
106
+ `)+`
107
+ `)}return o.blocking.length?1:0}if(o.blocking.length)throw new f("scan_blocked",`Project scan blocked import:
108
+ - ${o.blocking.join(`
109
+ - `)}`);let a=await lt(o);try{let c=e.requireClient(t),l=await c.imports.create({idempotencyKey:Mo(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 Fo(a.bundlePath))]),{onProgress:(w,b)=>{if(!e.json)e.stderr(`Uploading ${w}/${b} 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,u=d.projectId??d.requestedProjectId;if(!u||!d.revisionId||!d.generation)throw Error("Import completed without project revision metadata.");xe(t,{schemaVersion:1,projectId:u,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 m={projectId:u,revisionId:d.revisionId,generation:d.generation,commitSha:a.commitSha,files:o.manifest.totals.files,bytes:o.manifest.totals.bytes};if(e.json)e.stdout(y(k(dt.name,m)));else e.stderr(`
110
+ `),e.stdout(`Imported ${i.name}
111
+ Project ID: ${u}
112
+ Revision: ${d.generation}
113
+ `);return 0}finally{await a.dispose()}}};var cn={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(`
114
+ `),supportsJson:!0,async run(e){let t=Ar(e.cwd,Rr(e.env),{env:e.env});if(e.json)return e.stdout(y(k(cn.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(Hr(t,e.cwd)),0}};var Ko=(e)=>e instanceof Error?e.message:String(e);async function zo(e,t,n,r,s){try{let o=await q(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:Ko(o)}}}var ln={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(`
115
+ `),supportsJson:!0,async run(e){let t=B({env:e.env,flags:e.flags,cwd:e.cwd}),n=t.binding,r=n?rt(n.root):null,s=n?await zo(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:Nt(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(y(k(ln.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(`${_(a)}
116
+ `),0}};import{spawnSync as Fr}from"node:child_process";var dn={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(`
117
+ `),supportsJson:!0,options:["print","web"],args:{min:0,max:1},async run(e){let t=e.args[0]??O(e.cwd)?.config.projectId;if(!t)throw new f("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(y(k(dn.name,n))),n.available?0:1;if(!n.available){let i=n.environmentState?` (environment: ${n.environmentState})`:"";throw new f("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(`${_([["ssh",n.sshCommand??"not available"],["browser",n.webTerminalUrl??"not available"]])}
118
+ `),0;if(s){if(Fr(process.platform==="darwin"?"open":"xdg-open",[n.webTerminalUrl],{stdio:"ignore"}).status!==0)e.stdout(`${n.webTerminalUrl}
119
+ `);return 0}return Fr("sh",["-c",n.sshCommand],{stdio:"inherit"}).status??1}};import{createHash as si}from"node:crypto";import{readFile as oi,realpath as ii}from"node:fs/promises";import{createHash as qo}from"node:crypto";import{constants as pt}from"node:fs";import{chmod as Nr,copyFile as Do,lstat as pn,mkdir as Jo,mkdtemp as Go,open as Wo,realpath as Vo,rename as Xo,rm as Je,writeFile as Yo}from"node:fs/promises";import{tmpdir as Zo}from"node:os";import{dirname as Br,join as X,relative as Qo,resolve as ei,sep as Ur}from"node:path";import{spawnSync as ti}from"node:child_process";function Kr(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 zr(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 De(e,t){let n=ti("git",["-C",e,...t],{encoding:"utf8",maxBuffer:52428800,stdio:["ignore","pipe","pipe"]});if(n.status!==0)throw Error(n.stderr.trim().split(`
120
+ `).at(-1)??"Git command failed");return n.stdout.trim()}function Lr(e){return qo("sha256").update(e).digest("hex")}async function un(e,t){let n=await Vo(e),r=ei(n,...t.split("/"));if(r!==n&&!r.startsWith(n+Ur))throw Error(`Protected path escapes the project: ${t}`);let s=Qo(n,Br(r)),o=n;for(let i of s.split(Ur).filter(Boolean)){o=X(o,i);try{let a=await pn(o);if(!a.isDirectory()||a.isSymbolicLink())throw Error(`Protected path crosses a non-directory: ${t}`)}catch(a){if(a.code!=="ENOENT")throw a;await Jo(o,{mode:448})}}return r}async function Mr(e,t,n){let r=await un(e,t);try{let i=await pn(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=X(Br(r),`.hlix-pull-${crypto.randomUUID()}.tmp`),o=await Wo(s,pt.O_WRONLY|pt.O_CREAT|pt.O_EXCL|pt.O_NOFOLLOW,384);try{await o.writeFile(n),await o.sync()}finally{await o.close()}try{await Xo(s,r)}catch(i){throw await Je(s,{force:!0}),i}}async function ni(e,t){let n=await un(e,t);try{let r=await pn(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 qr(e,t,n,r,s){let o=await Go(X(Zo(),"hlix-pull-"));await Nr(o,448);let i=X(o,"project.bundle"),a=X(o,"checkout");try{let c=Buffer.from(await r.arrayBuffer());if(c.byteLength!==n.bundleSize||Lr(c)!==n.bundleSha256)throw Error("Downloaded revision bundle failed integrity verification.");if(await Yo(i,c,{mode:384}),De(o,["clone","--no-hardlinks","--branch","main",i,a]),De(a,["bundle","verify",i]),De(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 m of[...l.secretFiles,...l.quarantinedResources])p.set(m.path,m);if(s.files.length!==p.size)throw Error("Cloud protected files do not match the revision manifest.");let d=new Map;for(let m of s.files){let w=p.get(m.path),b=Buffer.from(m.contentBase64,"base64");if(b.toString("base64").replace(/=+$/,"")!==m.contentBase64.replace(/=+$/,"")||!w||w.kind!==m.kind||b.byteLength!==w.size||Lr(b)!==w.sha256)throw Error(`Cloud protected file failed integrity verification: ${m.path}`);d.set(m.path,b)}let u=new Set([...l.files.map((m)=>m.path),...t.manifest.secretFiles.map((m)=>m.path),...t.manifest.quarantinedResources.map((m)=>m.path),...d.keys()]);for(let m of[...u].sort())await ni(e,m);for(let[m,w]of d)await Mr(a,m,w);if(t.manifest.git.detected){De(e,["fetch",i,"refs/heads/main"]),De(e,["reset","--hard","FETCH_HEAD"]);let m=new Set(l.files.map((w)=>w.path));for(let w of t.manifest.files)if(!m.has(w.path))await Je(X(e,...w.path.split("/")),{force:!0})}else{for(let m of t.manifest.files)await Je(X(e,...m.path.split("/")),{force:!0});for(let m of l.files){let w=await un(e,m.path);await Do(X(a,...m.path.split("/")),w),await Nr(w,m.executable?493:420)}}for(let m of[...t.manifest.secretFiles,...t.manifest.quarantinedResources])if(!d.has(m.path))await Je(X(e,...m.path.split("/")),{force:!0});for(let[m,w]of d)await Mr(e,m,w)}finally{await Je(o,{recursive:!0,force:!0})}}function we(e,t,n){let r=new Map(zr(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 mn(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 fn(e,t,n){return e==="pull"&&t.localChanged&&!n}var ri={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 Dr(e,t,n,r){let s=n.files;return[`${e} --dry-run: ${ri[e][t]}`,...r?["Requires --yes (or interactive approval) to execute."]:[],"",_([["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(`
121
+ `)}function ai(e,t,n){return si("sha256").update(`project-push-v1\x00${e}\x00${t}\x00${n}`).digest("hex")}var ci={schemaVersion:1,revisionId:"",generation:0,commitSha:""};async function ve(e,{allowUnsynced:t=!1}={}){let n=O(e);if(!n?.config.projectId)throw new f("not_initialized","This folder is not bound to an imported Hlix project. Run `hlix import .` first.");let r=rt(n.root)??(t?ci:null);if(!r)throw new f("not_initialized","This folder is bound to a project but has never been pulled. Run `hlix pull` first.");return{root:await ii(n.root),config:n.config,state:r}}async function Ge(e,t,n,r){let s=await q(e,{historyMode:n,environment:t,rootName:r});if(s.blocking.length>0)throw new f("scan_blocked",`Project scan blocked sync:
122
+ - ${s.blocking.join(`
123
+ - `)}`);return s}async function gn(e,t,n,r){let{state:s,config:o}=await ve(r,{allowUnsynced:n==="pull"}),i=e.requireClient(),[a,c]=await Promise.all([Ge(r,e.env,s.historyMode??"preserve",s.rootName),i.revisions.head(o.projectId)]),l=we(a,s,c.revision),p=mn(n,l,e.flags.force===!0),d=fn(p,l,e.flags.yes===!0);if(e.json)e.stdout(y(k(t,{dryRun:!0,action:p,approvalRequired:d,...l})));else e.stdout(`${Dr(n,p,l,d)}
124
+ `);return p==="conflict"?1:0}async function li(e,t){if(e.flags.yes===!0)return;if(e.json||!e.confirm)throw new f("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(`
125
+ `);if(!await e.confirm(n))throw new f("cancelled","Pull cancelled.")}async function Jr(e,t,n,r){let{state:s,config:o}=await ve(e),i=t.requireClient(),a=s.historyMode??"preserve",c=n??await Ge(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 f("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 lt(c);try{let d=await i.revisions.createUpload(o.projectId,{idempotencyKey:ai(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 oi(p.bundlePath))]),{onProgress:(m,w)=>{if(!t.json)t.stderr(`Uploading ${m}/${w} bytes\r`)}})}let u=await i.revisions.finalize(o.projectId,d.revisionUpload.id,{secrets:c.secretValues,protectedFiles:c.protectedFiles});if(!u.revision)throw Error("Revision finalized without head metadata.");return _e(e,{schemaVersion:1,revisionId:u.revision.id,generation:u.revision.generation,commitSha:u.revision.commitSha,manifestSha256:u.revision.manifestSha256,historyMode:a,rootName:s.rootName??c.manifest.rootName}),{action:"push",...u.revision}}finally{await p.dispose()}}async function Gr(e,t,n,r,s){let{state:o,config:i}=await ve(e,{allowUnsynced:!0}),a=t.requireClient(),c=o.historyMode??"preserve",l=r??await Ge(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:E}=we(l,o,p);return E.localOnly+E.differing>0})();if(d&&!n)throw new f("conflict","Local files changed since the last sync. Push them, or use `hlix pull --force` to replace them.");if(d)await li(t,we(l,o,p));let[u,m]=await Promise.all([a.revisions.downloadBundle(i.projectId,p.id),a.revisions.protectedFiles(i.projectId)]);await qr(e,l,p,u,m);let w=Kr(p.manifest),b=w.historyMode??c,T=w.rootName??o.rootName??l.manifest.rootName,D=await Ge(e,t.env,b,T);return _e(e,{schemaVersion:1,revisionId:p.id,generation:p.generation,commitSha:p.commitSha,manifestSha256:D.manifestSha256,historyMode:b,rootName:T}),{action:"pull",revisionId:p.id,generation:p.generation,commitSha:p.commitSha}}function hn(e,t,n){if(e.json)e.stdout(y(k(t,n)));else if("action"in n&&n.action==="none")e.stdout(`Already in sync.
126
+ `);else e.stdout(`${String("action"in n?n.action:"sync")} complete.
127
+ `)}var ut={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 ve(e.cwd);if(e.flags["dry-run"]===!0)return gn(e,ut.name,"push",t);return hn(e,ut.name,await Jr(t,e)),0}},mt={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(`
128
+ `),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 ve(e.cwd,{allowUnsynced:!0});if(e.flags["dry-run"]===!0)return gn(e,mt.name,"pull",t);return hn(e,mt.name,await Gr(t,e,e.flags.force===!0)),0}},ft={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 ve(e.cwd);if(e.flags["dry-run"]===!0)return gn(e,ft.name,"sync",t);let s=e.requireClient(),[o,i]=await Promise.all([Ge(t,e.env,n.historyMode??"preserve",n.rootName),s.revisions.head(r.projectId)]),a=i.revision,c=we(o,n,a);if(c.localChanged&&c.cloudChanged)throw new f("conflict","Both local and cloud changed since the last sync. Pull or push explicitly after reviewing the conflict.");let l=c.localChanged?await Jr(t,e,o,a):c.cloudChanged?await Gr(t,e,!1,o,a):{action:"none",revisionId:n.revisionId,generation:n.generation};return hn(e,ft.name,l),0}};import{lstat as Wr,readFile as di,realpath as pi}from"node:fs/promises";import{basename as yn,dirname as ui,extname as mi,join as fi,parse as Vr,resolve as wn}from"node:path";function We(e,t){let n=e.flags[t];return typeof n==="string"&&n.trim()?n.trim():void 0}function vn(e){let t=O(e);if(!t?.config.projectId)throw new f("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 kn(e,t){let n=await Wr(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 pi(e),content:await di(e,"utf8")}}function bn(e,t,n,r){if(e.json)e.stdout(y(k(t,n)));else e.stdout(`${r}
129
+ `)}var Sn={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=vn(e.cwd),n=wn(e.cwd,e.args[0]),r=await Wr(n);if(r.isSymbolicLink())throw Error(`Refusing to import a symlink: ${n}`);let s=r.isDirectory()?fi(n,"SKILL.md"):n,o=await kn(s,200000),i=r.isDirectory()?yn(n):yn(s)==="SKILL.md"?yn(ui(s)):Vr(s).name,a=We(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 bn(e,Sn.name,c.skill,`Imported skill ${a}`),0}},jn={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=vn(e.cwd),n=wn(e.cwd,e.args[0]);if(![".md",".mdx"].includes(mi(n).toLowerCase()))throw Error("Agent imports must be Markdown files.");let r=await kn(n,20000),s=We(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=We(e,"duty")??"executor";if(o!=="executor"&&o!=="intake")throw Error("--duty must be executor or intake.");let i=We(e,"name")??Vr(n).name.replace(/[-_]+/g," "),a=await e.requireClient().resources.importAgent(t.projectId,{name:i,instructions:r.content,runtimeKind:s,duty:o});return bn(e,jn.name,a.agent,a.agent.duty==="intake"?`Imported agent ${a.agent.name} as this project's intake agent`:`Imported agent ${a.agent.name}`),0}},En={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=vn(e.cwd),n=await kn(wn(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=We(e,"server");if(!o&&s.length>1)throw Error("MCP config contains multiple servers; select one with --server <name>.");let i=o?s.find(([b])=>b===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((b)=>typeof b!=="string"))throw Error(`MCP server ${a} headers must be strings.`);let u=Object.values(d).flatMap((b)=>[...b.matchAll(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g)].map((T)=>T[1]));if(Object.keys(d).length>0&&u.length===0)throw Error("MCP remote headers must use ${KEY} placeholders; literal credentials are refused.");let m=/^(?:(?:Bearer|Basic|Token) )?\$\{[A-Za-z_][A-Za-z0-9_]*\}$/i;if(Object.values(d).some((b)=>!m.test(b)))throw Error("MCP remote headers must be ${KEY} or an approved auth scheme followed by ${KEY}.");let w=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((b)=>typeof b==="string")?{args:c.args}:{},...typeof c.url==="string"?{url:c.url}:{},...Object.keys(d).length>0?{headers:d}:{},envKeys:[...new Set([...Object.keys(p),...u])].sort()});return bn(e,En.name,w.mcpServer,`Imported MCP server ${a}`),0}};import{spawnSync as gi}from"node:child_process";import{chmod as hi,realpath as yi,writeFile as wi}from"node:fs/promises";import{basename as vi,dirname as ki,relative as bi,resolve as Yr,sep as Si}from"node:path";var Xr=64;function Xe(e){let t=O(e.cwd),r=(typeof e.flags.project==="string"?e.flags.project:void 0)??t?.config.projectId;if(!r)throw new f("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 Ve=(e,t)=>typeof e[t]==="string"?e[t]:void 0,Pn={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(`
130
+ `),supportsJson:!0,options:["project"],async run(e){let{projectId:t}=Xe(e),n=await e.requireClient().secrets.listEntries(t);if(e.json)return e.stdout(y(k(Pn.name,n))),0;if(n.entries.length===0)e.stdout(`No secrets stored for this project.
131
+ `);else e.stdout(`${W(["key","source","format","value","updated"],n.entries.map((r)=>[r.key,r.source,r.format||"-",r.maskedValue,r.updatedAt?.slice(0,10)??"-"]))}
132
+ `);for(let r of n.warnings)e.stderr(`warning: ${r}
133
+ `);return 0}},Cn={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(`
134
+ `),supportsJson:!0,options:["from-stdin","source","project"],args:{min:1,max:2},async run(e){let{projectId:t}=Xe(e),n=e.args[0],r=e.flags["from-stdin"]===!0;if(r&&e.args.length>1)throw new f("invalid_usage","Pass the value as an argument or with --from-stdin, not both.");if(!r&&e.args.length<2)throw new f("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 f("invalid_usage","--from-stdin is not available in this context.");s=(await e.readStdin()).replace(/\r?\n$/,"")}else s=e.args[1];let o=Ve(e.flags,"source"),i=await e.requireClient().secrets.upsertEntries(t,{entries:[{key:n,value:s,...o?{source:o}:{}}]});if(e.json)return e.stdout(y(k(Cn.name,i))),i.written>0?0:1;if(i.written===0)throw new f("bad_request",`The store refused ${n}: --source must be a project-relative file path.`);return e.stdout(`${_([["key",n],["source",o??".env"]])}
135
+ `),0}},$n={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(`
136
+ `),supportsJson:!0,options:["source","project"],args:{min:1,max:1},async run(e){let{projectId:t}=Xe(e),n=e.args[0],r=Ve(e.flags,"source"),s=await e.requireClient().secrets.deleteEntry(t,n,r);if(e.json)return e.stdout(y(k($n.name,s))),s.removed>0?0:1;if(s.removed===0)return e.stderr(`No stored secret named ${n}${r?` in ${r}`:""}.
137
+ `),1;return e.stdout(`Removed ${s.removed} entr${s.removed===1?"y":"ies"} for ${n}.
138
+ `),0}},gt={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(`
139
+ `),supportsJson:!0,options:["project"],args:{min:0,max:64},async run(e){let{projectId:t,root:n}=Xe(e),r=await q(n,{historyMode:"preserve",environment:e.env}),s=r.blocking.filter((d)=>!d.startsWith(rn));if(s.length>0)throw new f("scan_blocked",`Project scan blocked the import:
140
+ - ${s.join(`
141
+ - `)}`);let o=r.protectedFiles.filter((d)=>d.kind==="dotenv"||d.kind==="credential"),i=await yi(e.cwd),a=e.args.map((d)=>bi(r.root,Yr(i,d)).split(Si).join("/")),c=a.filter((d)=>!o.some((u)=>u.path===d));if(c.length>0)throw new f("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?y(k(gt.name,{imported:[],skipped:[],warnings:[],written:0,rejected:[]})):`No secret files found in this project.
142
+ `),0;if(l.length>Xr)throw new f("invalid_usage",`${l.length} secret files exceeds the ${Xr} 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(y(k(gt.name,p))),0;if(p.imported.length>0)e.stdout(`${W(["source","format","stored"],p.imported.map((d)=>[d.path,d.format||"-",d.kind==="file"?"as file":`${d.entries} entr${d.entries===1?"y":"ies"}`]))}
143
+ `);e.stdout(`${p.written} value${p.written===1?"":"s"} stored.
144
+ `);for(let d of p.skipped)e.stderr(`skipped ${d.path}: ${d.reason}
145
+ `);for(let d of p.warnings)e.stderr(`warning: ${d}
146
+ `);for(let d of p.rejected)e.stderr(`rejected ${d}: the store refused its source path
147
+ `);return 0}};function ji(e){return gi("git",["-C",ki(e),"ls-files","--error-unmatch","--",vi(e)],{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).status===0}var In={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(`
148
+ `),supportsJson:!0,options:["source","format","out","project"],async run(e){let{projectId:t}=Xe(e),n=Ve(e.flags,"source"),r=Ve(e.flags,"format"),s=Ve(e.flags,"out"),o=s===void 0?void 0:Yr(e.cwd,s);if(o!==void 0&&ji(o))throw new f("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 wi(o,i,{mode:384}),await hi(o,384);if(e.json)return e.stdout(y(k(In.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(`${_([["wrote",o],["mode","0600"],["bytes",String(Buffer.byteLength(i))]])}
149
+ `);return 0}};function xn(e,t){let n=e[t];if(typeof n!=="string"||n.trim()==="")throw new f("missing_argument",`--${t} is required.`);return n}var _n={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(`
150
+ `),supportsJson:!0,options:["title","description"],args:{min:1,max:1},async run(e){let t=e.args[0],n=xn(e.flags,"title"),r=xn(e.flags,"description"),s=await e.requireClient().cycles.propose({projectId:t,title:n,description:r});if(e.json)return e.stdout(y(k(_n.name,s))),0;return e.stdout(`${_([["project",t],["title",n],["status",s.adopted?"adopted — the project is planning it now":"recorded — it will be planned on the next pass"]])}
151
+ `),0}},On={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(`
152
+ `),supportsJson:!0,options:["title","description"],args:{min:1,max:1},async run(e){let t=e.args[0],n=xn(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(y(k(On.name,s))),0;return e.stdout(`${_([["task",s.id],["project",t],["status",s.status??"queued"],["note","not started — dispatch with `hlix cycles create`"]])}
153
+ `),0}},Tn={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(`
154
+ `),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(y(k(Tn.name,r))),0;return e.stdout(`${_([["scope",t?`project ${t}`:"workspace"],["harness",r.harness],["source",r.source]])}
155
+ `),0}},Rn={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(`
156
+ `),supportsJson:!0,options:["org"],args:{min:1,max:2},async run(e){let t=e.args[0];if(!fe.includes(t))throw new f("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 f("invalid_usage","Name a project or pass --org, not both: they are different scopes.");if(!n&&!r)throw new f("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(y(k(Rn.name,o))),0;return e.stdout(`${_([["scope",n?`project ${n}`:"workspace"],["harness",t]])}
157
+ `),0}};var Jl=[Kt,zt,he,ln,dn,cn,qt,Dt,Jt,sn,dt,ft,mt,ut,Sn,jn,En,Pn,Cn,$n,gt,In,Gt,Wt,Xt,Yt,Zt,Qt,On,_n,Tn,Rn];
158
+ export{f as a,Pi as b,O as c,B as d,Fs as e,wa as f,ar as g,fe as h,Ia as i,Mt as j,Jl as k};
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+ import{createHash as F}from"node:crypto";import{mkdirSync as M,readdirSync as T,readFileSync as P,rmSync as D,statSync as C,writeFileSync as L}from"node:fs";import{homedir as G,tmpdir as z}from"node:os";import{basename as _,isAbsolute as B,join as d,relative as J}from"node:path";var le=(e=process.env)=>e.HOME??e.USERPROFILE??G();function v(e){try{if(!C(e).isFile())return null;return P(e,"utf8")}catch{return null}}function W(e){try{return C(e).isDirectory()}catch{return!1}}function x(e,r){try{return T(e,{withFileTypes:!0}).filter((n)=>n.isFile()&&n.name.endsWith(r)).map((n)=>d(e,n.name)).sort()}catch{return[]}}function U(e){try{return T(e,{withFileTypes:!0}).filter((r)=>r.isDirectory()||r.isSymbolicLink()).map((r)=>d(e,r.name)).sort()}catch{return[]}}function j(e){let r=e.replace(/^\uFEFF/,""),n=r.indexOf(`
3
+ `);if(!r.startsWith("---")||n===-1)return{fields:{},body:r.trim()};let s=r.indexOf(`
4
+ ---`,n);if(s===-1)return{fields:{},body:r.trim()};let o={};for(let a of r.slice(n+1,s).split(`
5
+ `)){let m=/^([A-Za-z_][\w-]*)\s*:\s*(.*)$/.exec(a);if(!m)continue;o[m[1]]=m[2].trim().replace(/^["']|["']$/g,"")}let t=r.indexOf(`
6
+ `,s+1);return{fields:o,body:t===-1?"":r.slice(t+1).trim()}}function Z(e){let r=e.trimStart(),n=/^"((?:[^"\\]|\\.)*)"/.exec(r)??/^'([^']*)'/.exec(r);if(n)return n[1].replace(/\\"/g,'"').replace(/\\n/g,`
7
+ `);if(r.startsWith("["))return[...r.matchAll(/"((?:[^"\\]|\\.)*)"|'([^']*)'/g)].map((o)=>o[1]??o[2]??"");if(r.startsWith("{")){let o={};for(let t of r.matchAll(/([A-Za-z0-9_.-]+)\s*=\s*"((?:[^"\\]|\\.)*)"/g))o[t[1]]=t[2].replace(/\\"/g,'"');return o}let s=/^[^\s#]+/.exec(r)?.[0];if(s===void 0)return;if(s==="true"||s==="false")return s==="true";if(/^-?\d+(\.\d+)?$/.test(s))return Number(s);return s}function N(e){let r={"":{}},n="",s=e.split(`
8
+ `);for(let o=0;o<s.length;o+=1){let a=s[o].trim();if(!a||a.startsWith("#"))continue;let m=/^\[\[?([^\]]+)\]\]?$/.exec(a);if(m){n=m[1].trim(),r[n]??={};continue}let l=/^([A-Za-z0-9_.-]+|"[^"]+")\s*=\s*(.*)$/.exec(a);if(!l)continue;let p=l[1].replace(/^"|"$/g,""),g=l[2];if(g.startsWith('"""')){let y=[],c=g.slice(3);if(c.includes('"""'))y.push(c.slice(0,c.indexOf('"""')));else{if(c)y.push(c);while(o+1<s.length){o+=1;let u=s[o],i=u.indexOf('"""');if(i===-1){y.push(u);continue}y.push(u.slice(0,i));break}}r[n][p]=y.join(`
9
+ `).replace(/^\n/,"");continue}let S=Z(g);if(S!==void 0)r[n][p]=S}return r}function k(e,r){return e.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}/g,(n,s,o)=>{let t=r[s];return t!==void 0&&t!==""?t:o??""})}var A=(e,r)=>{let n={};for(let[s,o]of Object.entries(e))if(typeof o==="string")n[s]=k(o,r);return n},V=[{relative:"GEMINI.md",source:"gemini"},{relative:d(".gemini","GEMINI.md"),source:"gemini"},{relative:".cursorrules",source:"cursor"},{relative:".windsurfrules",source:"windsurf"},{relative:d(".github","copilot-instructions.md"),source:"copilot"}],H=[{relative:d(".gemini","GEMINI.md"),source:"gemini"}],K=[{relative:d(".cursor","rules"),source:"cursor",extension:".mdc"},{relative:d(".windsurf","rules"),source:"windsurf",extension:".md"}];function q(e,r){let n=d(e,".clinerules"),s=W(n)?x(n,".md"):[n],o=[];for(let t of s){let a=v(t)?.trim();if(a)o.push({path:t,source:"cline",scope:r,content:a})}return o}function Q(e,r,n){let{fields:s,body:o}=j(r);if(s.alwaysApply==="false")return{path:e,source:"cursor",scope:n,reason:"alwaysApply: false"};if(!o)return{path:e,source:"cursor",scope:n,reason:"no rule body"};let t=s.globs?.replace(/^\[|\]$/g,"").trim();return{path:e,source:"cursor",scope:n,content:o,...t?{note:`Applies to: ${t}`}:{}}}function R(e,r){let n=[];for(let s of["",".claude",r])for(let o of["AGENTS.md","CLAUDE.md"]){let t=v(d(e,s,o))?.trim();if(t)n.push(t)}return n}var X=[{dir:".claude",source:"claude",harnessReads:!0},{dir:".agents",source:"agents",harnessReads:!0},{dir:".hlix",source:"hlix",harnessReads:!0},{dir:".codex",source:"codex",harnessReads:!1}],Y=[{relative:d(".cursor","commands"),source:"cursor"},{relative:d(".codex","prompts"),source:"codex"}],O=[{relative:d(".cursor","mcp.json"),source:"cursor",key:"mcpServers",format:"json"},{relative:d(".windsurf","mcp.json"),source:"windsurf",key:"mcpServers",format:"json"},{relative:d(".gemini","settings.json"),source:"gemini",key:"mcpServers",format:"json"},{relative:d(".vscode","mcp.json"),source:"vscode",key:"servers",format:"json"},{relative:d(".codex","config.toml"),source:"codex",key:"mcp_servers",format:"toml"}],ee="found, not loaded (machine-wide; enable per project by copying into .hlix/mcp.json)",te=O.filter((e)=>e.source!=="vscode");function re(e,r){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 s=typeof n.command==="string"&&n.command!=="",o=typeof n.url==="string"&&n.url!=="";if(s&&o)return{reason:'has both "command" and "url"'};if(s){let l=Array.isArray(n.args)?n.args.filter((g)=>typeof g==="string"):void 0,p=n.env&&typeof n.env==="object"&&!Array.isArray(n.env)?A(n.env,r):void 0;return{config:{command:n.command,...l&&l.length>0?{args:l}:{},...p&&Object.keys(p).length>0?{env:p}:{}}}}if(!o)return{reason:'missing "command" or "url"'};let t=n.headers??n.http_headers,a=t&&typeof t==="object"&&!Array.isArray(t)?A(t,r):{},m=n.bearer_token_env_var;if(typeof m==="string"&&/^[A-Za-z_][A-Za-z0-9_]*$/.test(m)&&!Object.keys(a).some((l)=>l.toLowerCase()==="authorization"))a.Authorization=`Bearer ${k(`\${${m}}`,r)}`;return{config:{url:k(n.url,r),...Object.keys(a).length>0?{headers:a}:{}}}}function E(e,r,n,s){let o=v(e),t=[],a=[];if(o===null)return{servers:t,skipped:a};let m=[];if(r.format==="toml"){let l=N(o);m=Object.entries(l).filter(([p])=>p.startsWith(`${r.key}.`)).map(([p,g])=>[p.slice(r.key.length+1),g])}else try{let p=JSON.parse(o)?.[r.key];if(p&&typeof p==="object"&&!Array.isArray(p))m=Object.entries(p)}catch{return a.push({path:e,source:r.source,scope:n,reason:"not valid JSON"}),{servers:t,skipped:a}}for(let[l,p]of m){let g=re(p,s);if("reason"in g){a.push({path:e,source:r.source,scope:n,reason:`${l}: ${g.reason}`});continue}t.push({path:e,source:r.source,scope:n,name:l,config:g.config})}return{servers:t,skipped:a}}function ne(e,r,n){let{fields:s,body:o}=j(r);if(!o)return{path:e,source:"claude",scope:n,reason:"no instructions"};let t=s.tools?.replace(/^\[|\]$/g,"").split(",").map((a)=>a.trim()).filter(Boolean);return{path:e,source:"claude",scope:n,name:s.name||_(e,".md"),description:s.description??"",instructions:o,...t&&t.length>0&&t[0]!=="*"?{tools:t}:{},...s.model?{model:s.model}:{}}}function se(e){let r=N(e)[""]??{},n=typeof r.prompt==="string"?r.prompt.trim():"";if(!n)return null;return{description:typeof r.description==="string"?r.description:"",body:n}}function ue(e,r,n={}){let s=n.configDir??".hlix",o=n.env??process.env,t={instructions:[],skills:[],commands:[],generatedCommands:[],mcpServers:[],subagents:[],skipped:[]},a=(c)=>{if("reason"in c)t.skipped.push(c);else t.instructions.push(c)};for(let c of V){let u=d(e,c.relative),i=v(u)?.trim();if(i)t.instructions.push({path:u,source:c.source,scope:"project",content:i})}for(let c of K)for(let u of x(d(e,c.relative),c.extension)){let i=v(u);if(i===null)continue;if(c.source==="cursor"){a(Q(u,i,"project"));continue}let{body:f}=j(i);if(f)t.instructions.push({path:u,source:c.source,scope:"project",content:f})}for(let c of q(e,"project"))a(c);let m=R(e,s),l=d(e,".codex","AGENTS.md"),p=v(l)?.trim();if(p&&m.includes(p))t.skipped.push({path:l,source:"codex",scope:"project",reason:"same content as the project's AGENTS.md"});else if(p)t.instructions.push({path:l,source:"codex",scope:"project",content:p});for(let c of H){let u=d(r,c.relative),i=v(u)?.trim();if(i)t.instructions.push({path:u,source:c.source,scope:"global",content:i})}let g=d(r,".codex","AGENTS.md"),S=v(g)?.trim(),y=R(r,s);if(S&&y.includes(S))t.skipped.push({path:g,source:"codex",scope:"global",reason:"same content as the machine's AGENTS.md"});else if(S)t.instructions.push({path:g,source:"codex",scope:"global",content:S});for(let[c,u]of[[e,"project"],[r,"global"]])for(let i of X){let f=d(c,i.dir===".hlix"?s:i.dir,"skills");if(!U(f).some((I)=>v(d(I,"SKILL.md"))!==null))continue;t.skills.push({path:f,source:i.source,scope:u,harnessReads:i.harnessReads})}for(let[c,u]of[[e,"project"],[r,"global"]]){for(let i of Y){let f=d(c,i.relative);if(x(f,".md").length===0)continue;t.commands.push({path:f,source:i.source,scope:u})}for(let i of x(d(c,".gemini","commands"),".toml")){let f=v(i),h=f===null?null:se(f);if(!h){t.skipped.push({path:i,source:"gemini",scope:u,reason:"no prompt field"});continue}t.generatedCommands.push({path:i,source:"gemini",scope:u,name:_(i,".toml"),body:`---
10
+ description: ${h.description}
11
+ ---
12
+
13
+ ${h.body}
14
+ `})}}for(let c of O){let u=E(d(e,c.relative),c,"project",o);t.skipped.push(...u.skipped);for(let i of u.servers){let f=t.mcpServers.findIndex((h)=>h.name===i.name);if(f===-1)t.mcpServers.push(i);else t.mcpServers[f]=i}}for(let c of te){let u=E(d(r,c.relative),c,"global",o);for(let i of u.servers)t.skipped.push({path:i.path,source:i.source,scope:"global",reason:`${i.name}: ${ee}`})}for(let[c,u]of[[e,"project"],[r,"global"]])for(let i of x(d(c,".claude","agents"),".md")){let f=v(i);if(f===null)continue;let h=ne(i,f,u);if("reason"in h)t.skipped.push(h);else if(t.subagents.some((I)=>I.name===h.name))t.skipped.push({path:i,source:"claude",scope:u,reason:`a project agent already claims the name ${h.name}`});else t.subagents.push(h)}return t}function pe(e,r){if(e.length===0)return null;let n=d(z(),"hlix-standards-commands",F("sha256").update(r).digest("hex").slice(0,16));try{D(n,{recursive:!0,force:!0}),M(n,{recursive:!0});for(let s of e)L(d(n,`${s.name}.md`),s.body,"utf8");return n}catch{return null}}var oe=60000,w=(e,r)=>{let n=J(r,e);return!n||n.startsWith("..")||B(n)?e:n};function me(e,r,n=oe){if(e.length===0)return"";let s=["# 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(`
15
+ `),o=[],t=s.length,a=!1;for(let l of e){let p=`# From ${w(l.path,r)} (${l.source})`,g=l.note?`${p}
16
+ ${l.note}`:p,S=n-t-g.length-4;if(S<=0){a=!0;break}let y=l.content.length<=S?l.content:`${l.content.slice(0,S)}
17
+ [truncated]`;if(y.length<l.content.length)a=!0;o.push(`${g}
18
+
19
+ ${y}`),t+=g.length+y.length+4}let m=a?`
20
+
21
+ [The standards block reached its ${n}-character cap; some rules above are cut short or omitted.]`:"";return`${s}
22
+
23
+ ${o.join(`
24
+
25
+ `)}${m}`}var b=(e,r,n)=>`${e} ${e===1?r:n}`;function ge(e){let r=[];if(e.instructions.length>0)r.push(b(e.instructions.length,"instruction file","instruction files"));if(e.skills.length>0)r.push(b(e.skills.length,"skill directory","skill directories"));let n=e.commands.length+e.generatedCommands.length;if(n>0)r.push(b(n,"command source","command sources"));if(e.mcpServers.length>0)r.push(b(e.mcpServers.length,"mcp server","mcp servers"));if(e.subagents.length>0)r.push(b(e.subagents.length,"subagent","subagents"));if(r.length===0)return"";let s=[...new Set([...e.instructions,...e.skills,...e.commands,...e.generatedCommands,...e.mcpServers,...e.subagents].map((o)=>o.source))].sort();return`standards: ${r.join(" · ")} (${s.join(", ")})`}function fe(e,r){let n=[],s=(t,a)=>{if(a.length===0)return;n.push(t,...a.map((m)=>` ${m}`),"")},o=(t)=>`${t.source}${t.scope==="global"?" (global)":""} ${w(t.path,r)}`;if(s("Instructions",e.instructions.map((t)=>`${o(t)}${t.note?` — ${t.note}`:""}`)),s("Skills",e.skills.map((t)=>`${o(t)}${t.harnessReads?" — already read by the harness":""}`)),s("Commands",[...e.commands.map(o),...e.generatedCommands.map((t)=>`${o(t)} → /${t.name}`)]),s("MCP servers",e.mcpServers.map((t)=>`${o(t)} → ${t.name} (${"command"in t.config?"stdio":"http"})`)),s("Subagents",e.subagents.map((t)=>`${o(t)} → ${t.name}`)),s("Skipped",e.skipped.map((t)=>`${o(t)} — ${t.reason}`)),n.length===0)return`No standards from other agent tools were found in this folder.
26
+ `;return`${n.join(`
27
+ `).trimEnd()}
28
+ `}
29
+ export{le as l,ue as m,pe as n,me as o,ge as p,fe as q};
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
2
  import{createRequire as a}from"node:module";var c=a(import.meta.url);
3
- export{c as q};
3
+ export{c as r};
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 C,c as h,e as T,f as p,k as a}from"./index-5wxt3qe0.js";import"./index-rraz48fm.js";import{r as i}from"./index-y1n35st0.js";import{emitKeypressEvents as y}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),y(process.stdin),process.stdin.setRawMode(!0),process.stdin.resume(),new Promise((e,t)=>{let s="",c=()=>{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"){c(),t(Error("Login cancelled."));return}if(o.name==="return"||o.name==="enter"){c(),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 c=(await t.question(r)).trim(),n=Number(c);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 v,realpathSync as w}from"node:fs";import{fileURLToPath as b}from"node:url";function x(){if(i.main==i.module===!0)return!0;let r=process.argv[1];if(!r)return!1;try{return w(r)===w(b(import.meta.url))}catch{return!1}}var g={"-h":"--help","-v":"--version"};function S(r){return r.map((e)=>g[e]??e)}function E(r,e=a){let t=r[0];if(t===void 0)return!1;if(t in g||t==="--help"||t==="--version")return!0;return e.some((s)=>s.name.split(" ")[0]===t)}function P(r,e){if(E(r))return e.cli(S(r));return e.code(r[0]==="code"?r.slice(1):r)}if(x()){let r=await P(process.argv.slice(2),{cli:(e)=>p(a,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()=>v(0,"utf8")}),code:async(e)=>{let{version:t}=await import("./package-f3wbdpaa.js");return(await import("./harness-settings-9xpgt0fb.js")).configureHarnessEnvironment({version:t}),(await import("./main-py292c5v.js")).runHlixCode(e)}});process.exit(r)}export{a as COMMANDS,C as JSON_SCHEMA_VERSION,T as clientFor,P as dispatch,h as findProjectBinding,E as isCliInvocation,S as normalizeCliArgv,p as runCli};