@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.
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ import{a as w,d as re,e as h,f as U,g as I,h as f,i as C,j as we,k as b}from"./index-5wxt3qe0.js";import{l as ye,m as be,n as ke,o as ve,p as Se}from"./index-rraz48fm.js";import{r as wt}from"./index-y1n35st0.js";import{relative as yt,resolve as bt}from"node:path";import{parseArgs as kt}from"node:util";import{createMastraCode as vt}from"mastracode";import{loadMcpConfig as St}from"@mastra/code-sdk/mcp/config";import{executeSubagent as Ct}from"@mastra/code-sdk/agents/subagents/execute";import{exploreSubagent as Ht}from"@mastra/code-sdk/agents/subagents/explore";import{planSubagent as It}from"@mastra/code-sdk/agents/subagents/plan";import{hasHeadlessFlag as Pt,parseHeadlessArgs as jt,runMC as _t}from"mastracode/headless";import{MastraTUI as At}from"mastracode/tui";var je=[["You are already on the latest version","Update Hlix Code with npm or brew"],["A new version of Mastra Code is available","Hlix Code updates via npm or brew"],["-g mastracode@","-g @hlix/cli@"],["To use Mastra Code you need at least one API key or OAuth login","Run `hlix auth login`, or add a provider key for your own"],["See https://mastra.ai/models for supported providers and API key env vars.","Your hlix workspace supplies the models; a provider key is optional."],["https://mastra.ai/docs/memory/observational-memory","Observational memory summarizes long threads."],["Manage Mastra Code plugins","Manage Hlix Code plugins"],["Mastra Code","Hlix Code"],["MastraCode","Hlix Code"],["mastracode","hlix"]];function y(e){let t=e;for(let[s,r]of je)t=t.split(s).join(r);return t}function B(e){let s=e.state?.terminal;if(!s||typeof s.write!=="function")throw Error("Hlix Code cannot rebrand this MastraCode TUI: no `state.terminal.write` to wrap.");let r=s.write.bind(s);s.write=(o)=>r(y(o))}import{mkdirSync as Te,writeFileSync as $e}from"node:fs";import{join as Y}from"node:path";import{createTool as _e}from"@mastra/core/tools";import{z as u}from"zod";var v=(e)=>`hlix_${e.split(" ").join("_")}`,Ae=u.object({args:u.array(u.string()).optional().describe("Positional arguments that follow the command name."),flags:u.record(u.string(),u.union([u.string(),u.boolean()])).optional().describe('Options without the leading dashes, e.g. { "yes": true, "name": "api" }.')}),Re=u.object({exitCode:u.number(),stdout:u.string(),stderr:u.string()});function Me(e,t,s){let r=e.name.split(" ").concat(t.args??[]);for(let[o,n]of Object.entries(t.flags??{})){if(n===!1)continue;if(r.push(`--${o}`),typeof n==="string")r.push(n)}if(!t.flags?.cwd)r.push("--cwd",s);if(e.supportsJson&&!t.flags?.json)r.push("--json");return r}async function Oe(e,t,s,r=process.env){let o="",n="";return{exitCode:await U([e],Me(e,t,s),{stdout:(c)=>{o+=c},stderr:(c)=>{n+=c},env:r}),stdout:o,stderr:n}}function q(e){let t={};for(let s of e.commands??b){let r=v(s.name);t[r]=_e({id:r,description:`${s.summary}
3
+
4
+ ${s.usage}`,inputSchema:Ae,outputSchema:Re,execute:async(o)=>Oe(s,o,e.cwd,e.env)})}return t}var Ne=(e)=>`${e.split(" ").join("-")}.md`;function Ee(e){return["---",`description: ${e.summary}`,"---","",`Call the tool \`${v(e.name)}\` with the user's arguments: $ARGUMENTS.`,"Show the result.",""].join(`
5
+ `)}var Fe={"follow.md":["---","description: Watch a cloud task being coded, live","---","","Call the tool `hlix_tasks_follow` with `taskId` set to $ARGUMENTS. It streams the","coder's text and tool calls into this session. Summarise what it did.",""].join(`
6
+ `),"harness.md":["---","description: Show or change the harness — which coder does the work","---","","Call the tool `hlix_harness` with `harness` set to $ARGUMENTS when the user","named one, and with no argument when they did not. Show `message` verbatim.",""].join(`
7
+ `)};function K(e,t=b){let s=Y(e,".hlix","commands");Te(s,{recursive:!0});let r=[],o=[...t.map((n)=>[Ne(n.name),Ee(n)]),...Object.entries(Fe)];for(let[n,i]of o){let c=Y(s,n);try{$e(c,i,{flag:"wx"}),r.push(c)}catch(a){if(a.code!=="EEXIST")throw a}}return r}import{execFileSync as We}from"node:child_process";import{createACPTool as Le}from"@mastra/acp";import{createTool as De}from"@mastra/core/tools";import{z as p}from"zod";var x={"claude-code":{harness:"claude-code",label:"Claude Code",command:"claude-agent-acp",args:[],authEnvVars:["ANTHROPIC_API_KEY"],install:"npm i -g @agentclientprotocol/claude-agent-acp"},codex:{harness:"codex",label:"Codex",command:"codex-acp",args:[],authEnvVars:["OPENAI_API_KEY"],env:{NO_BROWSER:"1"},install:"npm i -g @agentclientprotocol/codex-acp"},"cursor-agent":{harness:"cursor-agent",label:"Cursor Agent",command:"cursor-agent",args:["acp"],authEnvVars:["CURSOR_API_KEY"],install:"curl https://cursor.com/install -fsS | bash"}};function G(e){if(e.flag)return{harness:Be(e.flag,"--harness"),source:"flag"};if(e.configured)return{harness:e.configured,source:e.configSource??"project"};return{harness:C,source:"default"}}function Be(e,t){if(f.includes(e))return e;throw Error(`${t} must be one of ${f.join(", ")}; got "${e}".`)}var S="hlix_tasks_follow",Ue=(e)=>`hlix_coder_${e.split("-").join("_")}`;function V(e,t){let s=t.source==="default"?"":` (${t.source==="flag"?"--harness":t.source})`;return`${e} · harness: ${t.harness}${s}`}function J(e,t=3000){try{return We("which",[e],{timeout:t,stdio:"ignore"}),!0}catch{return!1}}var H=(e)=>`harness ${e.harness} needs \`${e.command}\` on PATH. Install it with: ${e.install}`;function qe(e){let t=e.options??[],s=t.find((r)=>r.kind==="allow_once")??t.find((r)=>r.kind==="reject_once");if(!s)return{outcome:{outcome:"cancelled"}};return{outcome:{outcome:"selected",optionId:s.optionId}}}var X=["view","search_content","find_files","file_stat","lsp_inspect"],z=["ask_user","task_write","task_update","task_complete","task_check"],Ye=(e)=>[`harness ${e} runs in the project's Coding Workspace, not on this machine.`,"This session can follow and stream that work, but cannot start it:","which coder the platform uses comes from the project's harness preference,","and this CLI has no command that creates a task."].join(" "),Q=(e)=>[e==="unknown"?"This project's harness could not be read from the server. Do NOT guess which coder it runs — say so, and offer to check with the `hlix_harness` tool.":`This project's harness is ${e}: the platform runs ${e} for the coding work it executes, in the project's Coding Workspace.`,"Change it with the `hlix_harness` tool, which writes the project's setting.","","To do coding work here, dispatch it and then watch it:","1. `hlix_cycles_create` with the project id, a title and a description. That"," is what STARTS work — it enters the project's loop, which plans the cycle,"," creates its tasks and starts the coder. It returns no cycle id.","2. `hlix_tasks_list` with that project to find the tasks planning produced.",`3. \`${S}\` with a task id, which streams that coder's own text and`," tool calls into this session live. Report what it did.","","`hlix_tasks_create` only adds a board row; it does not start anything, and","there is no way to start a single task. Never claim otherwise."].join(`
8
+ `),Ke=(e,t)=>[`The user chose the ${e.label} harness. Do not edit files or run commands`,`yourself. Hand the whole task to \`${t}\` as one natural-language brief,`,`then report what it did. ${e.label} reads and writes the same working`,"directory you are in.","",`It authenticates from ${e.authEnvVars.join(" or ")} in this shell's`,"environment. If it reports a credential problem, say so — do not retry."].join(`
9
+ `);function Z(e){if(e.sandbox==="cloud"||e.active==="hlix")return[];let t=new Set(e.unavailable??[]),s=e.model?{defaultModelId:e.model}:{},r=[{id:"hlix",name:"Hlix",description:"The hlix agent codes here, with the full toolset.",...s}];for(let o of Object.values(x)){let n=e.active===o.harness,i=Ue(o.harness);r.push({id:o.harness,name:o.label,description:`${o.label} runs on this machine over ACP and edits ${e.cwd}.`,instructions:Ke(o,i),availableTools:t.has(o.harness)?[...X,...z,S]:[i,...X,...z,S],...t.has(o.harness)?{}:{additionalTools:{[i]:Le({id:i,description:`Run a coding task with ${o.label}. Give it one natural-language brief; it reads and writes the working directory and returns its final output.`,command:o.command,args:o.args,cwd:e.cwd,...o.env?{env:o.env}:{},...e.workspace?{workspace:e.workspace}:{},onPermissionRequest:async(c)=>qe(c)})}},...s,...n?{metadata:{default:!0}}:{}})}return r}function Xe(e){let t=[...e.available],s=(o,n="none")=>({harness:e.current,available:t,action:n,message:o});if(!e.requested)return s(`harness: ${e.current}. Available here: ${t.join(", ")}.`);if(!f.includes(e.requested))return s(`/harness must name one of ${f.join(", ")}; got "${e.requested}".`);let r=e.requested;if(e.sandbox==="cloud"){let o=`${e.sandboxLine} · harness: ${r} (project preference)`;return{harness:r,available:t,action:"preference",message:r==="hlix"?o:`${o}. ${Ye(r)}`}}if(!t.includes(r))return s(H(x[r]));if(!e.modesBuilt)return s(`This session runs the hlix coder, so there is no ${r} mode to switch to. Restart with \`hlix --harness ${r}\`, or make it the default with \`hlix config set harness ${r}\`.`,"restart");return{harness:r,available:t,action:"mode",message:`${e.sandboxLine} · harness: ${r}`}}function ee(e){return De({id:"hlix_harness",description:"Show or change the harness — which coder does the work. In a local or docker sandbox it switches this session's coder; in a cloud sandbox it writes the project's harness preference, which is what the platform runs. With no argument it reports the current harness.",inputSchema:p.object({harness:p.string().optional().describe(`One of ${f.join(", ")}. Omit to report the current one.`)}),outputSchema:p.object({harness:p.string(),available:p.array(p.string()),message:p.string()}),execute:async(t)=>{let s=e.session(),r=Xe({...t.harness?{requested:t.harness}:{},current:s?.mode.get()??C,available:e.available,sandbox:e.sandbox,sandboxLine:e.sandboxLine,modesBuilt:e.modesBuilt}),o={harness:r.harness,available:r.available,message:r.message};if(r.action==="mode"&&s)return await s.mode.switch({modeId:r.harness}),o;if(r.action==="preference"){if(!e.setProjectHarness)return{...o,message:"This folder is not bound to a hlix project, so there is no project preference to write. Run `hlix init` or pass --project <id>."};await e.setProjectHarness(r.harness)}return o}})}import{createTool as ze}from"@mastra/core/tools";import{writeToolProgress as Ge}from"mastracode/plugin";import{z as m}from"zod";function Ve(e){switch(e.type){case"on_chat_model_stream":return e.delta?{event:"text",text:e.delta}:null;case"reasoning":return e.delta?{event:"text",text:e.delta}:null;case"on_tool_start":return{event:"tool_start",toolName:e.name,args:e.input};case"on_tool_end":return{event:"tool_end",toolName:e.name,result:e.output,isError:Je(e.output)};case"error":return{event:"finish",isError:!0,result:e.message};case"done":return{event:"finish",isError:!1};default:return null}}function Je(e){return typeof e==="object"&&e!==null&&e.status==="failed"}async function Qe(e,t){let s=[],r=[],o="streamed",n="The coder's turn ended.";for await(let i of e){if(i.type==="idle"){o="idle",n="Nothing is being coded right now. The task is not in build or test.";break}if(i.type==="error")o="error",n=i.message;if(i.type==="on_chat_model_stream")s.push(i.delta);if(i.type==="on_tool_start")r.push(i.name);let c=Ve(i);if(c)await t(c)}return{status:o,text:s.join(""),tools:r,message:n}}function te(e){return ze({id:"hlix_tasks_follow",description:"Watch a hlix task being coded in the cloud, live. Streams the coder's text and tool calls into this session as they happen, and returns what it did. Use it after a task starts building.",inputSchema:m.object({taskId:m.string().describe("The task to follow.")}),outputSchema:m.object({status:m.enum(["streamed","idle","error","unassigned"]),text:m.string(),tools:m.array(m.string()),message:m.string()}),execute:async(t,s)=>{let r=h(e.env??process.env,{cwd:e.cwd,flags:{}}),o=await r.tasks.get(t.taskId);if(!o.agentId)return{status:"unassigned",text:"",tools:[],message:"No agent has picked this task up yet, so there is no coder to watch. Check `hlix_tasks_get` again once it is building."};return Qe(r.projects.observeAgent(o.projectId,o.agentId),(n)=>Ge(s,n))}})}import{buildMode as Ze}from"@mastra/code-sdk/agents/modes/build";import{fastMode as et}from"@mastra/code-sdk/agents/modes/explore";import{planMode as tt}from"@mastra/code-sdk/agents/modes/plan";import{setCustomProvidersSource as st}from"@mastra/code-sdk/agents/model";import{getCustomProviderId as se,loadSettings as rt}from"@mastra/code-sdk/onboarding/settings";var oe="hlix",ne="default",ot=(e)=>`${oe}/${e}`;function nt(e){return{name:oe,url:`${e.baseUrl.replace(/\/+$/,"")}/v1/api/ai/w/${e.workspaceId}`,apiKey:e.apiKey,models:[...new Set([ne,...e.models??[]])]}}function at(e){let t=[Ze,tt,et];return e?t.map((s)=>({...s,defaultModelId:e})):t}function ae(e){let t=re({env:e.env,flags:{},cwd:e.cwd});if(t.conflict||!t.credential||!t.workspaceId)return null;let s=nt({baseUrl:t.baseUrl,workspaceId:t.workspaceId,apiKey:t.credential.apiKey,...e.models?{models:e.models}:{}}),r=se(s.name);return st(()=>[...rt().customProviders.filter((o)=>se(o.name)!==r),s]),{provider:s,modelId:ot(ne)}}var ie=(e,t)=>e.length>0?[...e]:at(t);function ce(e){if(e.configured)return{id:e.configured,source:e.configuredSource??"config"};return e.wired?{id:e.wired.modelId,source:"workspace"}:null}var le=(e,t)=>t?`${e} · model: ${t.id} (${t.source})`:e;import{execFileSync as pt}from"node:child_process";import{DockerSandbox as ht}from"@mastra/docker";import{LocalFilesystem as gt,Workspace as ft}from"@mastra/core/workspace";import{posix as de}from"node:path";import{MastraFilesystem as it,MastraSandbox as ct,Workspace as lt}from"@mastra/core/workspace";var dt=600000,ut=["recursive","overwrite","force","maxDepth","extension"];function g(e){let t=e??{},s={};for(let r of ut)if(t[r]!==void 0)s[r]=t[r];return Object.keys(s).length>0?{options:s}:{}}var ue=(e)=>e instanceof Date?e:new Date(typeof e==="string"||typeof e==="number"?e:0);class me extends it{id;name="RemoteFilesystem";provider="hlix-coding-workspace";basePath;status="ready";client;constructor(e,t){super({name:"RemoteFilesystem"});this.client=e,this.basePath=t.root,this.id=t.id??`hlix-remote-fs:${t.root}`}getInfo(){return{id:this.id,name:this.name,provider:this.provider,status:this.status,metadata:{root:this.basePath}}}resolveAbsolutePath(e){return de.isAbsolute(e)?e:de.join(this.basePath,e)}async call(e){let{result:t}=await this.client.fs({...e,encoding:e.encoding??"utf8",path:this.resolveAbsolutePath(e.path)});return t}async readFile(e,t){let r=await this.call({op:"read",path:e,encoding:"base64"}),o=Buffer.from(r.content,r.encoding);return t?.encoding?o.toString(t.encoding):o}async writeFile(e,t,s){await this.call({op:"write",path:e,content:Buffer.from(t).toString("base64"),encoding:"base64",...g(s)})}async appendFile(e,t){await this.call({op:"append",path:e,content:Buffer.from(t).toString("base64"),encoding:"base64"})}async deleteFile(e,t){await this.call({op:"delete",path:e,...g(t)})}async copyFile(e,t,s){await this.call({op:"copy",path:e,dest:this.resolveAbsolutePath(t),...g(s)})}async moveFile(e,t,s){await this.call({op:"move",path:e,dest:this.resolveAbsolutePath(t),...g(s)})}async mkdir(e,t){await this.call({op:"mkdir",path:e,...g(t)})}async rmdir(e,t){await this.call({op:"rmdir",path:e,...g(t)})}async readdir(e,t){return await this.call({op:"readdir",path:e,...g(t)})??[]}async exists(e){return await this.call({op:"exists",path:e})===!0}async stat(e){let t=await this.call({op:"stat",path:e});return{...t,createdAt:ue(t.createdAt),modifiedAt:ue(t.modifiedAt)}}}var mt=(e)=>`'${e.split("'").join("'\\''")}'`;class pe extends ct{id;name="RemoteSandbox";provider="hlix-coding-workspace";status="ready";client;constructor(e,t){super({name:"RemoteSandbox"});if(this.client=e,this.id=`hlix-remote-sandbox:${t.projectId}`,t.root)this.setWorkingDirectory(t.root)}async start(){}getInfo(){return{id:this.id,name:this.name,provider:this.provider,status:this.status,createdAt:new Date(0)}}async executeCommand(e,t=[],s){let r=[e,...t.map(mt)].join(" "),o=Date.now(),n=s?.cwd??this.workingDirectory,i=await this.client.exec({command:r,...n?{cwd:n}:{},timeoutMs:s?.timeout??dt});return{success:i.exitCode===0,exitCode:i.exitCode,stdout:i.stdout,stderr:i.stderr,executionTimeMs:Date.now()-o,command:e,args:t}}}function he(e,t){let s=t.root??"/workspace";return new lt({id:`hlix-project:${t.projectId}`,name:"Hlix Coding Workspace",filesystem:new me(e,{root:s}),sandbox:new pe(e,{projectId:t.projectId,root:s})})}function xt(e,t){if(I.includes(e))return e;throw new w("invalid_usage",`${t==="flag"?"--sandbox":"sandbox in .hlix/config.json"} must be one of ${I.join(", ")}; got "${e}".`)}function ge(e){if(e.flag){let t=e.flagSource??"flag";return{choice:xt(e.flag,t),reason:t==="flag"?`--sandbox ${e.flag}`:"config"}}if(e.projectId)return{choice:"cloud",reason:`project ${e.projectId}`};if(e.dockerAvailable())return{choice:"docker",reason:"auto"};return{choice:"local",reason:"auto"}}var fe=(e)=>`sandbox: ${e.choice} (${e.reason})`;function xe(e=3000){try{return pt("docker",["info"],{timeout:e,stdio:"ignore"}),!0}catch{return!1}}function P(e,t){if(e.choice==="local")return;if(e.choice==="cloud"){if(!t.remote||!t.projectId)throw new w("invalid_usage","The cloud sandbox needs a hlix project. Run `hlix init`, pass --project <id>, or choose --sandbox docker|local.");return he(t.remote,{projectId:t.projectId})}let s="/workspace";return new ft({id:"hlix-code-docker",name:"Hlix Code (Docker)",filesystem:new gt({basePath:t.cwd}),...t.skills&&t.skills.length>0?{skills:t.skills}:{},sandbox:new ht({id:"hlix-code",volumes:{[t.cwd]:s},workingDirectory:s})})}var Rt=["Your name is Hlix Code. You are hlix's coding agent.","An earlier line of these instructions calls you Mastra Code — that is the","name of a framework hlix builds on, not your name. Never introduce yourself","as Mastra Code and never offer it as what the user is running. Naming the","underlying framework is fine when the user asks how hlix is implemented."].join(`
10
+ `),Mt=["Hlix Code could not resolve a model.","Run `hlix auth login` to use your workspace's models (no model key of your own needed),","or set your provider's key (ANTHROPIC_API_KEY, OPENAI_API_KEY, OPENROUTER_API_KEY) to use your own subscription."].join(`
11
+ `),Ot=(e)=>e instanceof Error?e.message:String(e),Tt=["You are running inside Hlix Code, the terminal harness for the hlix control plane.","Every `hlix` CLI command is available to you as a tool named `hlix_<command>`,","with spaces replaced by underscores — `hlix_status`, `hlix_tasks_list`, `hlix_push`.","Use those tools instead of running `hlix` through the shell: they resolve the","folder's workspace binding and credential the same way the CLI does, and they","return the CLI's machine-readable output.","Report a non-zero exit code and its stderr to the user verbatim. Never invent a","project, task or workspace id — read one with a tool first.","","This project's secrets live in the hlix secrets store, not in a file in this","folder: `hlix_secrets_list` shows them keyed by (key, source file) with every","value masked, and `hlix_secrets_set` changes one. When the user asks for a",'local env file, call `hlix_secrets_export` with `{ flags: { out: ".env" } }` —',"it writes the rendered file at mode 0600 and refuses a path git tracks. Do not","repeat an exported secret value back into the conversation."].join(`
12
+ `);function $t(e){if(!e||e.entries.length===0)return"";let t=e.entries.length,s=new Set(e.entries.map((r)=>r.source)).size;return`secrets: ${t} ${t===1?"entry":"entries"} (${s} ${s===1?"source":"sources"})`}async function Nt(e,t){try{return await h(process.env,{cwd:e,flags:{}}).secrets.listEntries(t)}catch{return null}}function Et(e){let{values:t}=kt({args:e,allowPositionals:!0,strict:!1,options:{local:{type:"boolean"},sandbox:{type:"string"},harness:{type:"string"},project:{type:"string"},cwd:{type:"string"}}}),s=typeof t.sandbox==="string"?t.sandbox:t.local===!0?"local":void 0;return{...s?{sandbox:s,sandboxSource:"flag"}:{},...typeof t.harness==="string"?{harness:t.harness}:{},...typeof t.project==="string"?{project:t.project}:{},cwd:bt(typeof t.cwd==="string"?t.cwd:".")}}function Ft(e){let t=Object.keys(x),r=e.sandbox==="cloud"?t:t.filter((a)=>e.installed(a)),o=["hlix",...r],n=t.filter((a)=>!r.includes(a)),i=e.requested.harness;if(i==="hlix"||r.includes(i))return{harness:e.requested,available:o,unavailable:n,refusal:null,warning:null};let c=H(x[i]);if(e.requested.source==="flag")return{harness:e.requested,available:o,unavailable:n,refusal:c,warning:null};return{harness:{harness:"hlix",source:"default"},available:o,unavailable:n,refusal:null,warning:`${c} Falling back to harness hlix.`}}async function Wt(e,t){try{let r=await h(process.env,{cwd:e,flags:{}}).modelConfig.resolvedProjectHarness(t);return{harness:r.harness,source:r.source}}catch{return null}}function Lt(e,t){let s=t.skills&&t.skills.length>0?{skills:t.skills}:{};if(e.choice!=="cloud")return P(e,{cwd:t.cwd,...s});if(!t.projectId)throw new w("invalid_usage","The cloud sandbox needs a hlix project. Run `hlix init`, pass --project <id>, or choose --sandbox docker|local.");let o=h(process.env,{cwd:t.cwd,flags:{}}).projects.workspace(t.projectId);return P(e,{cwd:t.cwd,projectId:t.projectId,remote:o})}var j=".hlix";function Dt(e){return e.skills.filter((t)=>!t.harnessReads).map((t)=>t.path)}function Bt(e,t){return e.skills.filter((s)=>s.scope==="project").map((s)=>yt(t,s.path)).filter((s)=>s!==""&&!s.startsWith(".."))}function Ut(e,t){if(e.length===0)return;let s={explore:"fast",plan:"plan",execute:"build"},r=t.find((a)=>a.metadata?.default===!0)?.id??t.find((a)=>a.id==="build")?.id??t[0]?.id,o=(a)=>t.find((d)=>d.id===s[a])?.defaultModelId??t.find((d)=>d.id===r)?.defaultModelId,n=[Ht,It,Ct].map((a)=>{let d=o(a.id);return{...a,...d?{defaultModelId:d}:{}}}),i=new Set(n.map((a)=>a.id)),c=e.filter((a)=>!i.has(a.name)).map((a)=>{let d=a.model??o("execute");return{id:a.name,name:a.name,description:a.description||`Project subagent from ${a.path}`,instructions:a.instructions,...a.tools?{allowedControllerTools:a.tools}:{},...d?{defaultModelId:d}:{}}});return[...n,...c]}var qt=new Set(["--sandbox","--harness","--project","--cwd"]),Yt=new Set(["--local"]);function Kt(e){let t=[];for(let s=0;s<e.length;s+=1){let r=e[s];if(Yt.has(r))continue;if(qt.has(r)){s+=1;continue}t.push(r)}return["node","hlix",...t]}async function Xt(e,t,s){let r=Kt(t);if(Pt(r)){let n=jt(r),c=await _t({controller:e.controller,session:e.session,prompt:n.prompt??"",...n.model?{model:n.model}:{},...n.maxTurns?{maxTurns:n.maxTurns}:{}}).result;if(process.stdout.write(`${c.text}
13
+ `),c.error)process.stderr.write(`${y(c.error.message)}
14
+ `);return c.exitCode}let o=new At({controller:e.controller,session:e.session,...e.hookManager?{hookManager:e.hookManager}:{},...e.mcpManager?{mcpManager:e.mcpManager}:{},...e.pluginManager?{pluginManager:e.pluginManager}:{},...e.knowledgeInspector?{knowledgeInspector:e.knowledgeInspector}:{},authStorage:e.authStorage,storageMaintenance:e.storageMaintenance,appName:"Hlix Code",version:s});return B(o),await o.run(),0}async function er(e,t={boot:vt,present:Xt}){let s=Et(e),r=we(s.cwd,process.env),o=s.project??r.merged.projectId,n=be(s.cwd,ye(process.env),{configDir:j}),i,c,a;try{if(c=ge({flag:s.sandbox??r.merged.sandbox,flagSource:s.sandbox?"flag":"config",projectId:o,dockerAvailable:()=>xe()}),a=Ft({requested:G({...s.harness?{flag:s.harness}:{},...r.merged.harness?{configured:r.merged.harness}:{},...r.sources.harness?{configSource:r.sources.harness}:{}}),sandbox:c.choice,installed:(l)=>J(x[l].command)}),a.refusal)throw new w("invalid_usage",a.refusal);i=Lt(c,{cwd:s.cwd,projectId:o,...c.choice==="docker"?{skills:Bt(n,s.cwd)}:{}})}catch(l){return process.stderr.write(`error: ${l instanceof Error?l.message:String(l)}
15
+ `),2}if(a.warning)process.stderr.write(`warning: ${a.warning}
16
+ `);if(c.choice==="cloud"){let l=o?await Wt(s.cwd,o):null;if(l&&s.harness&&s.harness!==l.harness)process.stderr.write(`warning: this project runs ${l.harness}. Run \`/harness ${s.harness}\` to make ${s.harness} the project's setting.
17
+ `);a={...a,harness:l??{harness:"unknown",source:o?"the project's setting could not be read":"no project bound"}}}let d=ce({wired:ae({cwd:s.cwd,env:process.env}),...r.merged.model?{configured:r.merged.model}:{},...r.sources.model?{configuredSource:r.sources.model}:{}}),_=fe(c);process.stdout.write(`${le(V(_,a.harness),d)}
18
+ `);let A=Se(n);if(A)process.stdout.write(`${A}
19
+ `);let R=o?$t(await Nt(s.cwd,o)):"";if(R)process.stdout.write(`${R}
20
+ `);K(s.cwd);let M=null,Ce=a.harness.harness==="unknown"?"hlix":a.harness.harness,O=Z({sandbox:c.choice,cwd:s.cwd,active:Ce,unavailable:a.unavailable,...i?{workspace:i}:{},...d?{model:d.id}:{}}),He=new Set(Object.keys(St(s.cwd,j).mcpServers??{})),T=Object.fromEntries(n.mcpServers.filter((l)=>!He.has(l.name)).map((l)=>[l.name,l.config])),N=ke(n.generatedCommands,s.cwd),E=[...n.commands.map((l)=>l.path),...N?[N]:[]],F=Dt(n),W=ie(O,d?.id),L=Ut(n.subagents,W),D=ve(n.instructions,s.cwd),{version:Ie}=await import("./package-f3wbdpaa.js"),Pe={configDir:j,cwd:s.cwd,coAuthor:{name:"Hlix Code",email:"noreply@hlix.ai"},hostInstructions:[Rt,Tt,...c.choice==="cloud"?[Q(a.harness.harness)]:[],...D?[D]:[]].join(`
21
+
22
+ `),...Object.keys(T).length>0?{mcpServers:T}:{},...L?{subagents:L}:{},...E.length>0||F.length>0?{initialState:{pluginCommandPaths:E,pluginSkillPaths:F}}:{},extraTools:{...q({cwd:s.cwd}),hlix_tasks_follow:te({cwd:s.cwd}),hlix_harness:ee({sandbox:c.choice,sandboxLine:_,available:a.available,modesBuilt:O.length>0,session:()=>M,...o?{setProjectHarness:async(l)=>{await h(process.env,{cwd:s.cwd,flags:{}}).modelConfig.setProjectHarness(o,l)}}:{}})},modes:W,...i?{workspace:i}:{}},k;try{k=await t.boot(Pe)}catch(l){return process.stderr.write(`error: ${y(Ot(l))}
23
+ ${Mt}
24
+ `),2}return M=k.session,t.present(k,e,Ie)}export{Dt as extraSkillPaths,Kt as headlessArgv,Et as parseHlixCodeArgs,Ft as planHarness,er as runHlixCode,$t as secretsStatusLine,Ut as standardsSubagents,Bt as workspaceSkillPaths};
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import"./index-syeavftx.js";var s="@hlix/cli",i="0.4.2",n="SEE LICENSE IN LICENSE",a="Hlix Code and the hlix control-plane CLI.",r=["hlix","cli","agents"],d="https://hlix.ai",p="module",c="./dist/index.js",o={hlix:"./dist/index.js"},l=["dist","skills","LICENSE","THIRD_PARTY_NOTICES"],u={node:">=22.19.0"},b={access:"public"},h={build:"rm -rf dist && bun build src/index.ts --outdir dist --target node --format esm --splitting --packages external --minify --banner '#!/usr/bin/env node'",test:'bun test --isolate src --path-ignore-patterns "**/*.integration.test.ts" --timeout 20000',typecheck:"tsc --noEmit",prepublishOnly:"bun run typecheck && bun run build && bun run test","test:integration":"NODE_ENV=test bun run ../../apps/backend/scripts/with-aimock.ts -- bun run ../../apps/backend/scripts/with-test-db.ts -- bun test --isolate --preload ../../apps/backend/test/helpers/pool-lifecycle.ts --timeout 60000 .integration.test.ts"},m={"@mastra/acp":"^0.4.1","@mastra/code-sdk":"1.7.0","@mastra/core":"1.65.0","@mastra/docker":"^0.7.0",ignore:"7.0.8",mastracode:"0.39.0","openapi-fetch":"^0.17.0",zod:"4.5.4"},g={"@hlix/sdk":"^0.2.0","@types/bun":"latest",typescript:"^7.0.2"},k={name:s,version:i,license:n,description:a,keywords:r,homepage:d,type:p,main:c,bin:o,files:l,engines:u,publishConfig:b,scripts:h,dependencies:m,devDependencies:g};export{o as bin,k as default,m as dependencies,a as description,g as devDependencies,u as engines,l as files,d as homepage,r as keywords,n as license,c as main,s as name,b as publishConfig,h as scripts,p as type,i as version};
2
+ import"./index-y1n35st0.js";var s="@hlix/cli",i="0.4.4",n="SEE LICENSE IN LICENSE",a="Hlix Code and the hlix control-plane CLI.",r=["hlix","cli","agents"],d="https://hlix.ai",p="module",c="./dist/index.js",o={hlix:"./dist/index.js"},l=["dist","skills","LICENSE","THIRD_PARTY_NOTICES"],u={node:">=22.19.0"},b={access:"public"},h={build:"rm -rf dist && bun build src/index.ts --outdir dist --target node --format esm --splitting --packages external --minify --banner '#!/usr/bin/env node'",test:'bun test --isolate src --path-ignore-patterns "**/*.integration.test.ts" --timeout 20000',typecheck:"tsc --noEmit",prepublishOnly:"bun run typecheck && bun run build && bun run test","test:integration":"NODE_ENV=test bun run ../../apps/backend/scripts/with-aimock.ts -- bun run ../../apps/backend/scripts/with-test-db.ts -- bun test --isolate --preload ../../apps/backend/test/helpers/pool-lifecycle.ts --timeout 60000 .integration.test.ts"},m={"@mastra/acp":"^0.4.1","@mastra/code-sdk":"1.7.1","@mastra/core":"1.66.0","@mastra/docker":"^0.7.0",ignore:"7.0.8",mastracode:"0.39.1","openapi-fetch":"^0.17.0",zod:"4.5.4"},g={"@hlix/sdk":"^0.2.0","@types/bun":"latest",typescript:"^7.0.2"},k={name:s,version:i,license:n,description:a,keywords:r,homepage:d,type:p,main:c,bin:o,files:l,engines:u,publishConfig:b,scripts:h,dependencies:m,devDependencies:g};export{o as bin,k as default,m as dependencies,a as description,g as devDependencies,u as engines,l as files,d as homepage,r as keywords,n as license,c as main,s as name,b as publishConfig,h as scripts,p as type,i as version};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hlix/cli",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "description": "Hlix Code and the hlix control-plane CLI.",
6
6
  "keywords": [
@@ -35,11 +35,11 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@mastra/acp": "^0.4.1",
38
- "@mastra/code-sdk": "1.7.0",
39
- "@mastra/core": "1.65.0",
38
+ "@mastra/code-sdk": "1.7.1",
39
+ "@mastra/core": "1.66.0",
40
40
  "@mastra/docker": "^0.7.0",
41
41
  "ignore": "7.0.8",
42
- "mastracode": "0.39.0",
42
+ "mastracode": "0.39.1",
43
43
  "openapi-fetch": "^0.17.0",
44
44
  "zod": "4.5.4"
45
45
  },
