craig-cli 0.6.2 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sam Hall
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -169,8 +169,38 @@ Craig writes local state under `.craig/`:
169
169
  worktrees/
170
170
  ```
171
171
 
172
- Treat `.craig/` as private developer state. It can contain task prompts, logs, local paths, PR metadata, and worktrees.
172
+ Treat `.craig/` as private developer state. It can contain task prompts, terminal logs, local paths, branch names, PR metadata, runtime state, and worktrees. Do not commit `.craig/` or share it in public issues.
173
+
174
+ Craig does not run a hosted service or upload `.craig/` state by itself. Commands that use external tools, such as `gh` or an agent CLI, follow the behavior and authentication model of those tools.
175
+
176
+ ## Open Source and Contributions
177
+
178
+ Craig is open source under the MIT license, but it is not currently a community-maintained project.
179
+
180
+ Issues are welcome for reproducible bugs, installation problems, and focused questions. Pull requests are not generally accepted unless they were discussed with the maintainer first, and unsolicited PRs may be closed without review.
181
+
182
+ See the GitHub repository for the contribution policy and private vulnerability reporting guidance.
173
183
 
174
184
  ## License
175
185
 
176
- Craig is proprietary software. All rights reserved.
186
+ MIT License
187
+
188
+ Copyright (c) 2026 Sam Hall
189
+
190
+ Permission is hereby granted, free of charge, to any person obtaining a copy
191
+ of this software and associated documentation files (the "Software"), to deal
192
+ in the Software without restriction, including without limitation the rights
193
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
194
+ copies of the Software, and to permit persons to whom the Software is
195
+ furnished to do so, subject to the following conditions:
196
+
197
+ The above copyright notice and this permission notice shall be included in all
198
+ copies or substantial portions of the Software.
199
+
200
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
201
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
202
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
203
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
204
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
205
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
206
+ SOFTWARE.
package/dist/cli.js CHANGED
@@ -180,7 +180,7 @@ ${p.slice(-2e3)}`:""}`)}async function Vo(e){let t=await Mh(e).catch(()=>null);r
180
180
  `)}function sa(e,t={}){let r=t.color??!0,s=te.overlay,o=new Array(e.height).fill(ce(" ".repeat(e.width),r,s)),p="Error Log",k=t.errorLogPath??"",i=t.errorLogLines??[],c=Math.max(20,e.width-8),d=Math.max(0,Math.floor((e.width-c)/2)),_=[{text:p,tone:"selected"},{text:k,tone:"muted"},Te(),...i.length>0?i.map(l=>({text:l})):[{text:"No Craig errors have been logged.",tone:"muted"}],Te(),{text:"Esc returns to Options.",tone:"muted"}],a=Ht(_,e.height-2),b=Math.max(1,Math.floor((e.height-a.length)/2));for(let l=0;l<a.length;l+=1){let m=b+l;if(m>=e.height)break;let w=a[l]??Te(),n=`${" ".repeat(d)}${xr(w.text,c)}`,g=w.tone==="selected"?te.overlayMenuSelected:w.tone==="muted"?te.overlay:te.panelBg;o[m]=ce(ze(n,e.width),r,g)}return o.join(`
181
181
  `)}function na(e,t,r={}){let s=r.color??!0,o=Ne.leftWidth,p=Ne.rightWidth,k=Ne.dividerWidth,i=r.centerOnly??!1,c=i?e.width:e.width-o-p-k*2,d=e.height-Ne.topRailHeight-1,_=`CRAIG | ${t.topRail.workspacePath} | ${t.topRail.agent}`,a=ce(ze(_,e.width),s,te.rail),b=Vh(t,o-Rr-Pr,d,s),l=zh(t,c,d,s),m=Yh(t,p,d,s),w=t.inputMode==="terminal",n=[];for(let u=0;u<d;u+=1){if(i){n.push(Tr(l[u]??Te(),c,s,"center"));continue}let h=Tr(b[u]??Te(),o,s,"left"),y=ce("\u2502",s,te.divider),S=Tr(l[u]??Te(),c,s,"center"),I=ce("\u2502",s,te.divider),x=Tr(m[u]??Te(),p,s,"right");n.push(`${h}${y}${S}${I}${x}`)}let g=w||t.modalInput?te.panelBg:te.panelMuted,f=Kh(t.footerText,t.footerToast,e.width,s,g);return[a,...n,f].join(`
182
182
  `)}function Kh(e,t,r,s,o){let p=` ${e}`;if(!t)return ce(ze(p,r),s,o);let k=`${t.tone==="error"?"\u2717":"\u2713"} ${t.message}`,i=ke(k),c=ke(p),d=Math.max(1,r-c-i-2),_=c+d+i+2>r?xr(p,Math.max(0,r-i-3)):p,a=Math.max(1,r-ke(_)-i-2),b=t.tone==="error"?gf(k,s,o):vt(k,s,o),l=`${_}${" ".repeat(a)}${b} `;return ce(ze(l,r),s,o)}function Us(e,t){let r=new Array(e.height).fill(ce(" ".repeat(e.width),t.color,te.overlay)),s=Ws(),o=Math.max(...t.menuItems.map(d=>d.length)),p=t.menuItems.map((d,_)=>`${_===t.menuIndex?">":" "} ${d.padEnd(o)}`),k=t.optionsMessage?["",t.optionsMessage]:[],i=[...s,"",t.subtitle,"",...p,...k],c=Math.max(1,Math.floor((e.height-i.length)/2));for(let d=0;d<i.length;d+=1){let _=aa(i[d]??"",e.width);if(d<s.length){r[c+d]=ce(_,t.color,te.overlayLogo);continue}if(d===s.length+1){r[c+d]=ce(_,t.color,te.overlaySubtitle);continue}let a=d-(s.length+3),l=a>=0&&a<t.menuItems.length&&a===t.menuIndex?te.overlayMenuSelected:te.overlay;r[c+d]=ce(_,t.color,l)}if(t.versionText){let d=t.updateText?" (update available)":"",_=`${t.versionText}${d} `,a=" ".repeat(Math.max(0,e.width-ke(_)));r[e.height-1]=ce(`${a}${qs(_,t.color,te.overlay)}`,t.color,te.overlay)}return r.join(`
183
- `)}function Vh(e,t,r,s){let o=Jh(e.runners),p=1,k=e.leftTree.map(c=>Qh(c,t,s));return[...Ht(k,r-p),o]}function zh(e,t,r,s){let o=t-2,p=e.tabs.find(h=>h.active)?.label??"AGENT",k=e.inputMode==="terminal"?0:hf(e.tabs),i=e.inputMode==="terminal"?o:p.length+1,c="\u2500".repeat(Math.max(0,i)),d=`${" ".repeat(k)}${e.inputMode==="terminal"?vt(c,s,te.panelBg):Ir(c,s,te.panelMuted)}`,_=[`${Ir(e.centerHeader.tabLabel,s,te.panelBg)} ${e.centerHeader.taskId}`,e.centerHeader.repo].join(" \xB7 "),a=e.tabs.find(h=>h.active)?.id??"agent",b=e.centerHeader.tabLabel==="BROWSER"||!lo(a)?e.centerTranscript.map(h=>({...h})):Gh(e),l=Zh(e.tabs,s,e.focusedRegion==="center"),m=" engaged ",w=m.length+2,n=e.inputMode==="terminal"?vt(`${m}\u25CF `,s,te.panelBg):"",g=e.inputMode==="terminal"?" ".repeat(Math.max(0,o-ke(l)-w)):"",u=[{text:e.inputMode==="terminal"?`${l}${g}${n}`:l},{text:d,tone:"muted"},{text:_},Te(),...b];return Ht(u,r)}function Gh(e){if(e.terminal.error)return[{text:"terminal \u25B8 PTY unavailable"},Te(),{text:e.terminal.error},Te(),{text:"Fix the native dependency setup, then re-enter terminal mode."}];let t=e.tabs.find(s=>s.active)?.id??"",r=t==="agent"||/:agent(?:-\d+)?$/.test(t)?"agent":"terminal";return e.terminal.rows.length===0?[{text:`Press Enter on the ${r.toUpperCase()} tab to attach a PTY.`}]:e.terminal.rows.map(s=>({text:da(s.segments),segments:s.segments,fullBleed:!0}))}function Yh(e,t,r,s){let o=e.rightInspection?Xh(e.actionMessage?[...e.rightInspection.rows.slice(0,2),{id:"action-message",text:e.actionMessage},{id:"action-message-spacer",text:""},...e.rightInspection.rows.slice(2)]:e.rightInspection.rows,r):Ht([{text:"CONTEXT"},Te(),...e.rightContext.map(p=>ef(p,s)),...e.actionMessage?[Te(),{text:e.actionMessage}]:[]],r);return Ht(o,r)}function Xh(e,t){let r=e.slice(0,2),s=e.slice(2),o=Math.max(0,t-r.length),p=s.findIndex(i=>i.focused||i.selected),k=p===-1?0:pf(p-Math.floor(o/2),0,Math.max(0,s.length-o));return[...r.map(i=>Qo(i)),...s.slice(k,k+o).map(i=>Qo(i))]}function Qo(e){let t=e.focused?"\u25B8 ":e.selected?"\u2022 ":" ",r=e.focused||e.selected?"selected":e.muted?"muted":"default",s=`${t}${e.text}`;if(e.segments)return{text:s,segments:[{text:t},...e.segments],tone:r};if(e.accentPrefix&&!e.muted){let o=e.text.indexOf(" "),p=o===-1?e.text:e.text.slice(0,o),k=o===-1?"":e.text.slice(o);return{text:s,segments:[{text:t},{text:p,style:{fg:"7aa2f7"}},{text:k}],tone:r}}return e.color?{text:s,segments:[{text:t},{text:e.text,style:{fg:e.color}}],tone:r}:{text:s,tone:r}}function Qh(e,t,r){let s=" ".repeat(e.indent??0),o=e.accentDot?" \u25CF":"",p=e.status?` ${e.status}`:"",k=e.accentDot?` ${vt("\u25CF",r,e.selected?te.panelSelected:te.panelBg)}`:"",i=e.prBadge?e.prBadge.reduce((l,m)=>l+ke(m.text),0):0,c=t-ke(p)-ke(o)-i,d=e.selected?e.text:e.focused?vt(e.text,r,te.panelBg):e.panelHeader?Ir(e.text,r,te.panelMuted):e.text,_=ze(`${s}${d}`,Math.max(0,c)),a=e.selected?"selected":e.muted?"muted":"default";if(e.prBadge){let l=[{text:`${_}${p}${k}`},...e.prBadge];return{text:`${_}${p}${e.prBadge.map(w=>w.text).join("")}`,segments:l,tone:a}}return{text:`${_}${p}${k}`,tone:a}}function Jh(e){let t=e.map(s=>{let o=s.health>=1,p=parseInt(s.count,10),k=p>1?` (${p})`:"";return{text:`${o?"\u25CF":"\u25CB"} ${s.name}${k}`,active:o}}),r=[];for(let s=0;s<t.length;s++){let o=t[s];s>0&&r.push({text:" "}),o.active?r.push({text:o.text,style:{fg:te.success.fg}}):r.push({text:o.text,style:{fg:te.panelMuted.fg}})}return{text:t.map(s=>s.text).join(" "),segments:r,tone:"muted"}}function Zh(e,t,r){return e.map(s=>s.active?r?vt(s.label,t,te.panelBg):Ir(s.label,t,te.panelBg):qs(s.label,t,te.panelBg)).join(" ")}function ef(e,t){return{text:`${e.label.padEnd(8," ")} ${e.mutedValue?qs(e.value,t,te.panelBg):e.value}`}}function Tr(e,t,r,s){let o=tf(s,e.tone??"default"),p=rf(e,r,o);if(s==="left"){if(e.fullBleed)return ce(ze(p,t),r,o);let i=t-Rr-Pr;if(e.rightAlign){let d=ke(p),_=Math.max(0,i-d),a=`${" ".repeat(Rr)}${" ".repeat(_)}${p}${" ".repeat(Pr)}`;return ce(a,r,o)}let c=`${" ".repeat(Rr)}${ze(p,i)}${" ".repeat(Pr)}`;return ce(c,r,o)}return s==="center"&&e.fullBleed?sf(e,t,r,o):ce(ze(` ${p}`,t),r,o)}function tf(e,t){return t==="selected"||t==="focused"?te.panelSelected:t==="muted"?te.panelMuted:te.panelBg}function Ht(e,t){let r=e.slice(0,t);for(;r.length<t;)r.push(Te());return r}function Te(){return{text:""}}function rf(e,t,r){return e.segments?e.segments.map(s=>ia(s,t,r)).join(""):e.text}function sf(e,t,r,s){let o=" ".repeat(Cr),p=Math.max(0,t-Cr*2);if(!e.segments)return ce(`${o}${ze(e.text,p)}${o}`,r,s);let k=af(e.segments,p),i=`${o}${k.map(c=>ia(c,r,s)).join("")}${o}`;return ce(i,r,s)}function ia(e,t,r){let s=e.href?`${oa(e.href)}${e.text}${Zo}`:nf(e.text);return!t||!e.style?s:`${Ut(df(e.style,r))}${uf(e.style)}${s}${js}${Ut(r)}`}function nf(e){return e.replace(Uh,t=>{let[r,s]=of(t);return`${oa(r)}${r}${Zo}${s}`})}function of(e){let t=e.length;for(;t>0&&".,;:!?)]}".includes(e[t-1]??"");)t-=1;return[e.slice(0,t),e.slice(t)]}function oa(e){return`\x1B]8;;${e}\x1B\\`}function af(e,t){let r=cf(e,t);return lf(r,t)}function cf(e,t){let r=[],s=t;for(let o of e){if(s<=0)break;let p=ke(o.text);if(p<=s){r.push(o),s-=p;continue}let k=xr(o.text,s);k.length>0&&r.push({...o,text:k}),s=0}return r}function lf(e,t){let r=ke(da(e));if(r>=t)return e;let s=e.at(-1)?.style;return s?.bg?[...e,{text:" ".repeat(t-r),style:s}]:[...e,{text:" ".repeat(t-r)}]}function df(e,t){let r=e.inverse?e.bg??t.bg:e.fg,s=e.inverse?e.fg??t.fg:e.bg,o={},p=r??t.fg,k=s??t.bg;return p&&(o.fg=p),k&&(o.bg=k),o}function uf(e){let t=[];return e.bold&&t.push("1"),e.dim&&t.push("2"),e.italic&&t.push("3"),e.underline&&t.push("4"),t.length>0?`\x1B[${t.join(";")}m`:""}function hf(e){let t=0;for(let r of e){if(r.active)return t;t+=r.label.length+3}return 0}function aa(e,t){let r=Math.max(0,t-ke(e)),s=Math.floor(r/2),o=r-s;return`${" ".repeat(s)}${e}${" ".repeat(o)}`}function ze(e,t){let r=ke(e);return r>=t?ff(e,t):e+" ".repeat(t-r)}function ff(e,t){if(t<=0)return"";if(ke(e)<=t)return e;let r=la(e);return xr(r,Math.max(0,t-1))+"\u2026"}function ke(e){let t=0;for(let r of Array.from(la(e)))t+=ca(r);return t}function xr(e,t){let r="",s=0;for(let o of Array.from(e)){let p=ca(o);if(s+p>t)break;r+=o,s+=p}return r}function ca(e){let t=e.codePointAt(0);return t===void 0||t===0||t<32||t>=127&&t<160||t>=768&&t<=879||t>=6832&&t<=6911||t>=7616&&t<=7679||t>=8400&&t<=8447||t>=65024&&t<=65039?0:t>=4352&&(t<=4447||t===9001||t===9002||t>=11904&&t<=42191&&t!==12351||t>=44032&&t<=55203||t>=63744&&t<=64255||t>=65040&&t<=65049||t>=65072&&t<=65135||t>=65280&&t<=65376||t>=65504&&t<=65510||t>=127744&&t<=129791||t>=131072&&t<=262141)?2:1}function pf(e,t,r){return Math.min(Math.max(e,t),r)}function la(e){return e.replace(Hh,"").replace(Wh,"")}function da(e){return e.map(t=>t.text).join("")}function ce(e,t,r){if(!t)return e;let s=Ut(r),o=e.replace(jh,`${js}${s}`);return`${s}${o}${js}`}function Ut(e){let t=[];return e.fg&&t.push(`38;2;${Jo(e.fg).join(";")}`),e.bg&&t.push(`48;2;${Jo(e.bg).join(";")}`),`\x1B[${t.join(";")}m`}function Jo(e){return[Number.parseInt(e.slice(0,2),16),Number.parseInt(e.slice(2,4),16),Number.parseInt(e.slice(4,6),16)]}function vt(e,t,r){return Er(e,t,te.success.fg,r)}function gf(e,t,r){return Er(e,t,te.error.fg,r)}function Ir(e,t,r){return Er(e,t,te.accent.fg,r)}function qs(e,t,r){return Er(e,t,te.mutedfg.fg,r)}function Er(e,t,r,s){if(!t)return e;let o=s.bg?{fg:r,bg:s.bg}:{fg:r};return`${Ut(o)}${e}${Ut(s)}`}var mf="https://registry.npmjs.org/craig-cli/latest";var Ar=null;function Ks(){try{return"0.6.2"}catch{return"unknown"}}async function ua(){let e=Ks(),t=Date.now();if(Ar&&t-Ar.cachedAt<36e5)return Ar.result;let r=null;try{let o=await fetch(mf,{signal:AbortSignal.timeout(5e3)});o.ok&&(r=(await o.json()).version??null)}catch{}let s={current:e,latest:r,updateAvailable:r!==null&&r!==e&&_f(r,e)};return Ar={result:s,cachedAt:t},s}function _f(e,t){let r=d=>d.split(".").map(Number),[s=0,o=0,p=0]=r(e),[k=0,i=0,c=0]=r(t);return s!==k?s>k:o!==i?o>i:p>c}Me();var Vs=["Runners","Error Log","Help"];function zs(e,t){return ue.map(r=>{let s=Se(r),o=e.runners?.[r]?.enabled!==!1,p=e.runners?.[r]?.path?.trim(),k=t.pathEdit?.runner===r?`${t.pathEdit.value}_`:p&&p.length>0?p:`default (${s.executable})`;return`${s.displayName} ${o?"enabled":"disabled"} ${k}`})}function fa(e){return e.message?e.message:e.pathEdit?"Type an executable path. Enter saves. Empty resets to default. Esc cancels.":"Enter toggles. E edits the executable path."}function pa(e,t){return t==="UP"||t==="k"?{kind:"render",menuIndex:Math.max(0,e-1)}:t==="DOWN"||t==="j"?{kind:"render",menuIndex:Math.min(Vs.length-1,e+1)}:t==="ESCAPE"?{kind:"back"}:Gs(t)?e===0?{kind:"runners"}:e===1?{kind:"error-log"}:{kind:"help"}:{kind:"noop",menuIndex:e}}function ga(e,t,r,s){if(e.pathEdit)return wf({...e,pathEdit:e.pathEdit},t,r);let o=zs(t,e).length;if(r==="UP"||r==="k")return{kind:"render",state:{...e,menuIndex:Math.max(0,e.menuIndex-1),message:null}};if(r==="DOWN"||r==="j")return{kind:"render",state:{...e,menuIndex:Math.min(o-1,e.menuIndex+1),message:null}};if(r==="ESCAPE")return{kind:"back",state:e};if(r==="e"){let i=ue[e.menuIndex]??"codex";return{kind:"render",state:{...e,message:null,pathEdit:{runner:i,value:t.runners?.[i]?.path??""}}}}if(!Gs(r))return{kind:"noop",state:e};let p=ue[e.menuIndex]??"codex",k=t.runners?.[p]?.enabled!==!1;return k&&s.length<=1?{kind:"render",state:{...e,message:"At least one runner must stay enabled."}}:{kind:"save",config:bf(t,p,!k),state:{...e,message:`${Se(p).displayName} ${k?"disabled":"enabled"}.`}}}function wf(e,t,r){if(r==="ESCAPE")return{kind:"render",state:ha({...e,message:null})};if(r==="BACKSPACE")return{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:e.pathEdit.value.slice(0,-1)}}};if(Gs(r)){let s=e.pathEdit.runner,o=e.pathEdit.value.trim();return{kind:"save",config:kf(t,s,o.length>0?o:null),state:ha({...e,message:o.length>0?`${Se(s).displayName} executable saved.`:`${Se(s).displayName} executable reset to default.`})}}return yf(r)?{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:`${e.pathEdit.value}${r}`}}}:{kind:"noop",state:e}}function bf(e,t,r){return{...e,runners:{...e.runners??{},[t]:{...e.runners?.[t]??{},enabled:r}}}}function kf(e,t,r){let s={...e.runners?.[t]??{},...r?{path:r}:{}};return r||delete s.path,{...e,runners:{...e.runners??{},[t]:s}}}function ha(e){let t={...e};return delete t.pathEdit,t}function Gs(e){return e==="ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
183
+ `)}function Vh(e,t,r,s){let o=Jh(e.runners),p=1,k=e.leftTree.map(c=>Qh(c,t,s));return[...Ht(k,r-p),o]}function zh(e,t,r,s){let o=t-2,p=e.tabs.find(h=>h.active)?.label??"AGENT",k=e.inputMode==="terminal"?0:hf(e.tabs),i=e.inputMode==="terminal"?o:p.length+1,c="\u2500".repeat(Math.max(0,i)),d=`${" ".repeat(k)}${e.inputMode==="terminal"?vt(c,s,te.panelBg):Ir(c,s,te.panelMuted)}`,_=[`${Ir(e.centerHeader.tabLabel,s,te.panelBg)} ${e.centerHeader.taskId}`,e.centerHeader.repo].join(" \xB7 "),a=e.tabs.find(h=>h.active)?.id??"agent",b=e.centerHeader.tabLabel==="BROWSER"||!lo(a)?e.centerTranscript.map(h=>({...h})):Gh(e),l=Zh(e.tabs,s,e.focusedRegion==="center"),m=" engaged ",w=m.length+2,n=e.inputMode==="terminal"?vt(`${m}\u25CF `,s,te.panelBg):"",g=e.inputMode==="terminal"?" ".repeat(Math.max(0,o-ke(l)-w)):"",u=[{text:e.inputMode==="terminal"?`${l}${g}${n}`:l},{text:d,tone:"muted"},{text:_},Te(),...b];return Ht(u,r)}function Gh(e){if(e.terminal.error)return[{text:"terminal \u25B8 PTY unavailable"},Te(),{text:e.terminal.error},Te(),{text:"Fix the native dependency setup, then re-enter terminal mode."}];let t=e.tabs.find(s=>s.active)?.id??"",r=t==="agent"||/:agent(?:-\d+)?$/.test(t)?"agent":"terminal";return e.terminal.rows.length===0?[{text:`Press Enter on the ${r.toUpperCase()} tab to attach a PTY.`}]:e.terminal.rows.map(s=>({text:da(s.segments),segments:s.segments,fullBleed:!0}))}function Yh(e,t,r,s){let o=e.rightInspection?Xh(e.actionMessage?[...e.rightInspection.rows.slice(0,2),{id:"action-message",text:e.actionMessage},{id:"action-message-spacer",text:""},...e.rightInspection.rows.slice(2)]:e.rightInspection.rows,r):Ht([{text:"CONTEXT"},Te(),...e.rightContext.map(p=>ef(p,s)),...e.actionMessage?[Te(),{text:e.actionMessage}]:[]],r);return Ht(o,r)}function Xh(e,t){let r=e.slice(0,2),s=e.slice(2),o=Math.max(0,t-r.length),p=s.findIndex(i=>i.focused||i.selected),k=p===-1?0:pf(p-Math.floor(o/2),0,Math.max(0,s.length-o));return[...r.map(i=>Qo(i)),...s.slice(k,k+o).map(i=>Qo(i))]}function Qo(e){let t=e.focused?"\u25B8 ":e.selected?"\u2022 ":" ",r=e.focused||e.selected?"selected":e.muted?"muted":"default",s=`${t}${e.text}`;if(e.segments)return{text:s,segments:[{text:t},...e.segments],tone:r};if(e.accentPrefix&&!e.muted){let o=e.text.indexOf(" "),p=o===-1?e.text:e.text.slice(0,o),k=o===-1?"":e.text.slice(o);return{text:s,segments:[{text:t},{text:p,style:{fg:"7aa2f7"}},{text:k}],tone:r}}return e.color?{text:s,segments:[{text:t},{text:e.text,style:{fg:e.color}}],tone:r}:{text:s,tone:r}}function Qh(e,t,r){let s=" ".repeat(e.indent??0),o=e.accentDot?" \u25CF":"",p=e.status?` ${e.status}`:"",k=e.accentDot?` ${vt("\u25CF",r,e.selected?te.panelSelected:te.panelBg)}`:"",i=e.prBadge?e.prBadge.reduce((l,m)=>l+ke(m.text),0):0,c=t-ke(p)-ke(o)-i,d=e.selected?e.text:e.focused?vt(e.text,r,te.panelBg):e.panelHeader?Ir(e.text,r,te.panelMuted):e.text,_=ze(`${s}${d}`,Math.max(0,c)),a=e.selected?"selected":e.muted?"muted":"default";if(e.prBadge){let l=[{text:`${_}${p}${k}`},...e.prBadge];return{text:`${_}${p}${e.prBadge.map(w=>w.text).join("")}`,segments:l,tone:a}}return{text:`${_}${p}${k}`,tone:a}}function Jh(e){let t=e.map(s=>{let o=s.health>=1,p=parseInt(s.count,10),k=p>1?` (${p})`:"";return{text:`${o?"\u25CF":"\u25CB"} ${s.name}${k}`,active:o}}),r=[];for(let s=0;s<t.length;s++){let o=t[s];s>0&&r.push({text:" "}),o.active?r.push({text:o.text,style:{fg:te.success.fg}}):r.push({text:o.text,style:{fg:te.panelMuted.fg}})}return{text:t.map(s=>s.text).join(" "),segments:r,tone:"muted"}}function Zh(e,t,r){return e.map(s=>s.active?r?vt(s.label,t,te.panelBg):Ir(s.label,t,te.panelBg):qs(s.label,t,te.panelBg)).join(" ")}function ef(e,t){return{text:`${e.label.padEnd(8," ")} ${e.mutedValue?qs(e.value,t,te.panelBg):e.value}`}}function Tr(e,t,r,s){let o=tf(s,e.tone??"default"),p=rf(e,r,o);if(s==="left"){if(e.fullBleed)return ce(ze(p,t),r,o);let i=t-Rr-Pr;if(e.rightAlign){let d=ke(p),_=Math.max(0,i-d),a=`${" ".repeat(Rr)}${" ".repeat(_)}${p}${" ".repeat(Pr)}`;return ce(a,r,o)}let c=`${" ".repeat(Rr)}${ze(p,i)}${" ".repeat(Pr)}`;return ce(c,r,o)}return s==="center"&&e.fullBleed?sf(e,t,r,o):ce(ze(` ${p}`,t),r,o)}function tf(e,t){return t==="selected"||t==="focused"?te.panelSelected:t==="muted"?te.panelMuted:te.panelBg}function Ht(e,t){let r=e.slice(0,t);for(;r.length<t;)r.push(Te());return r}function Te(){return{text:""}}function rf(e,t,r){return e.segments?e.segments.map(s=>ia(s,t,r)).join(""):e.text}function sf(e,t,r,s){let o=" ".repeat(Cr),p=Math.max(0,t-Cr*2);if(!e.segments)return ce(`${o}${ze(e.text,p)}${o}`,r,s);let k=af(e.segments,p),i=`${o}${k.map(c=>ia(c,r,s)).join("")}${o}`;return ce(i,r,s)}function ia(e,t,r){let s=e.href?`${oa(e.href)}${e.text}${Zo}`:nf(e.text);return!t||!e.style?s:`${Ut(df(e.style,r))}${uf(e.style)}${s}${js}${Ut(r)}`}function nf(e){return e.replace(Uh,t=>{let[r,s]=of(t);return`${oa(r)}${r}${Zo}${s}`})}function of(e){let t=e.length;for(;t>0&&".,;:!?)]}".includes(e[t-1]??"");)t-=1;return[e.slice(0,t),e.slice(t)]}function oa(e){return`\x1B]8;;${e}\x1B\\`}function af(e,t){let r=cf(e,t);return lf(r,t)}function cf(e,t){let r=[],s=t;for(let o of e){if(s<=0)break;let p=ke(o.text);if(p<=s){r.push(o),s-=p;continue}let k=xr(o.text,s);k.length>0&&r.push({...o,text:k}),s=0}return r}function lf(e,t){let r=ke(da(e));if(r>=t)return e;let s=e.at(-1)?.style;return s?.bg?[...e,{text:" ".repeat(t-r),style:s}]:[...e,{text:" ".repeat(t-r)}]}function df(e,t){let r=e.inverse?e.bg??t.bg:e.fg,s=e.inverse?e.fg??t.fg:e.bg,o={},p=r??t.fg,k=s??t.bg;return p&&(o.fg=p),k&&(o.bg=k),o}function uf(e){let t=[];return e.bold&&t.push("1"),e.dim&&t.push("2"),e.italic&&t.push("3"),e.underline&&t.push("4"),t.length>0?`\x1B[${t.join(";")}m`:""}function hf(e){let t=0;for(let r of e){if(r.active)return t;t+=r.label.length+3}return 0}function aa(e,t){let r=Math.max(0,t-ke(e)),s=Math.floor(r/2),o=r-s;return`${" ".repeat(s)}${e}${" ".repeat(o)}`}function ze(e,t){let r=ke(e);return r>=t?ff(e,t):e+" ".repeat(t-r)}function ff(e,t){if(t<=0)return"";if(ke(e)<=t)return e;let r=la(e);return xr(r,Math.max(0,t-1))+"\u2026"}function ke(e){let t=0;for(let r of Array.from(la(e)))t+=ca(r);return t}function xr(e,t){let r="",s=0;for(let o of Array.from(e)){let p=ca(o);if(s+p>t)break;r+=o,s+=p}return r}function ca(e){let t=e.codePointAt(0);return t===void 0||t===0||t<32||t>=127&&t<160||t>=768&&t<=879||t>=6832&&t<=6911||t>=7616&&t<=7679||t>=8400&&t<=8447||t>=65024&&t<=65039?0:t>=4352&&(t<=4447||t===9001||t===9002||t>=11904&&t<=42191&&t!==12351||t>=44032&&t<=55203||t>=63744&&t<=64255||t>=65040&&t<=65049||t>=65072&&t<=65135||t>=65280&&t<=65376||t>=65504&&t<=65510||t>=127744&&t<=129791||t>=131072&&t<=262141)?2:1}function pf(e,t,r){return Math.min(Math.max(e,t),r)}function la(e){return e.replace(Hh,"").replace(Wh,"")}function da(e){return e.map(t=>t.text).join("")}function ce(e,t,r){if(!t)return e;let s=Ut(r),o=e.replace(jh,`${js}${s}`);return`${s}${o}${js}`}function Ut(e){let t=[];return e.fg&&t.push(`38;2;${Jo(e.fg).join(";")}`),e.bg&&t.push(`48;2;${Jo(e.bg).join(";")}`),`\x1B[${t.join(";")}m`}function Jo(e){return[Number.parseInt(e.slice(0,2),16),Number.parseInt(e.slice(2,4),16),Number.parseInt(e.slice(4,6),16)]}function vt(e,t,r){return Er(e,t,te.success.fg,r)}function gf(e,t,r){return Er(e,t,te.error.fg,r)}function Ir(e,t,r){return Er(e,t,te.accent.fg,r)}function qs(e,t,r){return Er(e,t,te.mutedfg.fg,r)}function Er(e,t,r,s){if(!t)return e;let o=s.bg?{fg:r,bg:s.bg}:{fg:r};return`${Ut(o)}${e}${Ut(s)}`}var mf="https://registry.npmjs.org/craig-cli/latest";var Ar=null;function Ks(){try{return"0.6.3"}catch{return"unknown"}}async function ua(){let e=Ks(),t=Date.now();if(Ar&&t-Ar.cachedAt<36e5)return Ar.result;let r=null;try{let o=await fetch(mf,{signal:AbortSignal.timeout(5e3)});o.ok&&(r=(await o.json()).version??null)}catch{}let s={current:e,latest:r,updateAvailable:r!==null&&r!==e&&_f(r,e)};return Ar={result:s,cachedAt:t},s}function _f(e,t){let r=d=>d.split(".").map(Number),[s=0,o=0,p=0]=r(e),[k=0,i=0,c=0]=r(t);return s!==k?s>k:o!==i?o>i:p>c}Me();var Vs=["Runners","Error Log","Help"];function zs(e,t){return ue.map(r=>{let s=Se(r),o=e.runners?.[r]?.enabled!==!1,p=e.runners?.[r]?.path?.trim(),k=t.pathEdit?.runner===r?`${t.pathEdit.value}_`:p&&p.length>0?p:`default (${s.executable})`;return`${s.displayName} ${o?"enabled":"disabled"} ${k}`})}function fa(e){return e.message?e.message:e.pathEdit?"Type an executable path. Enter saves. Empty resets to default. Esc cancels.":"Enter toggles. E edits the executable path."}function pa(e,t){return t==="UP"||t==="k"?{kind:"render",menuIndex:Math.max(0,e-1)}:t==="DOWN"||t==="j"?{kind:"render",menuIndex:Math.min(Vs.length-1,e+1)}:t==="ESCAPE"?{kind:"back"}:Gs(t)?e===0?{kind:"runners"}:e===1?{kind:"error-log"}:{kind:"help"}:{kind:"noop",menuIndex:e}}function ga(e,t,r,s){if(e.pathEdit)return wf({...e,pathEdit:e.pathEdit},t,r);let o=zs(t,e).length;if(r==="UP"||r==="k")return{kind:"render",state:{...e,menuIndex:Math.max(0,e.menuIndex-1),message:null}};if(r==="DOWN"||r==="j")return{kind:"render",state:{...e,menuIndex:Math.min(o-1,e.menuIndex+1),message:null}};if(r==="ESCAPE")return{kind:"back",state:e};if(r==="e"){let i=ue[e.menuIndex]??"codex";return{kind:"render",state:{...e,message:null,pathEdit:{runner:i,value:t.runners?.[i]?.path??""}}}}if(!Gs(r))return{kind:"noop",state:e};let p=ue[e.menuIndex]??"codex",k=t.runners?.[p]?.enabled!==!1;return k&&s.length<=1?{kind:"render",state:{...e,message:"At least one runner must stay enabled."}}:{kind:"save",config:bf(t,p,!k),state:{...e,message:`${Se(p).displayName} ${k?"disabled":"enabled"}.`}}}function wf(e,t,r){if(r==="ESCAPE")return{kind:"render",state:ha({...e,message:null})};if(r==="BACKSPACE")return{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:e.pathEdit.value.slice(0,-1)}}};if(Gs(r)){let s=e.pathEdit.runner,o=e.pathEdit.value.trim();return{kind:"save",config:kf(t,s,o.length>0?o:null),state:ha({...e,message:o.length>0?`${Se(s).displayName} executable saved.`:`${Se(s).displayName} executable reset to default.`})}}return yf(r)?{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:`${e.pathEdit.value}${r}`}}}:{kind:"noop",state:e}}function bf(e,t,r){return{...e,runners:{...e.runners??{},[t]:{...e.runners?.[t]??{},enabled:r}}}}function kf(e,t,r){let s={...e.runners?.[t]??{},...r?{path:r}:{}};return r||delete s.path,{...e,runners:{...e.runners??{},[t]:s}}}function ha(e){let t={...e};return delete t.pathEdit,t}function Gs(e){return e==="ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
184
184
  `}function yf(e){return e.length===1&&e>=" "&&e!=="\x7F"}var Rf=vf(import.meta.url),Pf=Rf("terminal-kit"),Cf=Pf.terminal;async function wa(e={}){if(!process.stdin.isTTY||!process.stdout.isTTY)throw new Error("Craig terminal shell requires a TTY.");let t=e.workspaceRoot??process.cwd(),r=Ge(t);await kt(t);let s=await He(r),o=pt(s),p=e.uiStateFile?await Oe({uiStateFile:e.uiStateFile}):null,k=Promise.resolve(),i=Promise.resolve(),c=await qt(t,void 0,o),d=mr(no(p,s),c);c=await qt(t,d,o);let _=()=>{},a={workspaceRoot:t,onUpdate:()=>_(),resolveSessionSpec:(m,w)=>Af(c,w,t)},b=e.ptyRuntime??await Uo({...a,paths:r}),l=m=>{if(!e.uiStateFile)return;p=io(p,m);let w=p;k=k.then(()=>xe({uiStateFile:e.uiStateFile},w),()=>xe({uiStateFile:e.uiStateFile},w)),k.catch(()=>{})};return new Promise(m=>{let w=e.terminal??Cf,n={mode:"overlay",variant:"boot",menuIndex:0,optionsMessage:null,shell:mr(d,c)},g=!1,f=!1,u=null,h=0,y=0,S=null,I=null,x=null,N=null,F=null,D=!1,A=null,E=`Craig v${Ks()}`,U=null,z=0,V=!0,G=null,B=()=>{},v=b;_=()=>{n.mode==="main"&&(n={mode:"main",shell:P(n.shell)},x||(x=setTimeout(()=>{x=null,n.mode==="main"&&B()},50)))};function P(M){return Wt(M,v.getViewState(R(M)))}function R(M){let L=$(M);return L?L.ptyTabs.some(O=>O.id===M.activeTab)?M.activeTab:M.activeTab==="agent"||M.activeTab==="terminal"?L.ptyTabs.find(O=>O.kind===M.activeTab)?.id??M.selectedPtyTabId:M.selectedPtyTabId:M.selectedPtyTabId}function T(M){return P(If(M,c))}function $(M){return c.tasks.find(L=>L.id===M.selectedTaskId)??null}async function W(){let M=c.tasks.flatMap(L=>L.ptyTabs.map(O=>O.id));await v.pruneStale?.(M),await v.hydrateSessions?.(M)}function H(){W().catch(()=>{}).then(()=>{n.mode==="main"&&(n={mode:"main",shell:T(n.shell)},B())})}function K(M,L){return N&&(clearTimeout(N),N=null),L?(N=setTimeout(()=>{N=null,!(n.mode!=="main"||n.shell.footerToast!==L)&&(n={mode:"main",shell:T({...n.shell,footerToast:null})},B())},3e3),{...M,footerToast:L}):{...M,footerToast:null}}function re(M,L){return K(M,L?{tone:"success",message:L}:null)}function C(M,L,O){let j=L instanceof Error?L.message:O,q=L instanceof Error?L.stack??L.message:String(L);return ps(r,{context:M,message:j,details:q}),j}function Q(M,L){return K(M,{tone:"error",message:L})}function Y(M){let L=i.then(M,M);return i=L.then(()=>{},()=>{}),L}function J(M){let L=$(M),O=c.inspection,j=O&&O.taskId===L?.id?O:null,q=xf(j?.fileRows??[],M.collapsedFileTreePaths);return{leftItemIds:Ef(c),centerTabIds:ho(L,M),ptyTabIds:L?.ptyTabs.map(Z=>Z.id)??[],filePathIds:j?.filePaths??[],fileTreeRowIds:q.map(Z=>Z.path),fileTreeFileIds:q.filter(Z=>Z.kind==="file").map(Z=>Z.path),fileTreeDirectoryIds:q.filter(Z=>Z.kind==="directory").map(Z=>Z.path),diffPathIds:j?.diffPaths??[],diffPathRanges:[],fileLineCount:j?.selectedFile.lines.length??0,diffLineCount:j?.selectedDiff.lines.length??0,reviewRowCount:Co(M,L),pageRows:Math.max(5,ht(w.width,w.height).height-Ne.topRailHeight-9),enabledRunnerIds:o,projectTargetIds:L?.repoTargets?.map(Z=>Z.repoId)??[]}}async function ye(M){await on(r,M),s=M,o=pt(s),c={...c,enabledRunnerIds:o},n.mode==="main"?n={mode:"main",shell:T({...n.shell,selectedRunner:o.includes(n.shell.selectedRunner)?n.shell.selectedRunner:st(s)})}:n={...n,shell:T({...n.shell,selectedRunner:o.includes(n.shell.selectedRunner)?n.shell.selectedRunner:st(s)})}}async function ve(M){let L=M.selectedTaskId;L&&await Y(async()=>{let O=await fe(r,L);!O.ptyTabs.some(j=>j.id===M.activeTab)||O.selectedPtyTabId===M.activeTab||await se(r,{...O,selectedPtyTabId:M.activeTab})})}async function le(){let M=(n.mode==="main",n.shell);c=await qt(t,M,o),n.mode==="main"?n={mode:"main",shell:T(n.shell)}:n={...n,shell:T(n.shell)}}async function Re(M){let L=++z,O=ba(c.tasks,M),j=c.inspection,q;if(O&&j?.taskId===O.id){let Z={selectedFilePath:M.selectedFilePath,selectedDiffPath:M.selectedDiffPath},de=await Ei(O,j,Z);if(L!==z)return;q={...c,inspection:de}}else if(q=await qt(t,M,o),L!==z)return;c=q,n.mode==="main"&&(n={mode:"main",shell:T(n.shell)},l(n.shell),B())}async function De(M){let L=await Uf(M);n.mode==="main"&&(n={mode:"main",shell:T({...n.shell,workspaceBrowser:L,activeTab:n.shell.selectedPtyTabId??n.shell.activeTab,actionMessage:null})},B())}async function Je(M){try{let L=T(M),O=$(L),j=L.selectedPtyTabId;if(O&&L.focusedRegion==="tasks"){let de=O.ptyTabs.find(Le=>Le.kind==="agent")??null;de?j=de.id:(O=await Xs(O),await le(),j=O.selectedPtyTabId)}O&&!j&&(O=await Xs(O),await le(),j=O.selectedPtyTabId);let q=T({...L,activeTab:j??L.activeTab,selectedPtyTabId:j,focusedRegion:j?"center":L.focusedRegion});if(!q.selectedTaskId||!j){n={mode:"main",shell:q},B();return}n={mode:"main",shell:Wt({...q,inputMode:"terminal"},v.getViewState(j))},l(n.shell);let Z=await v.ensureSession(q.selectedTaskId,j,Dr(ht(w.width,w.height)));f=Ys(j),u=null,n={mode:"main",shell:Wt({...q,inputMode:"terminal"},Z)},l(n.shell)}catch(L){let O=C("attach PTY",L,"Failed to start PTY.");M.selectedTaskId&&M.selectedPtyTabId&&Ys(M.selectedPtyTabId)&&(await ya(M.selectedTaskId,O).catch(()=>{}),await le().catch(()=>{})),n={mode:"main",shell:Q(ao(T(M),O),O)},l(n.shell)}B()}async function ya(M,L){await Y(async()=>{let O=await fe(r,M);await se(r,{...O,status:O.status==="running"?"draft":O.status,runnerSession:{...O.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:L})})}async function va(M,L,O){let j=T(M);if(!j.selectedTaskId)throw new Error("Select a task before creating a tab.");let q=await Y(async()=>{let Z=await fe(r,j.selectedTaskId),de=L??Mf(Z,j.activeTab,j.preferredPtyTabKind),Le=ma(Z,de,O??void 0,s),Tt={...Z,ptyTabs:[...Z.ptyTabs,Le],selectedPtyTabId:Le.id};return await se(r,Tt),Tt});return await le(),T({...j,activeTab:q.selectedPtyTabId??j.activeTab,selectedPtyTabId:q.selectedPtyTabId,preferredPtyTabKind:q.ptyTabs.at(-1)?.kind??j.preferredPtyTabKind,focusedRegion:"center",actionMessage:`Created tab: ${q.ptyTabs.at(-1)?.title??"tab"}`})}async function Sa(M){let L=T(M);if(!L.selectedTaskId)throw new Error("Select a task before closing a tab.");let{closedTab:O,nextSelectedTab:j}=await Y(async()=>{let q=await fe(r,L.selectedTaskId),Z=q.ptyTabs.findIndex($r=>$r.id===L.activeTab);if(Z===-1)throw new Error("Only PTY tabs can be closed.");let de=q.ptyTabs[Z],Le=q.ptyTabs.filter($r=>$r.id!==de.id),Tt=Le[Math.min(Z,Le.length-1)]??Le[Z-1]??null;return await se(r,{...q,ptyTabs:Le,selectedPtyTabId:Tt?.id??null}),{closedTab:de,nextSelectedTab:Tt}});return v.disposeSession(O.id),await le(),T({...L,activeTab:j?.id??(L.openInspectionKind?"inspection":L.activeTab),selectedPtyTabId:j?.id??null,focusedRegion:"center",actionMessage:`Closed tab: ${O.title}`})}async function Ta(M){let L=T(M);if(!L.selectedTaskId)throw new Error("Select a task before refreshing PR checks.");let O=$(L),j=null,q=null;if(O?.type==="project"&&O.repoTargets?.length){let Z=await cr(r,L.selectedTaskId);await le();let de=Z.synced+Z.discovered+Z.notFound;q=`Refreshed ${Z.synced}/${de} targets`}else{let{disposition:Z,task:de}=await ns(r,L.selectedTaskId);await le(),j=Z==="not_found"?`No PR found for ${de.branch}`:null,Z!=="not_found"&&(q=`Refreshed checks: ${ge(de)?.requiredChecks.length??0} reported`)}return T({...re(L,q),focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"refresh-checks",actionMessage:j})}async function Ra(){if(D||n.mode!=="main")return;let M=c.tasks;D=!0;try{if(await li(r,M),A=null,n.mode!=="main")return;c=await qt(t,n.shell,o),n={mode:"main",shell:T(n.shell)},B()}catch(L){let O=L instanceof Error?L.message:"Background PR discovery failed.";O!==A&&(A=O,ps(r,{context:"background PR polling",message:O,details:L instanceof Error?L.stack??L.message:String(L)}))}finally{D=!1}}async function Pa(M){let L=T(M);if(!L.selectedTaskId)throw new Error("Select a task before closing it.");let{taskBeforeClose:O,task:j}=await Y(async()=>{let q=await fe(r,L.selectedTaskId),Z=await Wi(r,L.selectedTaskId);return{taskBeforeClose:q,task:Z}});for(let q of O.ptyTabs)v.disposeSession(q.id);return await le(),T({...L,selectedActionId:"close-task",actionMessage:j.cleanup.preservedWorktree?`Archived task ${j.id}; worktree preserved`:`Archived task ${j.id}`})}async function Ca(M){let L=T(M);if(!L.selectedWorkspaceId)throw new Error("Select a workspace before removing it.");if((await Ke(r,{workspaceId:L.selectedWorkspaceId,includeClosed:!0})).tasks.length>0)throw new Error(`Cannot remove workspace ${L.selectedWorkspaceId} while task records still reference it.`);await Mt(r,L.selectedWorkspaceId);let j=await Ot(r,L.selectedWorkspaceId);return await le(),T({...L,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null,selectedPtyTabId:null,selectedLeftItemId:null,actionMessage:`Removed workspace ${j.workspaceId}`})}async function Xs(M){let L=M.ptyTabs.find(q=>q.kind==="agent")??null;if(L){let q={...M,selectedPtyTabId:L.id};return await Y(async()=>{let Z=await fe(r,M.id),de=Z.ptyTabs.find(Le=>Le.kind==="agent")??null;de&&await se(r,{...Z,selectedPtyTabId:de.id})}),q}let O=ma(M,"agent",void 0,s),j={...M,ptyTabs:[...M.ptyTabs,O],selectedPtyTabId:O.id};return await Y(async()=>{let q=await fe(r,M.id),Z=q.ptyTabs.find(de=>de.kind==="agent")??null;if(Z){await se(r,{...q,selectedPtyTabId:Z.id});return}await se(r,{...q,ptyTabs:[...q.ptyTabs,O],selectedPtyTabId:O.id})}),j}B=()=>{Ia();let M=ht(w.width,w.height),L=n.mode==="main"?na(M,ko(T(n.shell),c),{centerOnly:n.shell.centerZoomed}):n.variant==="boot"?ea(M,{menuIndex:n.menuIndex,optionsMessage:n.optionsMessage,versionText:E,updateText:U}):n.variant==="pause"?ta(M,{menuIndex:n.menuIndex,optionsMessage:n.optionsMessage,versionText:E,updateText:U}):n.variant==="options"?Hs(M,{menuIndex:n.menuIndex,optionsMenuItems:Vs}):n.variant==="runners"?Hs(M,{menuIndex:Kt(n).menuIndex,optionsMenuItems:zs(s,Kt(n)),optionsMessage:fa(Kt(n)),optionsSubtitle:"Runners"}):n.variant==="error-log"?sa(M,{errorLogPath:n.errorLog?.path??r.errorLogFile,errorLogLines:n.errorLog?.lines??[]}):ra(M);V&&(w.moveTo(1,1),w.eraseDisplayBelow(),V=!1),w.noFormat(Bf(L)),w.hideCursor(!0)};function Ia(){let M=n.mode==="main"&&n.shell.inputMode==="terminal"?"terminal":"control";M!==G&&(G=M,w.grabInput(M==="terminal"?{mouse:"button"}:!0))}let xa=()=>{process.stdout.off("resize",tn),process.off("SIGCONT",rn),w.removeListener("key",Qs),w.removeListener("unknown",Js),w.removeListener("mouse",Zs),S&&(clearTimeout(S),S=null),I&&(clearTimeout(I),I=null),x&&(clearTimeout(x),x=null),N&&(clearTimeout(N),N=null),F&&(clearInterval(F),F=null),v.disposeAll(),w.grabInput(!1),w.hideCursor(!1),w.fullscreen(!1)},Or=M=>{xa(),m(M)},Ea=async()=>{if(n.mode!=="main"||g)return;let M=n.shell,L=M.taskPromptInput?.trim()??"";if(!M.selectedRepoId&&!M.selectedWorkspaceId){n={mode:"main",shell:T({...M,taskPromptError:"Select a workspace first."})},B();return}if(L.length===0){n={mode:"main",shell:T({...M,taskPromptError:"Task prompt cannot be empty."})},B();return}g=!0,n={mode:"main",shell:T({...M,actionMessage:`Creating ${M.selectedRunner} task in ${M.selectedWorkspaceId??M.selectedRepoId}...`})},B();let O=null;try{O=await Of(r,M.selectedRepoId,M.selectedWorkspaceId,L,M.selectedRunner),await le();let j=T({...n.shell,selectedRepoId:O.repoId,selectedWorkspaceId:O.workspaceId,selectedTaskId:O.id,selectedPtyTabId:O.selectedPtyTabId,selectedLeftItemId:`task:${O.id}`,activeTab:O.selectedPtyTabId??"agent",inputMode:"terminal",focusedRegion:"center",taskPromptInput:null,taskPromptError:null,actionMessage:null}),q=await v.ensureSession(O.id,j.selectedPtyTabId??ka(O,"agent"),Dr(ht(w.width,w.height)));f=Ys(j.selectedPtyTabId),n={mode:"main",shell:Wt(j,q)},l(n.shell)}catch(j){j instanceof Lr&&(O=j.task);let q=C("create task",j,"Failed to create task.");O&&(await se(r,{...O,status:"draft",runnerSession:{...O.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:q}).catch(()=>{}),await le().catch(()=>{})),n={mode:"main",shell:Q(T({...n.shell,inputMode:"control",selectedTaskId:O?.id??n.shell.selectedTaskId,selectedPtyTabId:O?.selectedPtyTabId??n.shell.selectedPtyTabId,selectedLeftItemId:O?`task:${O.id}`:n.shell.selectedLeftItemId,activeTab:O?.selectedPtyTabId??n.shell.activeTab,taskPromptInput:O?null:"",taskPromptError:q,actionMessage:null}),q)}}finally{g=!1,B()}},Aa=M=>{if(n.mode!=="main")return;let L=n.shell;if(L.taskPromptInput!==null){if(M==="ESCAPE"){n={mode:"main",shell:T({...L,taskPromptInput:null,taskPromptError:null,actionMessage:null})},B();return}if(Qe(M)){Ea();return}if(M==="BACKSPACE"){n={mode:"main",shell:T({...L,taskPromptInput:L.taskPromptInput.slice(0,-1),taskPromptError:null})},B();return}if(M==="CTRL_R"){n={mode:"main",shell:T({...L,selectedRunner:Rs(L.selectedRunner,o),taskPromptError:null})},B();return}co(M)&&(n={mode:"main",shell:T({...L,taskPromptInput:`${L.taskPromptInput}${M}`,taskPromptError:null})},B())}},Da=M=>{if(n.mode!=="main")return;let L=n.shell.workspaceBrowser;if(L){if(M==="ESCAPE"){n={mode:"main",shell:T({...n.shell,workspaceBrowser:null,actionMessage:null})},B();return}if(M==="UP"||M==="k"){n={mode:"main",shell:T({...n.shell,workspaceBrowser:{...L,selectedIndex:Math.max(0,L.selectedIndex-1),error:null}})},B();return}if(M==="DOWN"||M==="j"){let O=Math.max(0,L.entries.length-1);n={mode:"main",shell:T({...n.shell,workspaceBrowser:{...L,selectedIndex:Math.min(O,L.selectedIndex+1),error:null}})},B();return}if(M==="LEFT"||M==="h"){De(St.dirname(L.cwd)).catch(O=>{let j=C("open parent workspace directory",O,"Failed to open parent directory.");n={mode:"main",shell:Q(T({...n.shell,workspaceBrowser:{...L,error:j}}),j)},B()});return}if(M==="RIGHT"||M==="l"||Qe(M)){let O=L.entries[L.selectedIndex]??null;if(!O)return;if((M==="RIGHT"||M==="l")&&(O.kind==="directory"||O.kind==="repo")){De(O.path).catch(j=>{let q=C("open workspace directory",j,"Failed to open directory.");n={mode:"main",shell:Q(T({...n.shell,workspaceBrowser:{...L,error:q}}),q)},B()});return}Lt(r,O.path).then(async j=>{await le();let q=j.repos[0]??null;n={mode:"main",shell:T({...n.shell,workspaceBrowser:null,selectedLeftItemId:`workspace:${j.workspace.id}`,selectedWorkspaceId:j.workspace.id,selectedRepoId:q?.id??null,selectedTaskId:null,selectedPtyTabId:null,actionMessage:`Registered workspace: ${j.workspace.name??j.workspace.id}`})},l(n.shell),B()}).catch(j=>{let q=C("add workspace",j,"Failed to add workspace.");n={mode:"main",shell:Q(T({...n.shell,workspaceBrowser:{...L,error:q}}),q)},B()})}}},Qs=M=>{let L=typeof M=="string"?M:"";if(n.mode==="main"&&n.shell.taskPromptInput!==null){Aa(L);return}if(n.mode==="main"&&n.shell.workspaceBrowser!==null){Da(L);return}if(n.mode==="main"){let O=oo(n.shell,L,J(n.shell));if(O.exit){Or(0);return}if(O.detachTerminal){v.detach(),n={mode:"main",shell:T(O.state)},l(n.shell),B();return}if(n.shell.inputMode==="terminal"){if(O.changed){n={mode:"main",shell:T(O.state)},l(n.shell),B();return}if(f&&Qe(L)){f=!1;return}f&&(f=!1),u=Ff(L)?{key:L,at:Date.now()}:null;let j=Nf(L,n.shell.terminal.scrolledBack??!1);if(j!==0){Br(j);return}v.writeKey(L);return}if(L==="CTRL_C"){Or(0);return}if(L==="?"&&n.shell.inputMode==="control"){n={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:n.shell},V=!0,B();return}if(O.pause){n={mode:"overlay",variant:"pause",menuIndex:0,optionsMessage:null,shell:T(O.state)},V=!0,B();return}if(O.beginTaskPrompt){n={mode:"main",shell:T(O.state)},l(n.shell),B();return}if(O.openWorkspaceBrowser){De(t).catch(j=>{let q=C("browse workspaces",j,"Failed to browse workspaces.");n={mode:"main",shell:Q(T({...O.state,workspaceBrowser:{cwd:t,entries:[],selectedIndex:0,error:q}}),q)},B()});return}if(O.createPtyTab){va(O.state,O.createPtyTabKind,O.createPtyTabRunner).then(j=>{Je(j)}).catch(j=>{let q=C("create PTY tab",j,"Failed to create tab.");n={mode:"main",shell:Q(T({...O.state,actionMessage:q}),q)},B()});return}if(O.closePtyTab){Sa(O.state).then(j=>{n={mode:"main",shell:j},l(n.shell),B()}).catch(j=>{let q=C("close PTY tab",j,"Failed to close tab.");n={mode:"main",shell:Q(T({...O.state,actionMessage:q}),q)},B()});return}if(O.refreshPullRequestChecks){Ta(O.state).then(j=>{n={mode:"main",shell:j},l(n.shell),B()}).catch(j=>{let q=C("refresh PR checks",j,"Failed to refresh PR checks.");n={mode:"main",shell:Q(T({...O.state,actionMessage:q}),q)},B()});return}if(O.closeTask){Pa(O.state).then(j=>{n={mode:"main",shell:j},l(n.shell),B()}).catch(j=>{let q=C("close task",j,"Failed to close task.");n={mode:"main",shell:Q(T({...O.state,actionMessage:q}),q)},B()});return}if(O.removeWorkspace){Ca(O.state).then(j=>{n={mode:"main",shell:j},l(n.shell),B()}).catch(j=>{let q=C("remove workspace",j,"Failed to remove workspace.");n={mode:"main",shell:Q(T({...O.state,actionMessage:q}),q)},B()});return}if(O.attachTerminal){Je(O.state);return}if(O.refreshInspection){n={mode:"main",shell:T(O.state)},l(n.shell),B(),Re(n.shell).catch(j=>{let q=C("refresh inspection",j,"Failed to refresh inspection.");n={mode:"main",shell:Q(T({...n.shell,actionMessage:q}),q)},B()});return}O.changed&&(n={mode:"main",shell:T(O.state)},ve(n.shell).catch(()=>{}),l(n.shell),B());return}if(n.variant==="help"){n.viaOptions&&n.parentVariant?n={mode:"overlay",variant:"options",menuIndex:2,optionsMessage:null,shell:n.shell,parentVariant:n.parentVariant}:n.parentVariant?n={mode:"overlay",variant:n.parentVariant,menuIndex:1,optionsMessage:null,shell:n.shell}:n={mode:"main",shell:T(n.shell)},V=!0,B();return}if(n.variant==="options"){La(L);return}if(n.variant==="runners"){Oa(L);return}if(n.variant==="error-log"){if(L==="ESCAPE"||Qe(L)){let O=n.parentVariant;n={mode:"overlay",variant:"options",menuIndex:1,optionsMessage:null,shell:n.shell,...O!==void 0?{parentVariant:O}:{}},V=!0,B()}return}if(n.optionsMessage){(L==="ESCAPE"||Qe(L))&&(n={...n,optionsMessage:null},B());return}if(L==="UP"||L==="k"){n={...n,menuIndex:Math.max(0,n.menuIndex-1)},B();return}if(L==="DOWN"||L==="j"){n={...n,menuIndex:Math.min(2,n.menuIndex+1)},B();return}if(L==="ESCAPE"){n.variant==="pause"&&(n={mode:"main",shell:T(n.shell)},V=!0,B());return}if(Qe(L)){if(n.menuIndex===0){let O=n.variant==="boot";n={mode:"main",shell:T({...n.shell,inputMode:"control"})},V=!0,B(),O?Fa.then(()=>{n.mode==="main"&&(n={mode:"main",shell:T(n.shell)},B())}):H();return}if(n.menuIndex===1){let O=n.variant==="boot"||n.variant==="pause"?n.variant:void 0;n={mode:"overlay",variant:"options",menuIndex:0,optionsMessage:null,shell:n.shell,...O!==void 0?{parentVariant:O}:{}},V=!0,B();return}Or(0)}};function La(M){if(n.mode!=="overlay"||n.variant!=="options")return;let L=pa(n.menuIndex,M);if(L.kind!=="noop"){if(L.kind==="render"){n={...n,menuIndex:L.menuIndex},B();return}if(L.kind==="back"){n.parentVariant&&(n={mode:"overlay",variant:n.parentVariant,menuIndex:1,optionsMessage:null,shell:n.shell},V=!0,B());return}if(L.kind==="help"){let O=n.parentVariant;n={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:n.shell,viaOptions:!0,...O!==void 0?{parentVariant:O}:{}},V=!0,B();return}if(L.kind==="runners"){let O=n.parentVariant;n={mode:"overlay",variant:"runners",menuIndex:0,optionsMessage:null,shell:n.shell,...O!==void 0?{parentVariant:O}:{}},V=!0,B();return}if(L.kind==="error-log"){let O=n.parentVariant;Ma(O)}}}async function Ma(M){let L;try{L=await Ii(r)}catch(O){let j=C("open error log",O,"Failed to read Craig error log.");L={path:r.errorLogFile,lines:[`Unable to read error log: ${j}`],empty:!1}}n.mode==="overlay"&&(n={mode:"overlay",variant:"error-log",menuIndex:0,optionsMessage:null,shell:n.shell,errorLog:L,...M!==void 0?{parentVariant:M}:{}},V=!0,B())}function Oa(M){if(n.mode!=="overlay"||n.variant!=="runners")return;let L=ga(Kt(n),s,M,o);if(L.kind!=="noop"){if(L.kind==="back"){let O=n.parentVariant;n={mode:"overlay",variant:"options",menuIndex:0,optionsMessage:null,shell:n.shell,...O!==void 0?{parentVariant:O}:{}},V=!0,B();return}if(L.kind==="render"){n={...n,runnerOptions:L.state},B();return}ye(L.config).then(()=>{n.mode!=="overlay"||n.variant!=="runners"||(n={...n,runnerOptions:L.state},B())}).catch(O=>{if(n.mode!=="overlay"||n.variant!=="runners")return;let j=C("save runner option",O,"Failed to save runner option."),q=Q(T(n.shell),j);n={...n,shell:q,runnerOptions:{...Kt(n),message:j}},B()})}}let Js=M=>{let L=$f(M);if(n.mode!=="main"||n.shell.inputMode!=="terminal"||L.length===0)return;if(L.includes("")){v.detach(),f=!1,u=null,n={mode:"main",shell:T({...n.shell,inputMode:"control",actionMessage:null,focusedRegion:"center"})},l(n.shell),B();return}let O=Wf(L);if(O!==0){Br(O);return}let j=jf(L);if(j){f=!1,u={key:j,at:Date.now()},v.writeKey(j);return}if(f&&L!=="\r"&&L!==`
185
185
  `&&L!==`\r
186
186
  `&&(f=!1),Hf(f,u,L)){f=!1;return}v.write(L)},Zs=M=>{if(n.mode!=="main")return;if(n.shell.inputMode==="control"){$a(_a(M));return}let L=_a(M);L!==0&&Br(L)};function Br(M){h+=M,!S&&(S=setTimeout(()=>{S=null;let L=h;h=0,L!==0&&(Ba(L),B())},16))}function Ba(M){v.scrollViewport(M),n={mode:"main",shell:P(n.shell)}}function en(){V=!0,w.fullscreen(!0)}function $a(M){M!==0&&(y+=M,!I&&(I=setTimeout(()=>{I=null;let L=y;if(y=0,L===0||n.mode!=="main"||n.shell.inputMode!=="control")return;let O=rt(n.shell,L,J(n.shell));if(O.changed){if(O.refreshInspection){n={mode:"main",shell:T(O.state)},l(n.shell),B(),Re(n.shell).catch(j=>{let q=C("refresh inspection",j,"Failed to refresh inspection.");n={mode:"main",shell:Q(T({...n.shell,actionMessage:q}),q)},B()});return}n={mode:"main",shell:T(O.state)},l(n.shell),B()}},16)))}let tn=()=>{en(),n.mode==="main"&&n.shell.inputMode==="terminal"&&(v.resize(Dr(ht(w.width,w.height))),n={mode:"main",shell:P(n.shell)}),B()},rn=()=>{en(),n.mode==="main"&&n.shell.inputMode==="terminal"&&(v.resize(Dr(ht(w.width,w.height))),n={mode:"main",shell:P(n.shell)}),B()};process.stdout.on("resize",tn),process.on("SIGCONT",rn),w.grabInput(!0),G="control",w.hideCursor(!0),w.fullscreen(!0),w.on("key",Qs),w.on("unknown",Js),w.on("mouse",Zs),F=setInterval(()=>{Ra()},(s.github?.watchIntervalSeconds??5)*1e3),ua().then(M=>{M.updateAvailable&&M.latest&&(U=`Update available: v${M.latest}`,B())});let Fa=W().catch(()=>{});B()})}async function qt(e,t,r){let s=Ge(e),[o,p,k]=await Promise.all([lt(s),$e(s),Ke(s)]),i=ba(k.tasks,t),c=t?{selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath}:{},d=i?await Ai(i,c):null;return{workspaceRoot:e,workspaces:p.filter(_=>_.status==="active"),repos:o,tasks:k.tasks,inspection:d,...r?{enabledRunnerIds:r}:{}}}function ba(e,t){return t?.selectedTaskId?e.find(r=>r.id===t.selectedTaskId)??null:null}function If(e,t){return mr(e,t)}function xf(e,t){let r=new Set(t);return e.filter(s=>{let o=s.path.split("/");for(let p=1;p<o.length;p+=1)if(r.has(o.slice(0,p).join("/")))return!1;return!0})}function Ef(e){let t=[];if(e.workspaces?.length)for(let r of e.workspaces){t.push(`workspace:${r.id}`);for(let s of e.tasks.filter(o=>o.workspaceId===r.id))t.push(`task:${s.id}`);r.kind==="project"&&t.push(`new-task-workspace:${r.id}`),r.kind==="repo"&&t.push(`new-task:${r.primaryRepoId}`)}else for(let r of e.repos){t.push(`repo:${r.id}`);for(let s of e.tasks.filter(o=>o.repoId===r.id))t.push(`task:${s.id}`);t.push(`new-task:${r.id}`)}return t.push("new-workspace"),t}function Af(e,t,r){let s=e.tasks.find(i=>i.ptyTabs.some(c=>c.id===t))??null,o=s?.ptyTabs.find(i=>i.id===t)??null,p=s?.worktreePath??r,k=o?.kind==="agent"?Lf(o):[];return s?.type==="project"?{cwd:p,command:k,env:{GIT_CEILING_DIRECTORIES:Df(process.env.GIT_CEILING_DIRECTORIES,p)}}:{cwd:p,command:k}}function Df(e,t){let r=(e??"").split(St.delimiter).filter(s=>s.length>0);return r.includes(t)?r.join(St.delimiter):[...r,t].join(St.delimiter)}function Lf(e){return e.command.length>0?e.command:["codex"]}function Kt(e){return e.runnerOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}function Mf(e,t,r){return e.ptyTabs.find(s=>s.id===t)?.kind??r}function ma(e,t,r,s={}){let o=r??e.runner,p=Se(o),k=t==="agent"?p.defaultAgentTitle:"Terminal",i=t==="agent"&&r&&r!==e.runner?`${e.id}:${r}`:`${e.id}:${t}`,c=new Set(e.ptyTabs.map(l=>l.id)),d=1,_=i;for(;c.has(_);)d+=1,_=`${i}-${d}`;let a=new Date().toISOString(),b=r&&r!==e.runner?r:void 0;return{id:_,kind:t,...b?{runner:b}:{},title:d===1?k:`${k} ${d}`,command:t==="agent"?_e(o,void 0,s):[],createdAt:a,updatedAt:a}}async function Of(e,t,r,s,o){let p=await He(e);Vt(o,p);let k=r?await rr(e,r,s,{runner:o,config:p}):await xt(e,t??"",s,{runner:o,config:p});try{let d=at();await ee(ct(Nr(o,p).executable,{cwd:k.repoRoot,env:d}),["--help"],{cwd:k.repoRoot,env:d})}catch(d){let _=d instanceof Error?d.message:"Failed to start runner.",a={...k.task,status:"draft",runnerSession:{...k.task.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:_};throw await se(e,a),new Lr(_,a)}let i=ka(k.task,"agent"),c={...k.task,status:"running",selectedPtyTabId:i,runnerSession:{...k.task.runnerSession,startedAt:new Date().toISOString(),lastKnownState:"running"}};return await se(e,c),await xe({uiStateFile:e.uiStateFile},{...await Oe({uiStateFile:e.uiStateFile})??qe(),version:1,selectedRepoId:c.repoId,selectedWorkspaceId:c.workspaceId,selectedTaskId:c.id,selectedPtyTabId:c.selectedPtyTabId,inputMode:"control",focusedRegion:"center",activeTab:c.selectedPtyTabId??"agent",selectedActionId:"commit",updatedAt:new Date().toISOString()}),c}var Lr=class extends Error{task;constructor(t,r){super(t),this.name="InteractiveTaskStartupError",this.task=r}};function ka(e,t){let r=e.ptyTabs.find(s=>s.kind===t);if(!r)throw new Error(`Task ${e.id} is missing its ${t} PTY tab.`);return r.id}function Dr(e){return{columns:Math.max(20,e.width-Ne.leftWidth-Ne.rightWidth-Ne.dividerWidth-Cr*2),rows:Math.max(5,e.height-Ne.topRailHeight-5)}}function Bf(e){return e.split(`
package/package.json CHANGED
@@ -1,8 +1,28 @@
1
1
  {
2
2
  "name": "craig-cli",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "description": "Craig local control plane CLI",
5
- "license": "UNLICENSED",
5
+ "license": "MIT",
6
+ "keywords": [
7
+ "ai-coding",
8
+ "agent-orchestration",
9
+ "cli",
10
+ "coding-agents",
11
+ "developer-tools",
12
+ "git-worktree",
13
+ "local-first",
14
+ "terminal-ui",
15
+ "tui",
16
+ "worktree"
17
+ ],
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/hallsamuel90/craig.git"
21
+ },
22
+ "bugs": {
23
+ "url": "https://github.com/hallsamuel90/craig/issues"
24
+ },
25
+ "homepage": "https://github.com/hallsamuel90/craig#readme",
6
26
  "type": "module",
7
27
  "bin": {
8
28
  "craig": "dist/cli.js"