@@ -12,7 +12,7 @@ if they disagree, so this file cannot advertise something that does not exist.
12
12
  ## Authentication
13
13
 
14
14
  ```bash
15
- hlix auth login --workspace <id> [--base-url <url>]
15
+ hlix auth login [--workspace <id>] [--base-url <url>]
16
16
  hlix auth status [--json] # which credential, from where, does it work
17
17
  hlix auth logout [--yes] [--json] # remove the stored credential file
18
18
  ```
@@ -25,10 +25,16 @@ Reads the key from a hidden terminal prompt, verifies it against the API
25
25
  `HLIX_WORKSPACE_ID` set the target and workspace. Use those in CI rather than
26
26
  running a login step.
27
27
 
28
- `--workspace` is required at login: an API key authenticates a user but names
29
- no workspace, so the caller states one. `hlix auth login` verifies the key
30
- against a real call **before** writing it, so a key that does not work is never
31
- stored.
28
+ `--workspace` is **optional** at login. An API key authenticates a user and
29
+ names no workspace, so the key is read first and then used to list the
30
+ workspaces its owner belongs to (`GET /v1/api/workspaces`, the one endpoint that
31
+ needs no `X-Organization-Id`). With exactly one, that one is used and named on
32
+ stderr; with several, a terminal gets a numbered list to pick from and a
33
+ non-interactive run (`--json`, or no TTY) exits `missing_argument` listing the
34
+ ids so it can be re-run with `--workspace`. A `--workspace` that is not one of
35
+ them exits `workspace_mismatch` naming the ones that are, instead of storing a
36
+ credential that 403s later. `hlix auth login` then verifies the key against a
37
+ real call **before** writing it, so a key that does not work is never stored.
32
38
 
33
39
  `auth status` names the credential's **source** — the environment or the stored
34
40
  file — and probes it against the API. It never prints the key, not even a