@ciandt-flow/cli 1.0.1 → 1.0.2
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/dist/index.js +30 -30
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,84 +1,84 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {Box,Text,render,useInput}from'ink';import
|
|
3
|
-
`));}function
|
|
2
|
+
import {Box,Text,render,useInput}from'ink';import Ir,{useMemo,useEffect,useState,useCallback,useRef}from'react';import {jsxs,jsx,Fragment}from'react/jsx-runtime';import {create}from'zustand';import rr,{HTTPError}from'ky';import Yn from'conf';import T,{readFileSync,existsSync,chmodSync,realpathSync}from'fs';import fr from'ink-big-text';import gr from'ink-gradient';import*as v from'path';import v__default,{join}from'path';import h from'chalk';import Mr from'ink-spinner';import*as it from'os';import it__default,{homedir}from'os';import*as R from'fs/promises';import Hr from'extract-zip';import Jr from'proper-lockfile';import {randomUUID}from'crypto';import {Command}from'commander';var Wn=16;function gt({label:e,value:t,onChange:n,masked:r=false,isActive:o,error:i}){let s=useRef(t);useEffect(()=>{s.current=t;},[t]),useInput((d,c)=>{if(c.backspace||c.delete){let f=s.current.slice(0,-1);s.current=f,n(f);}else if(d&&!c.ctrl&&!c.meta&&!c.escape&&!c.return&&!c.tab&&!c.upArrow&&!c.downArrow&&!c.leftArrow&&!c.rightArrow){let f=s.current+d;s.current=f,n(f);}},{isActive:o});let a=r?"\u2022".repeat(t.length):t;return jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{children:[jsx(Text,{color:o?"cyan":"gray",children:o?"\u25B8 ":" "}),jsx(Text,{color:o?"white":"gray",bold:o,children:e.padEnd(Wn)}),jsx(Text,{color:o?"cyan":"gray",children:a}),o&&jsx(Text,{color:"cyan",children:"\u2588"})]}),i&&jsx(Box,{paddingLeft:3,children:jsxs(Text,{color:"red",children:["\u26A0 ",i]})})]})}var L=create(e=>({credentials:null,isAuthenticated:false,justAuthenticated:false,setCredentials:t=>e({credentials:t,isAuthenticated:true}),clearCredentials:()=>e({credentials:null,isAuthenticated:false,justAuthenticated:false}),setJustAuthenticated:t=>e({justAuthenticated:t})}));var m=create(e=>({activeTab:"discover",focus:"list",selectedIndex:0,actionMenuOpen:false,notification:null,loading:false,loadingMessage:"",catalogError:null,setActiveTab:t=>e({activeTab:t}),setFocus:t=>e({focus:t}),setSelectedIndex:t=>e({selectedIndex:t}),setActionMenuOpen:t=>e({actionMenuOpen:t}),showNotification:(t,n)=>e({notification:{message:t,type:n}}),clearNotification:()=>e({notification:null}),setLoading:(t,n="")=>e({loading:t,loadingMessage:t?n:""}),setCatalogError:t=>e({catalogError:t})}));var ge="FLOW",J="flow-skills";var F=new Yn({projectName:ge});function ht(){try{chmodSync(F.path,384);}catch{}}function S(){let e=F.get("credentials");if(!e)return null;try{return JSON.parse(e)}catch{return null}}function yt(e){F.set("credentials",JSON.stringify(e)),ht();}function wt(){F.delete("credentials"),F.delete("tokenCache");}function xt(){return F.path}function bt(e){F.set("tokenCache",{accessToken:e.accessToken,expiresAt:e.expiresAt}),ht();}function Ke(){let e=F.get("tokenCache");return e?{accessToken:e.accessToken,expiresAt:e.expiresAt}:null}function B(){let e=Ke();return e?new Date(e.expiresAt)>new Date:false}var er=[/^localhost\.?$/i,/^127\./,/^10\./,/^172\.(1[6-9]|2\d|3[01])\./,/^192\.168\./,/^169\.254\./,/^::1$/,/^\[::1\]$/,/^\[::ffff:/i,/^0\.0\.0\.0$/,/^\[f[cd]/i,/^\[fe80:/i,/^metadata\.google\.internal\.?$/i,/^metadata\.azure\.internal\.?$/i];function tr(e){return er.some(t=>t.test(e))}function nr(e,t){let n=process.env[e]??t;if(!n)throw new Error(`Missing required environment variable: ${e}`);return n}function he(e,t){let n=nr(e,t),r;try{r=new URL(n);}catch{throw new Error(`${e} must be a valid URL. Got: "${n}"`)}if(r.protocol!=="https:")throw new Error(`${e} must be an HTTPS URL. Got protocol: "${r.protocol}"`);if(r.username||r.password)throw new Error(`${e} must not contain embedded credentials (user:pass@host is not allowed)`);if(tr(r.hostname))throw new Error(`${e} must not point to a private/loopback address. Got: "${r.hostname}"`);return n}var ir=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function sr(e){if(!ir.test(e))throw new Error(`Invalid tenant value: "${e}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}var It={INVALID_CLIENT_SECRET:"Invalid Client Secret \u2014 check the value and try again",INVALID_CLIENT_ID:"Invalid Client ID \u2014 check the value and try again",INVALID_TENANT:"Invalid Tenant \u2014 check the value and try again",TENANT_NOT_FOUND:"Tenant not found \u2014 verify the tenant identifier"};async function ar(e){if(e instanceof HTTPError){let t=e.response.status,n="";try{let r=await e.response.text(),o=JSON.parse(r);typeof o.error=="string"&&(n=o.error);}catch{}return n&&It[n]?new Error(It[n]):t===401||t===403||t===500?new Error("Invalid credentials"):t>=400&&t<500?new Error("Authentication request was rejected"):new Error("Authentication service unavailable, please try again later")}return e instanceof Error?e:new Error("Authentication failed")}async function ne(e){let t=he("AUTH_ENGINE_URL","https://dev.flow.ciandt.com/auth-engine-api/v2/api-key/token");sr(e.tenant);let n;try{n=await rr.post(t,{headers:{FlowTenant:e.tenant},json:{clientSecret:e.clientSecret}}).json();}catch(o){throw await ar(o)}let r=n.expires_at??new Date(Date.now()+(n.expires_in??3600)*1e3).toISOString();yt(e),bt({accessToken:n.access_token,expiresAt:r});}async function vt(){if(B()){let e=Ke();if(!e)throw new Error("Flow CLI not configured. Run: npx @flow/cli auth login");return e.accessToken}throw new Error("Flow CLI not configured or token expired. Run: npx @flow/cli auth login")}var E=["clientId","clientSecret","tenant"],cr={clientId:"Client ID",clientSecret:"Client Secret",tenant:"Tenant"};function Tt(){let[e,t]=useState({clientId:"",clientSecret:"",tenant:""}),[n,r]=useState("clientId"),[o,i]=useState({}),[s,a]=useState(null),[d,c]=useState(false),{setCredentials:f,setJustAuthenticated:N}=L(),{setFocus:O}=m();useInput((l,p)=>{if(!d){if(p.shift&&p.tab){let g=E.indexOf(n);g>0&&r(E[g-1]);}else if(p.tab){let g=E.indexOf(n);g<E.length-1&&r(E[g+1]);}else if(p.return)if(n==="tenant")x();else {let g=E.indexOf(n);r(E[g+1]);}}},{isActive:true});let x=async()=>{let l={};for(let p of E)e[p].trim()||(l[p]="This field is required");if(Object.keys(l).length>0){i(l);let p=E.find(g=>l[g]);p&&r(p);return}c(true),a(null);try{await ne({clientId:e.clientId.trim(),clientSecret:e.clientSecret.trim(),tenant:e.tenant.trim()});let{clientSecret:p,...g}=e;f(g),N(!0),O("list");}catch(p){a(p instanceof Error?p.message:"Authentication failed");}finally{c(false),t(p=>({...p,clientSecret:""}));}},$=l=>p=>{t(g=>({...g,[l]:p})),o[l]&&i(g=>({...g,[l]:void 0}));};return jsxs(Box,{flexDirection:"column",padding:2,children:[jsx(Box,{marginBottom:1,children:jsxs(Text,{bold:true,color:"cyan",children:[ge," \u2014 Initial Setup"]})}),jsx(Box,{flexDirection:"column",children:E.map(l=>jsx(Box,{marginBottom:1,children:jsx(gt,{label:cr[l],value:e[l],onChange:$(l),masked:l==="clientSecret",isActive:n===l&&!d,error:o[l]})},l))}),d&&jsx(Box,{marginTop:1,children:jsx(Text,{color:"cyan",children:"Authenticating..."})}),s&&jsx(Box,{marginTop:1,children:jsxs(Text,{color:"red",children:["\u26A0 ",s]})}),jsx(Box,{marginTop:1,children:jsx(Text,{dimColor:true,children:"Tab next field \xB7 Enter confirm"})})]})}var mr=JSON.parse(readFileSync(join(import.meta.dirname,"..","package.json"),"utf8")),we=mr.version;function Et(){return jsxs(Box,{flexDirection:"column",alignItems:"center",children:[jsx(gr,{name:"morning",children:jsx(fr,{text:"FLOW",font:"block"})}),jsx(Box,{marginTop:-1,marginBottom:1,children:jsxs(Text,{dimColor:true,children:["Marketplace \xB7 v",we]})})]})}var ze={discover:"Discover",installed:"Installed"},hr=Object.keys(ze);function Ct(){let e=m(t=>t.activeTab);return jsxs(Box,{paddingX:1,paddingBottom:1,children:[hr.map(t=>jsx(Box,{marginRight:2,children:t===e?jsx(Text,{bold:true,underline:true,color:"cyan",children:ze[t]}):jsx(Text,{dimColor:true,children:ze[t]})},t)),jsx(Text,{dimColor:true,children:"(Tab to cycle)"})]})}var A=create(e=>({query:"",setQuery:t=>e({query:t}),resetQuery:()=>e({query:""})}));function kt(){let e=m(r=>r.focus),t=A(r=>r.query),n=e==="search";return jsxs(Box,{borderStyle:"single",borderTop:false,borderBottom:true,borderLeft:false,borderRight:false,paddingX:1,marginX:1,marginBottom:1,children:[jsx(Text,{color:n?"cyan":"gray",children:"\u03C1 "}),n?jsxs(Fragment,{children:[jsx(Text,{color:"white",children:t}),jsx(Text,{color:"cyan",children:"\u2588"})]}):jsx(Text,{dimColor:true,children:t||"Search..."})]})}function w(e){return e.replace(/\x1b\[[0-9;:<=>?]*[ -/]*[@-~]/g,"").replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g,"").replace(/\x1b./g,"").replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g,"")}function z(e){process.stdout.write(h.green(` \u2713 ${w(e)}
|
|
3
|
+
`));}function I(e){process.stderr.write(h.red(` \u2717 ${w(e)}
|
|
4
4
|
`));}function C(e){process.stdout.write(h.cyan(` \u2139 ${w(e)}
|
|
5
|
-
`));}function
|
|
5
|
+
`));}function ve(e,t){let n=t.map(a=>a.map(w)),r=[e,...n],o=e.map((a,d)=>Math.max(...r.map(c=>(c[d]??"").length))),i=o.map(a=>"\u2500".repeat(a)).join(" "),s=a=>a.map((d,c)=>d.padEnd(o[c])).join(" ");process.stdout.write(`
|
|
6
6
|
`),process.stdout.write(` ${h.bold(s(e))}
|
|
7
7
|
`),process.stdout.write(` ${h.dim(i)}
|
|
8
8
|
`);for(let a of n)process.stdout.write(` ${s(a)}
|
|
9
9
|
`);process.stdout.write(`
|
|
10
10
|
`);}function Te(e){process.stdout.write(JSON.stringify(e,null,2)+`
|
|
11
|
-
`);}function Pe(e){let t=new Date(e);return isNaN(t.getTime())?"\u2014":new Intl.DateTimeFormat("en-US",{dateStyle:"short"}).format(t)}var kt=xo.memo(function({item:t,isSelected:n}){let o=t.status==="disabled"?"yellow":"green";return jsxs(Box,{flexDirection:"column",paddingBottom:1,children:[jsxs(Box,{children:[jsx(Text,{color:n?"cyan":"gray",children:n?"\u203A ":"\u25CB "}),jsx(Text,{bold:n,color:n?"cyan":"white",children:t.name}),jsxs(Text,{dimColor:true,children:[t.authorName?` \xB7 ${t.authorName}`:""," \xB7 v",t.version]}),t.status&&jsxs(Text,{color:o,children:[" [",t.status,"]"]}),t.updateAvailable&&jsx(Text,{color:"yellow",children:" [update available]"}),t.installedBadge&&jsx(Text,{color:"cyan",children:" [installed]"}),t.installedAt&&jsxs(Text,{dimColor:true,children:[" \xB7 ",Pe(t.installedAt)]})]}),jsx(Box,{paddingLeft:2,children:jsx(Text,{dimColor:true,children:t.description})})]})});function Lt({message:e}){return jsx(Box,{paddingX:2,paddingY:1,children:jsx(Text,{dimColor:true,children:e??"No items found."})})}var We=5;function Dt({items:e,emptyMessage:t}){let n=m(l=>l.selectedIndex);if(e.length===0)return jsx(Lt,{message:t});let o=Math.max(0,n-Math.floor(We/2)),r=Math.min(e.length,o+We);r===e.length&&(o=Math.max(0,r-We));let i=e.slice(o,r),s=o,a=e.length-r;return jsxs(Box,{flexDirection:"column",children:[s>0&&jsx(Box,{paddingX:2,children:jsxs(Text,{dimColor:true,children:["\u2191 ",s," more above"]})}),i.map((l,d)=>jsx(kt,{item:l,isSelected:o+d===n},l.name)),a>0&&jsx(Box,{paddingX:2,children:jsxs(Text,{dimColor:true,children:["\u2193 ",a," more below"]})})]})}var Io={discover:"Discover plugins",installed:"Installed plugins"};function Ft({items:e,tabId:t,emptyMessage:n}){return jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{paddingX:1,paddingBottom:1,children:[jsx(Text,{bold:true,children:Io[t]}),jsxs(Text,{dimColor:true,children:[" (",e.length,")"]})]}),jsx(Rt,{}),jsx(Dt,{items:e,emptyMessage:n})]})}function Bt({filteredItems:e,emptyMessage:t}){let n=m(o=>o.activeTab);return jsx(Box,{flexDirection:"column",flexGrow:1,children:n==="discover"?jsx(Ft,{items:e,tabId:"discover",emptyMessage:t},"discover"):jsx(Ft,{items:e,tabId:"installed",emptyMessage:t},"installed")})}var So={tabs:"Tab: switch tab | \u2191\u2193: navigate | Enter: select | /: search | q: quit",list:"Tab: switch tab | \u2191\u2193: navigate | Enter: select | /: search | q: quit",search:"Type to filter | Esc: cancel search | Enter: confirm",actionMenu:"\u2191\u2193: navigate options | Enter: confirm | Esc: close menu",auth:"Tab: next field | Enter: confirm | Ctrl+C: quit"};function Ut(){let e=m(t=>t.focus);return jsx(Box,{borderStyle:"single",borderTop:true,borderBottom:false,borderLeft:false,borderRight:false,children:jsx(Text,{dimColor:true,children:So[e]})})}function jt({message:e,type:t}){return e?jsx(Box,{paddingX:1,children:jsxs(Text,{color:t==="success"?"green":t==="info"?"cyan":"red",children:[t==="success"?"\u2713":t==="info"?"(i)":"\u2717"," ",e]})}):null}function Ht({message:e}){return jsxs(Box,{children:[jsx(Text,{color:"cyan",children:jsx($o,{type:"dots"})}),jsxs(Text,{children:[" ",e]})]})}function Vt({message:e,onRetry:t,onBack:n}){return useInput((o,r)=>{o==="r"&&t?t():r.escape&&n&&n();}),jsxs(Box,{flexDirection:"column",paddingX:2,paddingY:1,children:[jsxs(Text,{color:"red",children:["\u2717 ",e]}),t&&jsx(Text,{dimColor:true,children:"Press r to retry"}),n&&jsx(Text,{dimColor:true,children:"Press Escape to go back"})]})}function Ae({itemName:e,actions:t,onAction:n,onClose:o}){let r=m(a=>a.focus),[i,s]=useState(0);return useInput((a,l)=>{l.upArrow?s(d=>d>0?d-1:d):l.downArrow?s(d=>d<t.length-1?d+1:d):l.return?n(t[i]):l.escape&&o();},{isActive:r==="actionMenu"}),jsxs(Box,{flexDirection:"column",borderStyle:"round",paddingX:1,children:[jsx(Text,{bold:true,children:e}),jsx(Box,{flexDirection:"column",marginTop:1,children:t.map((a,l)=>jsx(Box,{children:jsxs(Text,{bold:l===i,color:l===i?"cyan":void 0,children:[l===i?"\u203A ":" ",a]})},l))})]})}function Xt({itemName:e,onInstall:t,onClose:n}){return jsx(Ae,{itemName:e,actions:["Install","Cancel"],onAction:i=>{i==="Install"?t():n();},onClose:n})}function Zt({itemName:e,itemStatus:t,updateAvailable:n,onUninstall:o,onToggleStatus:r,onUpdate:i,onClose:s}){let[a,l]=useState(false),d=m(x=>x.focus);if(useInput((x,$)=>{$.escape||x==="n"?l(false):x==="y"&&o();},{isActive:a&&d==="actionMenu"}),a)return jsxs(Box,{flexDirection:"column",borderStyle:"round",paddingX:1,children:[jsx(Text,{bold:true,children:e}),jsxs(Box,{marginTop:1,children:[jsx(Text,{children:"Uninstall "}),jsx(Text,{bold:true,color:"red",children:e}),jsx(Text,{children:"? (y/N)"})]})]});let g=t==="enabled"?"Disable":"Enable";return jsx(Ae,{itemName:e,actions:n?["Uninstall",g,"Update","Cancel"]:["Uninstall",g,"Cancel"],onAction:x=>{x==="Uninstall"?l(true):x===g?r():x==="Update"?i?.():s();},onClose:s})}var Uo=".claude",jo=".flow";function en(e){return I.join(it.homedir(),Uo,"plugins","cache",J,e)}function tn(){return I.join(it.homedir(),jo,"cache","install.lock")}async function nn(e,t){let n=I.resolve(t);await R.mkdir(n,{recursive:true});let o=I.join(I.dirname(n),`${randomUUID()}.zip`);try{await R.writeFile(o,e),await _o(o,{dir:n,onEntry(r){if((r.externalFileAttributes>>16&61440)===40960)throw new Error(`Zip Slip (symlink): entry "${r.fileName}" is a symbolic link and was rejected`);let s=I.resolve(n,r.fileName);if(!s.startsWith(n+I.sep)&&s!==n)throw new Error(`Zip Slip detected: entry "${r.fileName}" would escape target directory`)}});try{let r=realpathSync(n);if(!r.startsWith(I.resolve(I.dirname(n))))throw new Error(`Zip Slip (post-extract): resolved path "${r}" is outside expected parent`)}catch(r){if(r.code!=="ENOENT")throw r}}finally{try{await R.unlink(o);}catch{}}}async function rt(e){await R.rm(e,{recursive:true,force:true});}async function ae(){let e=tn();await R.mkdir(I.dirname(e),{recursive:true});try{await R.writeFile(e,"",{flag:"wx"});}catch(n){if(n.code!=="EEXIST")throw n}return await qo.lock(e,{stale:1e4,retries:{retries:2,minTimeout:500,maxTimeout:500}})}function on(){return I__default.join(it__default.homedir(),".claude","plugins","installed_plugins.json")}function Jo(){return I__default.join(it__default.homedir(),".claude","plugins")}function zo(e){let t=I__default.resolve(e),n=I__default.resolve(Jo());if(!t.startsWith(n+I__default.sep)&&t!==n)throw new Error(`Security error: installPath '${e}' is outside the plugins directory`)}function rn(){return I__default.join(it__default.homedir(),".claude","settings.json")}function W(){let e=on();if(!T.existsSync(e))return {version:2,plugins:{}};try{return JSON.parse(T.readFileSync(e,"utf-8"))}catch{return {version:2,plugins:{}}}}function st(e){let t=on();T.mkdirSync(I__default.dirname(t),{recursive:true});let n=`${t}.tmp`;T.writeFileSync(n,JSON.stringify(e,null,2),"utf-8"),T.renameSync(n,t);}function le(e){let t=e.lastIndexOf("@");return t===-1?{name:e,marketplace:""}:{name:e.slice(0,t),marketplace:e.slice(t+1)}}function Vo(e){let t=I__default.join(e,".claude-plugin","plugin.json");if(!T.existsSync(t))return null;try{return JSON.parse(T.readFileSync(t,"utf-8"))}catch{return null}}function at(){let e=rn();if(!T.existsSync(e))return {};try{return JSON.parse(T.readFileSync(e,"utf-8"))}catch{return {}}}function sn(e){let t=rn(),n=`${t}.tmp`;T.writeFileSync(n,JSON.stringify(e,null,2),"utf-8"),T.renameSync(n,t);}function Go(){return at().enabledPlugins??{}}function Wo(e){let t=at(),n=t.enabledPlugins;if(!n||!(e in n))return;let{[e]:o,...r}=n;t.enabledPlugins=r,sn(t);}function lt(e,t){let n=at(),o=n.enabledPlugins??{};n.enabledPlugins={...o,[e]:t},sn(n);}function k(){let e=W(),t=Go();return Object.entries(e.plugins).map(([n,o])=>{let r=o[0],{name:i,marketplace:s}=le(n),a=Vo(r.installPath),l=t[n];return {name:i,marketplace:s,version:r.version,installedAt:r.installedAt,installPath:r.installPath,scope:r.scope,description:a?.description,author:a?.author,status:l===false?"disabled":"enabled"}})}async function Ce(e){let t=await ae();try{let{name:n,marketplace:o}=le(e),r=W(),i;if(o?(i=`${n}@${o}`,r.plugins[i]||(i=void 0)):i=Object.keys(r.plugins).filter(g=>le(g).name===n)[0],!i)throw new Error(`Plugin '${n}' is not installed`);let s=r.plugins[i][0].installPath;zo(s),T.rmSync(s,{recursive:!0,force:!0});let{[i]:a,...l}=r.plugins;st({...r,plugins:l}),Wo(i);}finally{await t();}}async function ce(e,t){let n=await ae();try{let{name:o}=le(e),r=W(),i=Object.keys(r.plugins).filter(s=>le(s).name===o);if(i.length===0)throw new Error(`Plugin '${o}' is not installed`);lt(i[0],t==="enabled");}finally{await n();}}var K=create(e=>({installedItems:[],setInstalledItems:t=>e({installedItems:t}),loadFromDisk:()=>e({installedItems:k()})}));var S=["discover","installed"];function an(e,t,n){if(t.rightArrow||t.tab){let o=S.indexOf(n.activeTab);return [{type:"setTab",tab:S[(o+1)%S.length]},{type:"setSelectedIndex",index:0},{type:"setFocus",focus:"list"}]}if(t.leftArrow){let o=S.indexOf(n.activeTab);return [{type:"setTab",tab:S[(o-1+S.length)%S.length]},{type:"setSelectedIndex",index:0},{type:"setFocus",focus:"list"}]}return t.downArrow?[{type:"setFocus",focus:"list"}]:[]}function ln(e,t,n,o){if(t.upArrow&&n.selectedIndex>0)return [{type:"setSelectedIndex",index:n.selectedIndex-1}];if(t.downArrow&&n.selectedIndex<o-1)return [{type:"setSelectedIndex",index:n.selectedIndex+1}];if(t.tab){let r=S.indexOf(n.activeTab);return [{type:"setTab",tab:S[(r+1)%S.length]},{type:"setSelectedIndex",index:0}]}return t.return?[{type:"setActionMenuOpen",open:true},{type:"setFocus",focus:"actionMenu"}]:e==="/"?[{type:"setFocus",focus:"search"}]:[]}function cn(e,t){return t.escape?[{type:"setActionMenuOpen",open:false},{type:"setFocus",focus:"list"}]:[]}function un(e,t){return t.escape?{actions:[{type:"setFocus",focus:"list"}],queryUpdate:"reset"}:t.return?{actions:[{type:"setFocus",focus:"list"}],queryUpdate:null}:t.backspace||t.delete?{actions:[],queryUpdate:{backspace:true}}:e&&!t.ctrl&&!t.meta?{actions:[],queryUpdate:{append:e}}:{actions:[],queryUpdate:null}}function Re(e){let{setActiveTab:t,setFocus:n,setSelectedIndex:o,setActionMenuOpen:r}=m.getState();for(let i of e)i.type==="setTab"?t(i.tab):i.type==="setFocus"?n(i.focus):i.type==="setSelectedIndex"?o(i.index):i.type==="setActionMenuOpen"&&r(i.open);}function mn({listLength:e}){let t=m(c=>c.focus),n=m(c=>c.selectedIndex),o=m(c=>c.actionMenuOpen),r=m(c=>c.setFocus),i=m(c=>c.setActionMenuOpen),s=E(c=>c.query),a=E(c=>c.setQuery),l=E(c=>c.resetQuery),d=useRef(e);useEffect(()=>{d.current=e;},[e]);let[g,O]=useState("");useEffect(()=>{let c=setTimeout(()=>O(s),300);return ()=>clearTimeout(c)},[s]),useInput((c,p)=>{c==="q"&&process.exit(0);},{isActive:t!=="search"&&t!=="auth"}),useInput((c,p)=>{let{activeTab:f,selectedIndex:b,actionMenuOpen:Y}=m.getState();Re(an(c,p,{activeTab:f}));},{isActive:t==="tabs"}),useInput((c,p)=>{let{activeTab:f,selectedIndex:b,actionMenuOpen:Y}=m.getState();Re(ln(c,p,{activeTab:f,selectedIndex:b},d.current));},{isActive:t==="list"}),useInput((c,p)=>{Re(cn(c,p));},{isActive:t==="actionMenu"}),useInput((c,p)=>{let f=un(c,p),b=f.queryUpdate;Re(f.actions),b==="reset"?(l(),O("")):b!==null&&("backspace"in b?a(E.getState().query.slice(0,-1)):a(E.getState().query+b.append));},{isActive:t==="search"});let F=useCallback(()=>{i(false),r("list");},[i,r]),x=useCallback(c=>{let{setSelectedIndex:p,selectedIndex:f}=m.getState();c===0?p(0):f>=c&&p(c-1);},[]),$=useCallback(c=>{if(!g)return d.current=c.length,c;let p=g.toLowerCase(),f=c.filter(b=>b.name.toLowerCase().includes(p)||b.description?.toLowerCase().includes(p));return d.current=f.length,f},[g]);return {actionMenuOpen:o,closeMenu:F,selectedIndex:n,clampIndex:x,filteredItems:$}}var pn=800;var er=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function ke(){return eo.create({prefixUrl:he("PROMPT_MANAGER_URL","https://dev.flow.ciandt.com/prompt-manager-api/"),hooks:{beforeRequest:[async e=>{let t=await vt();e.headers.set("Authorization",`Bearer ${t}`);let n=P();n?.tenant&&er.test(n.tenant)&&e.headers.set("FlowTenant",n.tenant);}]}})}var tr=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function fn(e){if(!e||!tr.test(e))throw new Error(`Invalid plugin name: "${e}". Must be 1-64 chars, lowercase alphanumeric and hyphens only.`)}async function X(){try{let{plugins:e}=await ke().get("v1/plugins/catalog").json();return e}catch(e){throw e instanceof Error?e.message.includes("401")||e.message.includes("403")?new Error("Authentication failed. Run: flow auth login"):e.message.includes("timeout")?new Error("Request timed out while fetching plugin catalog"):new Error(`Failed to fetch plugin catalog: ${e.message}`):e}}async function gn(e){fn(e);try{return await ke().get(`v1/plugins/${e}/manifest`).json()}catch(t){throw t instanceof Error?t.message.includes("404")?new Error(`Plugin '${e}' not found in catalog`):t.message.includes("timeout")?new Error("Download timed out after 30s"):new Error(`Failed to fetch plugin manifest: ${t.message}`):t}}async function hn(e){fn(e);try{let t=await ke().get(`v1/plugins/${e}/archive`);return Buffer.from(await t.arrayBuffer())}catch(t){throw t instanceof Error?t.message.includes("timeout")?new Error("Download timed out after 30s"):new Error(`Failed to download plugin: ${t.message}`):t}}async function yn(e){await new Promise(t=>setTimeout(t,pn)),console.warn("Update not implemented yet");}function wn(){let[e,t]=useState([]),[n,o]=useState(true),[r,i]=useState(null),s=useCallback(async()=>{o(true),i(null);try{let a=await X();t(a);}catch(a){i(a instanceof Error?a:new Error(String(a))),t([]);}finally{o(false);}},[]);return useEffect(()=>{s();},[s]),{catalog:e,isLoading:n,error:r,refetch:s}}function xn(){return {items:K(t=>t.installedItems)}}var Q=class extends Error{constructor(n,o){super(`${n} v${o} is already installed. Use --force to reinstall.`);this.pluginName=n;this.version=o;this.name="AlreadyInstalledError";}};var rr=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function ir(e){if(!rr.test(e))throw new Error(`Invalid plugin name from manifest: "${e}". Plugin names must be lowercase alphanumeric and hyphens (1-64 chars).`)}function sr(e,t){return n=>{t&&console.log(`[${e}] ${n}`);}}function ar(e,t){let n=`${e}@${J}`,r=W().plugins[n];if(r&&!t)throw new Q(e,r[0].version);return {pluginKey:n,alreadyInstalled:r}}async function lr(e,t,n,o){n&&await rt(t);try{o(`Extracting to ${t}...`),await nn(e,t);}catch(r){throw await rt(t),r}}function cr(e,t,n){let o=W(),r={scope:"user",installPath:t,version:n,installedAt:new Date().toISOString()};o.plugins[e]=[r],st(o),lt(e,true);}async function $e(e,t={}){let n=Date.now(),o=sr(e,t.verbose),r=null;try{o("Acquiring lock..."),r=await ae();let{pluginKey:i,alreadyInstalled:s}=ar(e,t.force);o("Fetching manifest...");let a=await gn(e);ir(a.name),o("Downloading archive...");let l=await hn(e),d=en(a.name);await lr(l,d,!!s&&!!t.force,o),cr(i,d,a.version);let g=Date.now()-n;return o(`Installed successfully in ${g}ms`),{name:a.name,version:a.version,path:d,duration_ms:g}}finally{r&&await r();}}function bn(){let e=K(s=>s.installedItems),t=K(s=>s.setInstalledItems),n=useCallback(async s=>{await $e(s.name),K.getState().loadFromDisk();},[]),o=useCallback(async s=>{await Ce(s),t(e.filter(a=>a.name!==s));},[e,t]),r=useCallback(async s=>{let l=e.find(d=>d.name===s)?.status==="enabled"?"disabled":"enabled";await ce(s,l),t(e.map(d=>d.name===s?{...d,status:l}:d));},[e,t]),i=useCallback(async s=>{await yn(),t(e.map(a=>a.name===s?{...a,updateAvailable:false}:a));},[e,t]);return {install:n,uninstall:o,toggle:r,update:i}}function mr(e){return {name:e.name,version:e.version,description:e.description,authorName:e.author.name,updateAvailable:e.updateAvailable}}function pr(e){return {name:e.name,version:e.version,description:e.description,authorName:e.author?.name,status:e.status,updateAvailable:e.updateAvailable,installedAt:e.installedAt}}function vn(){let e=m(u=>u.activeTab),t=m(u=>u.notification),n=m(u=>u.showNotification),o=m(u=>u.clearNotification),r=m(u=>u.loading),i=m(u=>u.loadingMessage),s=m(u=>u.catalogError),a=m(u=>u.setLoading),l=m(u=>u.setCatalogError),d=E(u=>u.query),{catalog:g,isLoading:O,error:F,refetch:x}=wn(),{items:$}=xn(),c=K(u=>u.loadFromDisk),p=useMemo(()=>new Set($.map(u=>`${u.name}|${u.author?.name??""}|${u.marketplace}`)),[$]),{install:f,uninstall:b,toggle:Y,update:On}=bn(),mt=L(u=>u.justAuthenticated),Fe=L(u=>u.credentials),Fn=L(u=>u.setJustAuthenticated),Be=e==="discover"?g.filter(u=>!p.has(`${u.name}|${u.author.name}|${J}`)).map(u=>mr(u)):$.map(u=>pr(u)),{actionMenuOpen:pt,closeMenu:Ne,selectedIndex:Bn,clampIndex:Ue,filteredItems:Nn}=mn({listLength:Be.length}),me=Nn(Be),y=me[Bn]??null;useEffect(()=>{c();},[]),useEffect(()=>{Ue(me.length);},[me.length,Ue]),useEffect(()=>{mt&&Fe&&(n(`Authenticated. Tenant: ${Fe.tenant}`,"success"),Fn(false));},[mt,Fe]),useEffect(()=>{if(!t)return;let u=setTimeout(o,3e3);return ()=>clearTimeout(u)},[t]),useEffect(()=>{F&&(console.error("[usePluginCatalog]",F),l("Failed to load catalog"));},[F]);let ft=(u,Z)=>{n(u,Z);},pe=async(u,Z,Hn)=>{a(true,u),Ne();try{await Z();let fe=Be.length;Ue(fe),ft(Hn,"success");}catch(fe){ft(fe instanceof Error?fe.message:"Something went wrong","error");}finally{a(false);}},Un=()=>{if(!y)return;let u=g.find(Z=>Z.name===y.name);u&&pe(`Installing ${y.name}...`,()=>f(u),"\u2713 Installed successfully");},jn=()=>{y&&pe(`Uninstalling ${y.name}...`,()=>b(y.name),"\u2713 Uninstalled");},Kn=()=>{if(!y)return;let u=y.status==="enabled";pe(u?`Disabling ${y.name}...`:`Enabling ${y.name}...`,()=>Y(y.name),u?"\u2713 Disabled":"\u2713 Enabled");},_n=e==="installed"?"No plugins installed \u2014 explore the Discover tab!":d?`No plugins found for '${d}'`:"No plugins available in the catalog",qn=()=>{y&&pe(`Updating ${y.name}...`,()=>On(y.name),"\u2713 Updated");};return jsxs(Box,{flexDirection:"column",borderStyle:"round",paddingX:1,children:[jsx(St,{}),jsx(Et,{}),jsx(Bt,{filteredItems:me,emptyMessage:_n}),(r||O)&&jsx(Ht,{message:r?i:"Loading catalog..."}),s&&!O&&e==="discover"&&jsx(Vt,{message:s,onRetry:()=>{l(null),x();},onBack:()=>l(null)}),t&&jsx(jt,{message:t.message,type:t.type}),pt&&y&&e==="discover"&&jsx(Xt,{itemName:y.name,onInstall:Un,onClose:Ne}),pt&&y&&e==="installed"&&jsx(Zt,{itemName:y.name,itemStatus:y.status??"enabled",updateAvailable:y.updateAvailable??false,onUninstall:jn,onToggleStatus:Kn,onUpdate:qn,onClose:Ne}),jsx(Ut,{})]})}var In=P();if(In&&N()){let{clientSecret:e,...t}=In;L.getState().setCredentials(t),m.getState().setFocus("list");}else m.getState().setFocus("auth");function Pn(){return L(t=>t.isAuthenticated)?jsx(vn,{}):jsx(It,{})}function Me(e,t={}){return new Promise((n,o)=>{let{masked:r=false,defaultValue:i=""}=t;process.stdout.write(e+i);let s=i,a=g=>{if(g===""){l(),o(new Error("SIGINT"));return}if(g==="\r"||g===`
|
|
12
|
-
`){
|
|
13
|
-
`),n(s);return}if(
|
|
11
|
+
`);}function Se(e){let t=new Date(e);return isNaN(t.getTime())?"\u2014":new Intl.DateTimeFormat("en-US",{dateStyle:"short"}).format(t)}var $t=Ir.memo(function({item:t,isSelected:n}){let r=t.status==="disabled"?"yellow":"green";return jsxs(Box,{flexDirection:"column",paddingBottom:1,children:[jsxs(Box,{children:[jsx(Text,{color:n?"cyan":"gray",children:n?"\u203A ":"\u25CB "}),jsx(Text,{bold:n,color:n?"cyan":"white",children:t.name}),jsxs(Text,{dimColor:true,children:[t.authorName?` \xB7 ${t.authorName}`:""," \xB7 v",t.version]}),t.status&&jsxs(Text,{color:r,children:[" [",t.status,"]"]}),t.updateAvailable&&jsx(Text,{color:"yellow",children:" [update available]"}),t.installedBadge&&jsx(Text,{color:"cyan",children:" [installed]"}),t.installedAt&&jsxs(Text,{dimColor:true,children:[" \xB7 ",Se(t.installedAt)]})]}),jsx(Box,{paddingLeft:2,children:jsx(Text,{dimColor:true,children:t.description})})]})});function Mt({message:e}){return jsx(Box,{paddingX:2,paddingY:1,children:jsx(Text,{dimColor:true,children:e??"No items found."})})}var We=5;function Nt({items:e,emptyMessage:t}){let n=m(d=>d.selectedIndex);if(e.length===0)return jsx(Mt,{message:t});let r=Math.max(0,n-Math.floor(We/2)),o=Math.min(e.length,r+We);o===e.length&&(r=Math.max(0,o-We));let i=e.slice(r,o),s=r,a=e.length-o;return jsxs(Box,{flexDirection:"column",children:[s>0&&jsx(Box,{paddingX:2,children:jsxs(Text,{dimColor:true,children:["\u2191 ",s," more above"]})}),i.map((d,c)=>jsx($t,{item:d,isSelected:r+c===n},d.name)),a>0&&jsx(Box,{paddingX:2,children:jsxs(Text,{dimColor:true,children:["\u2193 ",a," more below"]})})]})}var Sr={discover:"Discover plugins",installed:"Installed plugins"};function Ft({items:e,tabId:t,emptyMessage:n}){return jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{paddingX:1,paddingBottom:1,children:[jsx(Text,{bold:true,children:Sr[t]}),jsxs(Text,{dimColor:true,children:[" (",e.length,")"]})]}),jsx(kt,{}),jsx(Nt,{items:e,emptyMessage:n})]})}function Bt({filteredItems:e,emptyMessage:t}){let n=m(r=>r.activeTab);return jsx(Box,{flexDirection:"column",flexGrow:1,children:n==="discover"?jsx(Ft,{items:e,tabId:"discover",emptyMessage:t},"discover"):jsx(Ft,{items:e,tabId:"installed",emptyMessage:t},"installed")})}var Ar={tabs:"Tab: switch tab | \u2191\u2193: navigate | Enter: select | /: search | q: quit",list:"Tab: switch tab | \u2191\u2193: navigate | Enter: select | /: search | q: quit",search:"Type to filter | Esc: cancel search | Enter: confirm",actionMenu:"\u2191\u2193: navigate options | Enter: confirm | Esc: close menu",auth:"Tab: next field | Enter: confirm | Ctrl+C: quit"};function jt(){let e=m(t=>t.focus);return jsx(Box,{borderStyle:"single",borderTop:true,borderBottom:false,borderLeft:false,borderRight:false,children:jsx(Text,{dimColor:true,children:Ar[e]})})}function _t({message:e,type:t}){return e?jsx(Box,{paddingX:1,children:jsxs(Text,{color:t==="success"?"green":t==="info"?"cyan":"red",children:[t==="success"?"\u2713":t==="info"?"(i)":"\u2717"," ",e]})}):null}function Jt({message:e}){return jsxs(Box,{children:[jsx(Text,{color:"cyan",children:jsx(Mr,{type:"dots"})}),jsxs(Text,{children:[" ",e]})]})}function Gt({message:e,onRetry:t,onBack:n}){return useInput((r,o)=>{r==="r"&&t?t():o.escape&&n&&n();}),jsxs(Box,{flexDirection:"column",paddingX:2,paddingY:1,children:[jsxs(Text,{color:"red",children:["\u2717 ",e]}),t&&jsx(Text,{dimColor:true,children:"Press r to retry"}),n&&jsx(Text,{dimColor:true,children:"Press Escape to go back"})]})}function Ee({itemName:e,actions:t,onAction:n,onClose:r}){let o=m(a=>a.focus),[i,s]=useState(0);return useInput((a,d)=>{d.upArrow?s(c=>c>0?c-1:c):d.downArrow?s(c=>c<t.length-1?c+1:c):d.return?n(t[i]):d.escape&&r();},{isActive:o==="actionMenu"}),jsxs(Box,{flexDirection:"column",borderStyle:"round",paddingX:1,children:[jsx(Text,{bold:true,children:e}),jsx(Box,{flexDirection:"column",marginTop:1,children:t.map((a,d)=>jsx(Box,{children:jsxs(Text,{bold:d===i,color:d===i?"cyan":void 0,children:[d===i?"\u203A ":" ",a]})},d))})]})}function Qt({itemName:e,onInstall:t,onClose:n}){return jsx(Ee,{itemName:e,actions:["Install","Cancel"],onAction:i=>{i==="Install"?t():n();},onClose:n})}function en({itemName:e,itemStatus:t,updateAvailable:n,onUninstall:r,onToggleStatus:o,onUpdate:i,onClose:s}){let[a,d]=useState(false),c=m(x=>x.focus);if(useInput((x,$)=>{$.escape||x==="n"?d(false):x==="y"&&r();},{isActive:a&&c==="actionMenu"}),a)return jsxs(Box,{flexDirection:"column",borderStyle:"round",paddingX:1,children:[jsx(Text,{bold:true,children:e}),jsxs(Box,{marginTop:1,children:[jsx(Text,{children:"Uninstall "}),jsx(Text,{bold:true,color:"red",children:e}),jsx(Text,{children:"? (y/N)"})]})]});let f=t==="enabled"?"Disable":"Enable";return jsx(Ee,{itemName:e,actions:n?["Uninstall",f,"Update","Cancel"]:["Uninstall",f,"Cancel"],onAction:x=>{x==="Uninstall"?d(true):x===f?o():x==="Update"?i?.():s();},onClose:s})}var _r=".claude",Kr=".flow";function tn(e){return v.join(it.homedir(),_r,"plugins","cache",J,e)}function nn(){return v.join(it.homedir(),Kr,"cache","install.lock")}async function rn(e,t){let n=v.resolve(t);await R.mkdir(n,{recursive:true});let r=v.join(v.dirname(n),`${randomUUID()}.zip`);try{await R.writeFile(r,e),await Hr(r,{dir:n,onEntry(o){if((o.externalFileAttributes>>16&61440)===40960)throw new Error(`Zip Slip (symlink): entry "${o.fileName}" is a symbolic link and was rejected`);let s=v.resolve(n,o.fileName);if(!s.startsWith(n+v.sep)&&s!==n)throw new Error(`Zip Slip detected: entry "${o.fileName}" would escape target directory`)}});try{let o=realpathSync(n);if(!o.startsWith(v.resolve(v.dirname(n))))throw new Error(`Zip Slip (post-extract): resolved path "${o}" is outside expected parent`)}catch(o){if(o.code!=="ENOENT")throw o}}finally{try{await R.unlink(r);}catch{}}}async function ot(e){await R.rm(e,{recursive:true,force:true});}async function ae(){let e=nn();await R.mkdir(v.dirname(e),{recursive:true});try{await R.writeFile(e,"",{flag:"wx"});}catch(n){if(n.code!=="EEXIST")throw n}return await Jr.lock(e,{stale:1e4,retries:{retries:2,minTimeout:500,maxTimeout:500}})}function on(){return v__default.join(it__default.homedir(),".claude","plugins","installed_plugins.json")}function Vr(){return v__default.join(it__default.homedir(),".claude","plugins")}function Gr(e){let t=v__default.resolve(e),n=v__default.resolve(Vr());if(!t.startsWith(n+v__default.sep)&&t!==n)throw new Error(`Security error: installPath '${e}' is outside the plugins directory`)}function sn(){return v__default.join(it__default.homedir(),".claude","settings.json")}function W(){let e=on();if(!T.existsSync(e))return {version:2,plugins:{}};try{return JSON.parse(T.readFileSync(e,"utf-8"))}catch{return {version:2,plugins:{}}}}function st(e){let t=on();T.mkdirSync(v__default.dirname(t),{recursive:true});let n=`${t}.tmp`;T.writeFileSync(n,JSON.stringify(e,null,2),"utf-8"),T.renameSync(n,t);}function le(e){let t=e.lastIndexOf("@");return t===-1?{name:e,marketplace:""}:{name:e.slice(0,t),marketplace:e.slice(t+1)}}function Wr(e){let t=v__default.join(e,".claude-plugin","plugin.json");if(!T.existsSync(t))return null;try{return JSON.parse(T.readFileSync(t,"utf-8"))}catch{return null}}function at(){let e=sn();if(!T.existsSync(e))return {};try{return JSON.parse(T.readFileSync(e,"utf-8"))}catch{return {}}}function an(e){let t=sn(),n=`${t}.tmp`;T.writeFileSync(n,JSON.stringify(e,null,2),"utf-8"),T.renameSync(n,t);}function Xr(){return at().enabledPlugins??{}}function Qr(e){let t=at(),n=t.enabledPlugins;if(!n||!(e in n))return;let{[e]:r,...o}=n;t.enabledPlugins=o,an(t);}function lt(e,t){let n=at(),r=n.enabledPlugins??{};n.enabledPlugins={...r,[e]:t},an(n);}function k(){let e=W(),t=Xr();return Object.entries(e.plugins).map(([n,r])=>{let o=r[0],{name:i,marketplace:s}=le(n),a=Wr(o.installPath),d=t[n];return {name:i,marketplace:s,version:o.version,installedAt:o.installedAt,installPath:o.installPath,scope:o.scope,description:a?.description,author:a?.author,status:d===false?"disabled":"enabled"}})}async function Ce(e){let t=await ae();try{let{name:n,marketplace:r}=le(e),o=W(),i;if(r?(i=`${n}@${r}`,o.plugins[i]||(i=void 0)):i=Object.keys(o.plugins).filter(f=>le(f).name===n)[0],!i)throw new Error(`Plugin '${n}' is not installed`);let s=o.plugins[i][0].installPath;Gr(s),T.rmSync(s,{recursive:!0,force:!0});let{[i]:a,...d}=o.plugins;st({...o,plugins:d}),Qr(i);}finally{await t();}}async function ce(e,t){let n=await ae();try{let{name:r}=le(e),o=W(),i=Object.keys(o.plugins).filter(s=>le(s).name===r);if(i.length===0)throw new Error(`Plugin '${r}' is not installed`);lt(i[0],t==="enabled");}finally{await n();}}var _=create(e=>({installedItems:[],setInstalledItems:t=>e({installedItems:t}),loadFromDisk:()=>e({installedItems:k()})}));var P=["discover","installed"];function ln(e,t,n){if(t.rightArrow||t.tab){let r=P.indexOf(n.activeTab);return [{type:"setTab",tab:P[(r+1)%P.length]},{type:"setSelectedIndex",index:0},{type:"setFocus",focus:"list"}]}if(t.leftArrow){let r=P.indexOf(n.activeTab);return [{type:"setTab",tab:P[(r-1+P.length)%P.length]},{type:"setSelectedIndex",index:0},{type:"setFocus",focus:"list"}]}return t.downArrow?[{type:"setFocus",focus:"list"}]:[]}function cn(e,t,n,r){if(t.upArrow&&n.selectedIndex>0)return [{type:"setSelectedIndex",index:n.selectedIndex-1}];if(t.downArrow&&n.selectedIndex<r-1)return [{type:"setSelectedIndex",index:n.selectedIndex+1}];if(t.tab){let o=P.indexOf(n.activeTab);return [{type:"setTab",tab:P[(o+1)%P.length]},{type:"setSelectedIndex",index:0}]}return t.return?[{type:"setActionMenuOpen",open:true},{type:"setFocus",focus:"actionMenu"}]:e==="/"?[{type:"setFocus",focus:"search"}]:[]}function un(e,t){return t.escape?[{type:"setActionMenuOpen",open:false},{type:"setFocus",focus:"list"}]:[]}function dn(e,t){return t.escape?{actions:[{type:"setFocus",focus:"list"}],queryUpdate:"reset"}:t.return?{actions:[{type:"setFocus",focus:"list"}],queryUpdate:null}:t.backspace||t.delete?{actions:[],queryUpdate:{backspace:true}}:e&&!t.ctrl&&!t.meta?{actions:[],queryUpdate:{append:e}}:{actions:[],queryUpdate:null}}function Re(e){let{setActiveTab:t,setFocus:n,setSelectedIndex:r,setActionMenuOpen:o}=m.getState();for(let i of e)i.type==="setTab"?t(i.tab):i.type==="setFocus"?n(i.focus):i.type==="setSelectedIndex"?r(i.index):i.type==="setActionMenuOpen"&&o(i.open);}function pn({listLength:e}){let t=m(l=>l.focus),n=m(l=>l.selectedIndex),r=m(l=>l.actionMenuOpen),o=m(l=>l.setFocus),i=m(l=>l.setActionMenuOpen),s=A(l=>l.query),a=A(l=>l.setQuery),d=A(l=>l.resetQuery),c=useRef(e);useEffect(()=>{c.current=e;},[e]);let[f,N]=useState("");useEffect(()=>{let l=setTimeout(()=>N(s),300);return ()=>clearTimeout(l)},[s]),useInput((l,p)=>{l==="q"&&process.exit(0);},{isActive:t!=="search"&&t!=="auth"}),useInput((l,p)=>{let{activeTab:g,selectedIndex:b,actionMenuOpen:Y}=m.getState();Re(ln(l,p,{activeTab:g}));},{isActive:t==="tabs"}),useInput((l,p)=>{let{activeTab:g,selectedIndex:b,actionMenuOpen:Y}=m.getState();Re(cn(l,p,{activeTab:g,selectedIndex:b},c.current));},{isActive:t==="list"}),useInput((l,p)=>{Re(un(l,p));},{isActive:t==="actionMenu"}),useInput((l,p)=>{let g=dn(l,p),b=g.queryUpdate;Re(g.actions),b==="reset"?(d(),N("")):b!==null&&("backspace"in b?a(A.getState().query.slice(0,-1)):a(A.getState().query+b.append));},{isActive:t==="search"});let O=useCallback(()=>{i(false),o("list");},[i,o]),x=useCallback(l=>{let{setSelectedIndex:p,selectedIndex:g}=m.getState();l===0?p(0):g>=l&&p(l-1);},[]),$=useCallback(l=>{if(!f)return c.current=l.length,l;let p=f.toLowerCase(),g=l.filter(b=>b.name.toLowerCase().includes(p)||b.description?.toLowerCase().includes(p));return c.current=g.length,g},[f]);return {actionMenuOpen:r,closeMenu:O,selectedIndex:n,clampIndex:x,filteredItems:$}}var fn=800;var no=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function ke(){return rr.create({prefixUrl:he("PROMPT_MANAGER_URL","https://dev.flow.ciandt.com/prompt-manager-api/"),hooks:{beforeRequest:[async e=>{let t=await vt();e.headers.set("Authorization",`Bearer ${t}`);let n=S();n?.tenant&&no.test(n.tenant)&&e.headers.set("FlowTenant",n.tenant);}]}})}var ro=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function gn(e){if(!e||!ro.test(e))throw new Error(`Invalid plugin name: "${e}". Must be 1-64 chars, lowercase alphanumeric and hyphens only.`)}async function X(){try{let{plugins:e}=await ke().get("v1/plugins/catalog").json();return e}catch(e){throw e instanceof Error?e.message.includes("401")||e.message.includes("403")?new Error("Authentication failed. Run: flow auth login"):e.message.includes("timeout")?new Error("Request timed out while fetching plugin catalog"):new Error(`Failed to fetch plugin catalog: ${e.message}`):e}}async function hn(e){gn(e);try{return await ke().get(`v1/plugins/${e}/manifest`).json()}catch(t){throw t instanceof Error?t.message.includes("404")?new Error(`Plugin '${e}' not found in catalog`):t.message.includes("timeout")?new Error("Download timed out after 30s"):new Error(`Failed to fetch plugin manifest: ${t.message}`):t}}async function yn(e){gn(e);try{let t=await ke().get(`v1/plugins/${e}/archive`);return Buffer.from(await t.arrayBuffer())}catch(t){throw t instanceof Error?t.message.includes("timeout")?new Error("Download timed out after 30s"):new Error(`Failed to download plugin: ${t.message}`):t}}async function wn(e){await new Promise(t=>setTimeout(t,fn)),console.warn("Update not implemented yet");}function xn(){let[e,t]=useState([]),[n,r]=useState(true),[o,i]=useState(null),s=useCallback(async()=>{r(true),i(null);try{let a=await X();t(a);}catch(a){i(a instanceof Error?a:new Error(String(a))),t([]);}finally{r(false);}},[]);return useEffect(()=>{s();},[s]),{catalog:e,isLoading:n,error:o,refetch:s}}function bn(){return {items:_(t=>t.installedItems)}}var Q=class extends Error{constructor(n,r){super(`${n} v${r} is already installed. Use --force to reinstall.`);this.pluginName=n;this.version=r;this.name="AlreadyInstalledError";}};var so=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function ao(e){if(!so.test(e))throw new Error(`Invalid plugin name from manifest: "${e}". Plugin names must be lowercase alphanumeric and hyphens (1-64 chars).`)}function lo(e,t){return n=>{t&&console.log(`[${e}] ${n}`);}}function co(e,t){let n=`${e}@${J}`,o=W().plugins[n];if(o&&!t)throw new Q(e,o[0].version);return {pluginKey:n,alreadyInstalled:o}}async function uo(e,t,n,r){n&&await ot(t);try{r(`Extracting to ${t}...`),await rn(e,t);}catch(o){throw await ot(t),o}}function mo(e,t,n){let r=W(),o={scope:"user",installPath:t,version:n,installedAt:new Date().toISOString()};r.plugins[e]=[o],st(r),lt(e,true);}async function $e(e,t={}){let n=Date.now(),r=lo(e,t.verbose),o=null;try{r("Acquiring lock..."),o=await ae();let{pluginKey:i,alreadyInstalled:s}=co(e,t.force);r("Fetching manifest...");let a=await hn(e);ao(a.name),r("Downloading archive...");let d=await yn(e),c=tn(a.name);await uo(d,c,!!s&&!!t.force,r),mo(i,c,a.version);let f=Date.now()-n;return r(`Installed successfully in ${f}ms`),{name:a.name,version:a.version,path:c,duration_ms:f}}finally{o&&await o();}}function In(){let e=_(s=>s.installedItems),t=_(s=>s.setInstalledItems),n=useCallback(async s=>{await $e(s.name),_.getState().loadFromDisk();},[]),r=useCallback(async s=>{await Ce(s),t(e.filter(a=>a.name!==s));},[e,t]),o=useCallback(async s=>{let d=e.find(c=>c.name===s)?.status==="enabled"?"disabled":"enabled";await ce(s,d),t(e.map(c=>c.name===s?{...c,status:d}:c));},[e,t]),i=useCallback(async s=>{await wn(),t(e.map(a=>a.name===s?{...a,updateAvailable:false}:a));},[e,t]);return {install:n,uninstall:r,toggle:o,update:i}}function go(e){return {name:e.name,version:e.version,description:e.description,authorName:e.author.name,updateAvailable:e.updateAvailable}}function ho(e){return {name:e.name,version:e.version,description:e.description,authorName:e.author?.name,status:e.status,updateAvailable:e.updateAvailable,installedAt:e.installedAt}}function vn(){let e=m(u=>u.activeTab),t=m(u=>u.notification),n=m(u=>u.showNotification),r=m(u=>u.clearNotification),o=m(u=>u.loading),i=m(u=>u.loadingMessage),s=m(u=>u.catalogError),a=m(u=>u.setLoading),d=m(u=>u.setCatalogError),c=A(u=>u.query),{catalog:f,isLoading:N,error:O,refetch:x}=xn(),{items:$}=bn(),l=_(u=>u.loadFromDisk),p=useMemo(()=>new Set($.map(u=>`${u.name}|${u.author?.name??""}|${u.marketplace}`)),[$]),{install:g,uninstall:b,toggle:Y,update:On}=In(),mt=L(u=>u.justAuthenticated),Oe=L(u=>u.credentials),Fn=L(u=>u.setJustAuthenticated),Fe=e==="discover"?f.filter(u=>!p.has(`${u.name}|${u.author.name}|${J}`)).map(u=>go(u)):$.map(u=>ho(u)),{actionMenuOpen:pt,closeMenu:Be,selectedIndex:Bn,clampIndex:Ue,filteredItems:Un}=pn({listLength:Fe.length}),me=Un(Fe),y=me[Bn]??null;useEffect(()=>{l();},[]),useEffect(()=>{Ue(me.length);},[me.length,Ue]),useEffect(()=>{mt&&Oe&&(n(`Authenticated. Tenant: ${Oe.tenant}`,"success"),Fn(false));},[mt,Oe]),useEffect(()=>{if(!t)return;let u=setTimeout(r,3e3);return ()=>clearTimeout(u)},[t]),useEffect(()=>{O&&(console.error("[usePluginCatalog]",O),d("Failed to load catalog"));},[O]);let ft=(u,Z)=>{n(u,Z);},pe=async(u,Z,Jn)=>{a(true,u),Be();try{await Z();let fe=Fe.length;Ue(fe),ft(Jn,"success");}catch(fe){ft(fe instanceof Error?fe.message:"Something went wrong","error");}finally{a(false);}},jn=()=>{if(!y)return;let u=f.find(Z=>Z.name===y.name);u&&pe(`Installing ${y.name}...`,()=>g(u),"\u2713 Installed successfully");},_n=()=>{y&&pe(`Uninstalling ${y.name}...`,()=>b(y.name),"\u2713 Uninstalled");},Kn=()=>{if(!y)return;let u=y.status==="enabled";pe(u?`Disabling ${y.name}...`:`Enabling ${y.name}...`,()=>Y(y.name),u?"\u2713 Disabled":"\u2713 Enabled");},qn=e==="installed"?"No plugins installed \u2014 explore the Discover tab!":c?`No plugins found for '${c}'`:"No plugins available in the catalog",Hn=()=>{y&&pe(`Updating ${y.name}...`,()=>On(y.name),"\u2713 Updated");};return jsxs(Box,{flexDirection:"column",borderStyle:"round",paddingX:1,children:[jsx(Et,{}),jsx(Ct,{}),jsx(Bt,{filteredItems:me,emptyMessage:qn}),(o||N)&&jsx(Jt,{message:o?i:"Loading catalog..."}),s&&!N&&e==="discover"&&jsx(Gt,{message:s,onRetry:()=>{d(null),x();},onBack:()=>d(null)}),t&&jsx(_t,{message:t.message,type:t.type}),pt&&y&&e==="discover"&&jsx(Qt,{itemName:y.name,onInstall:jn,onClose:Be}),pt&&y&&e==="installed"&&jsx(en,{itemName:y.name,itemStatus:y.status??"enabled",updateAvailable:y.updateAvailable??false,onUninstall:_n,onToggleStatus:Kn,onUpdate:Hn,onClose:Be}),jsx(jt,{})]})}var Tn=S();if(Tn&&B()){let{clientSecret:e,...t}=Tn;L.getState().setCredentials(t),m.getState().setFocus("list");}else m.getState().setFocus("auth");function Pn(){return L(t=>t.isAuthenticated)?jsx(vn,{}):jsx(Tt,{})}function Me(e,t={}){return new Promise((n,r)=>{let{masked:o=false,defaultValue:i=""}=t;process.stdout.write(e+i);let s=i,a=f=>{if(f===""){d(),r(new Error("SIGINT"));return}if(f==="\r"||f===`
|
|
12
|
+
`){d(),process.stdout.write(`
|
|
13
|
+
`),n(s);return}if(f==="\x7F"){s.length>0&&(s=s.slice(0,-1),process.stdout.write("\b \b"));return}f.startsWith("\x1B")||(s+=f,process.stdout.write(o?"*".repeat(f.length):f));};function d(){process.stdin.setRawMode(false),process.stdin.removeListener("data",a),process.removeListener("uncaughtException",c),process.removeListener("unhandledRejection",c);}function c(){try{process.stdin.setRawMode(!1);}catch{}}process.on("uncaughtException",c),process.on("unhandledRejection",c),process.stdin.setRawMode(true),process.stdin.resume(),process.stdin.setEncoding("utf8"),process.stdin.on("data",a);})}async function wo(e){try{return await ne(e),process.stdout.write(h.green(` \u2713 Setup complete. Tenant: ${e.tenant}
|
|
14
14
|
|
|
15
15
|
`)),0}catch(t){let n=w(t instanceof Error?t.message:"unknown error");return process.stderr.write(h.red(` \u2717 Authentication failed: ${n}
|
|
16
|
-
`)),1}}async function
|
|
16
|
+
`)),1}}async function xo(){try{process.stdout.write(`
|
|
17
17
|
`);let e=(await Me(h.cyan(" ? ")+"Client ID: ")).trim(),t=(await Me(h.cyan(" ? ")+"Client Secret: ",{masked:!0})).trim(),n=(await Me(h.cyan(" ? ")+"Tenant: ")).trim();if(!e||!t||!n)return process.stderr.write(h.red(` \u2717 All fields are required
|
|
18
|
-
`)),1;try{await ne({clientId:e,clientSecret:t,tenant:n});}catch(
|
|
18
|
+
`)),1;try{await ne({clientId:e,clientSecret:t,tenant:n});}catch(r){let o=w(r instanceof Error?r.message:"unknown error");return process.stderr.write(h.red(` \u2717 Authentication failed: ${o}
|
|
19
19
|
`)),1}return process.stdout.write(h.green(` \u2713 Setup complete. Tenant: ${n}
|
|
20
20
|
|
|
21
21
|
`)),0}catch(e){if(e instanceof Error&&e.message==="SIGINT")throw e;let t=w(e instanceof Error?e.message:"unknown error");return process.stderr.write(h.red(` \u2717 Unexpected error: ${t}
|
|
22
|
-
`)),1}}async function dt(e={}){if(e.clientId&&e.clientSecret&&e.tenant)return
|
|
23
|
-
`),130;throw t}}async function
|
|
22
|
+
`)),1}}async function dt(e={}){if(e.clientId&&e.clientSecret&&e.tenant)return wo({clientId:e.clientId,clientSecret:e.clientSecret,tenant:e.tenant});try{return await xo()}catch(t){if(t instanceof Error&&t.message==="SIGINT")return process.stdout.write(`
|
|
23
|
+
`),130;throw t}}async function bo(){try{return process.stdout.write(`
|
|
24
24
|
`),(await Me(h.cyan(" ? ")+"Are you sure? This will remove your local credentials. (y/N): ")).toLowerCase()!=="y"?(process.stdout.write(h.yellow(` \u26A0 Logout cancelled
|
|
25
25
|
`)),0):null}catch(e){if(e instanceof Error&&e.message==="SIGINT")return process.stdout.write(`
|
|
26
|
-
`),130;throw e}}async function
|
|
27
|
-
`)),0;if(!e){let t=await
|
|
26
|
+
`),130;throw e}}async function En(e){if(!S())return process.stdout.write(h.yellow(` \u26A0 You are not authenticated
|
|
27
|
+
`)),0;if(!e){let t=await bo();if(t!==null)return t}try{return wt(),process.stdout.write(h.green(` \u2713 Credentials removed successfully
|
|
28
28
|
`)),0}catch{return process.stderr.write(h.red(` \u2717 Error removing credentials
|
|
29
|
-
`)),1}}async function An(){let e=
|
|
29
|
+
`)),1}}async function An(){let e=S();if(!e)return process.stdout.write(h.yellow(" \u26A0 Not authenticated. Run `npx @flow/cli` or `npx @flow/cli auth login` to set up.\n")),0;if(!B())return process.stdout.write(h.yellow(" \u26A0 Session expired. Run `npx @flow/cli auth login` to re-authenticate.\n")),0;let t=e.clientSecret.length>4?"****...****"+e.clientSecret.slice(-4):"****";return process.stdout.write(`
|
|
30
30
|
`+h.bold(` Authenticated
|
|
31
31
|
`)),process.stdout.write(h.dim(" Tenant: ")+w(e.tenant)+`
|
|
32
32
|
`),process.stdout.write(h.dim(" Client ID: ")+w(e.clientId)+`
|
|
33
33
|
`),process.stdout.write(h.dim(" Client Secret: ")+t+`
|
|
34
34
|
`),process.stdout.write(h.dim(" Config: ")+w(xt())+`
|
|
35
35
|
`),process.stdout.write(`
|
|
36
|
-
`),0}function
|
|
36
|
+
`),0}function K(){return S()?true:(I("Not authenticated. Run: flow-plugins auth"),false)}async function Io(e){let t=k(),n;try{n=await X();}catch{n=[];}let r=new Set(t.map(o=>o.name));return e.json?(Te(n.map(o=>({...o,installed:r.has(o.name)}))),0):(ve(["","Name","Version","Category","Status"],n.map(o=>[r.has(o.name)?"*":" ",o.name,o.version,o.category,r.has(o.name)?"installed":"available"])),0)}function vo(e){let n=k().filter(r=>r.updateAvailable);return n.length===0?(C("All plugins are up to date."),0):e.json?(Te(n),0):(ve(["Name","Installed","Available"],n.map(r=>[r.name,r.version,"\u2014"])),process.stdout.write(`
|
|
37
37
|
${n.length} plugin(s) outdated.
|
|
38
|
-
`),0)}function
|
|
38
|
+
`),0)}function To(e){let t=k();return t.length===0?(C("No plugins installed. Use `flow plugin install <name>` to install one."),0):e.json?(Te(t),0):(ve(["Name","Version","Installed at"],t.map(n=>[n.name,n.version,Se(n.installedAt)])),process.stdout.write(`
|
|
39
39
|
${t.length} plugin(s) installed.
|
|
40
|
-
`),0)}async function
|
|
41
|
-
Installation summary: ${t} succeeded, ${n} failed`);}async function
|
|
40
|
+
`),0)}async function Cn(e){if(!K())return 1;try{return e.available?await Io(e):e.outdated?vo(e):To(e)}catch(t){return I(t instanceof Error?t.message:"Failed to list plugins."),1}}function De(e){return e instanceof Error?e.message:String(e)}async function So(e,t,n){n.silent||C(`${t}Installing ${e}...`);try{let r=await $e(e,n);return n.silent||z(`${t}${r.name} v${r.version} installed successfully`),{name:e,success:!0}}catch(r){if(r instanceof Q)return n.silent||C(`${t}${r.message}`),{name:e,success:true};let o=De(r);return I(`${t}Failed to install ${e}: ${o}`),{name:e,success:false,error:o}}}function Po(e){let t=e.filter(r=>r.success).length,n=e.filter(r=>!r.success).length;C(`
|
|
41
|
+
Installation summary: ${t} succeeded, ${n} failed`);}async function Rn(e,t={}){if(!K())return 1;let n=[];for(let r=0;r<e.length;r++){let o=e.length>1?`[${r+1}/${e.length}] `:"",i=await So(e[r],o,t);n.push(i);}return e.length>1&&!t.silent&&Po(n),n.some(r=>!r.success)?1:0}async function kn(e,t){if(!K())return 1;if(!t.force){let n=k().find(s=>s.name===e);if(!n)return I(`Plugin "${e}" is not installed`),1;let r=w(n.name),o=w(n.version);if(!await Eo(`Remove ${r} v${o}? [y/N] `))return C("Operation cancelled."),0}try{return await Ce(e),z("Plugin removed successfully"),0}catch(n){return I(De(n)),1}}async function Eo(e){let n=(await import('readline')).default.createInterface({input:process.stdin,output:process.stdout});return new Promise(r=>{n.question(e,o=>{n.close(),r(o.toLowerCase()==="y");});})}async function $n(e){if(!K())return 1;let t=k().find(n=>n.name===e);if(!t)return I(`Plugin "${e}" is not installed`),1;if(t.status==="enabled")return C(`${t.name} is already enabled`),0;try{return await ce(e,"enabled"),z(`${t.name} enabled successfully`),0}catch(n){return I(De(n)),1}}async function Ln(e){if(!K())return 1;let t=k().find(n=>n.name===e);if(!t)return I(`Plugin "${e}" is not installed`),1;if(t.status==="disabled")return C(`${t.name} is already disabled`),0;try{return await ce(e,"disabled"),z(`${t.name} disabled successfully`),0}catch(n){return I(De(n)),1}}async function Mn(e){return K()?(z(`${e} updated successfully`),0):1}function ko(){return S()?{passed:true,message:"Credentials configured"}:{passed:false,message:"Credentials not configured \u2014 Run `auth login`"}}async function $o(){let e=Date.now();try{await X();let t=Date.now()-e;return {passed:!0,message:`Prompt Manager accessible (${t}ms)`,latency:t}}catch(t){return t instanceof Error&&t.name==="TimeoutError"?{passed:false,message:"Timeout after 5s \u2014 check your connection"}:{passed:false,message:`Connection error: ${t instanceof Error?t.message:"Unknown"}`}}}function Lo(){return B()?{passed:true,message:"Token is valid"}:{passed:false,message:"Token expired \u2014 run `auth login` to re-authenticate"}}function Mo(){let e=join(homedir(),".claude","settings.json");return existsSync(e)?{passed:true,message:"Claude Code detected"}:{passed:false,message:"Claude Code not detected"}}async function Dn(){process.stdout.write(`
|
|
42
42
|
`+h.bold(` FlowSetup CLI Diagnostics
|
|
43
43
|
|
|
44
|
-
`));let e=[{name:"Credentials",fn:
|
|
44
|
+
`));let e=[{name:"Credentials",fn:ko},{name:"Prompt Manager",fn:$o},{name:"Valid Token",fn:Lo},{name:"Claude Code",fn:Mo}],t=true;for(let n of e){let r=await n.fn(),o="",i=h.green;r.passed?o=h.green("[OK] "):(o=h.red("[FAIL]"),i=h.red,t=false);let s=` ${o} ${i(n.name.padEnd(18))} ${w(r.message)}`;process.stdout.write(s+`
|
|
45
45
|
`);}return process.stdout.write(`
|
|
46
46
|
`),t?(process.stdout.write(h.green(` \u2713 All checks passed!
|
|
47
47
|
|
|
48
48
|
`)),0):(process.stdout.write(h.red(` \u2717 Some checks failed \u2014 verify your configuration
|
|
49
49
|
|
|
50
|
-
`)),1)}function
|
|
50
|
+
`)),1)}function Nn(e){let t=new Command;t.name("flow").description("FlowSetup CLI \u2014 Manage Flow plugins in your Claude Code").version(`@flow/cli v${we}`,"-V, --version","Display the CLI version").addHelpText("after",`
|
|
51
51
|
Without arguments, opens the interactive interface (TUI).
|
|
52
52
|
Use 'flow <command> --help' for details on each command.`).action(()=>{e();});let n=new Command("setup").description("Configure the CLI by detecting Claude Code credentials");n.command("init").description("Initialize the Flow CLI configuration").addHelpText("after",`
|
|
53
53
|
Examples:
|
|
54
|
-
$ flow setup init`).action(async()=>{let i=await dt();process.exit(i);}),t.addCommand(n);let
|
|
54
|
+
$ flow setup init`).action(async()=>{let i=await dt();process.exit(i);}),t.addCommand(n);let r=new Command("plugin").description("Manage plugins from the Findr catalog installed in your Claude Code");r.command("list").description("List available or installed plugins").option("--available","show full catalog with installation status",false).option("--outdated","show only plugins with updates available",false).option("--json","output as JSON",false).addHelpText("after",`
|
|
55
55
|
Examples:
|
|
56
56
|
$ flow plugin list
|
|
57
57
|
$ flow plugin list --available
|
|
58
58
|
$ flow plugin list --outdated
|
|
59
|
-
$ flow plugin list --json`).action(async i=>{let s=await
|
|
59
|
+
$ flow plugin list --json`).action(async i=>{let s=await Cn(i);process.exit(s);}),r.command("install").description("Install one or more plugins from the Findr catalog into Claude Code").argument("<name...>","Name(s) of the plugin(s) to install (space-separated)").option("--force","Reinstall even if the version is already installed").option("--verbose","Display each step of the installation process").option("--silent","Output in JSON only").addHelpText("after",`
|
|
60
60
|
Examples:
|
|
61
61
|
$ flow plugin install flow-adr-writer
|
|
62
62
|
$ flow plugin install flow-adr-writer flow-prd-writer startup-pack-ai
|
|
63
63
|
$ flow plugin install flow-adr-writer --force
|
|
64
|
-
$ flow plugin install flow-adr-writer --silent`).action(async(i,s)=>{let a=await
|
|
64
|
+
$ flow plugin install flow-adr-writer --silent`).action(async(i,s)=>{let a=await Rn(i,s);process.exit(a);}),r.command("uninstall").description("Remove an installed plugin from Claude Code").argument("<name>","Name of the plugin to remove").option("--force","Skip interactive confirmation").addHelpText("after",`
|
|
65
65
|
Examples:
|
|
66
66
|
$ flow plugin uninstall flow-adr-writer
|
|
67
|
-
$ flow plugin uninstall startup-pack-ai --force`).action(async(i,s)=>{let a=await
|
|
67
|
+
$ flow plugin uninstall startup-pack-ai --force`).action(async(i,s)=>{let a=await kn(i,s);process.exit(a);}),r.command("update").description("Update plugins to the latest version").argument("[name]","Name of the plugin to update (omit to update all)").addHelpText("after",`
|
|
68
68
|
Examples:
|
|
69
69
|
$ flow plugin update
|
|
70
|
-
$ flow plugin update flow-adr-writer`).action(async i=>{if(i){let s=await
|
|
70
|
+
$ flow plugin update flow-adr-writer`).action(async i=>{if(i){let s=await Mn(i);process.exit(s);}else console.log("Update all plugins coming soon."),process.exit(0);}),r.command("enable").description("Enable an installed plugin").argument("<name>","Name of the plugin to enable").addHelpText("after",`
|
|
71
71
|
Examples:
|
|
72
|
-
$ flow plugin enable flow-adr-writer`).action(async i=>{let s=await
|
|
72
|
+
$ flow plugin enable flow-adr-writer`).action(async i=>{let s=await $n(i);process.exit(s);}),r.command("disable").description("Disable an installed plugin").argument("<name>","Name of the plugin to disable").addHelpText("after",`
|
|
73
73
|
Examples:
|
|
74
|
-
$ flow plugin disable flow-adr-writer`).action(async i=>{let s=await
|
|
74
|
+
$ flow plugin disable flow-adr-writer`).action(async i=>{let s=await Ln(i);process.exit(s);}),t.addCommand(r);let o=new Command("auth").description("Manage authentication credentials");return o.command("login").description("Authenticate and save credentials locally").option("--client-id <id>","Client ID for non-interactive authentication").option("--client-secret <secret>","Client Secret for non-interactive authentication").option("--tenant <tenant>","Tenant for non-interactive authentication").addHelpText("after",`
|
|
75
75
|
Examples:
|
|
76
76
|
$ flow auth login
|
|
77
|
-
$ flow auth login --client-id ID --client-secret SECRET --tenant TENANT`).action(async i=>{let s=await dt(i);process.exit(s);}),
|
|
77
|
+
$ flow auth login --client-id ID --client-secret SECRET --tenant TENANT`).action(async i=>{let s=await dt(i);process.exit(s);}),o.command("logout").description("Remove locally saved credentials").option("--force","Skip interactive confirmation").addHelpText("after",`
|
|
78
78
|
Examples:
|
|
79
79
|
$ flow auth logout
|
|
80
|
-
$ flow auth logout --force`).action(async i=>{let s=await
|
|
80
|
+
$ flow auth logout --force`).action(async i=>{let s=await En(i.force);process.exit(s);}),o.command("status").description("Display the current authentication status").addHelpText("after",`
|
|
81
81
|
Examples:
|
|
82
|
-
$ flow auth status`).action(async()=>{let i=await An();process.exit(i);}),t.addCommand(
|
|
82
|
+
$ flow auth status`).action(async()=>{let i=await An();process.exit(i);}),t.addCommand(o),t.command("health").description("Check the CLI configuration and connectivity").addHelpText("after",`
|
|
83
83
|
Examples:
|
|
84
|
-
$ flow health`).action(async()=>{let i=await
|
|
84
|
+
$ flow health`).action(async()=>{let i=await Dn();process.exit(i);}),t}var No=Nn(()=>{render(jsx(Pn,{}));});No.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ciandt-flow/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "TUI for browsing and installing Claude Code plugins from the Flow ecosystem",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"scripts": {
|
|
23
23
|
"build": "npm run typecheck && tsup && npm run obfuscate",
|
|
24
24
|
"build:npm": "npm run typecheck && tsup",
|
|
25
|
-
"obfuscate": "javascript-obfuscator dist/index.js --output dist/index.js --options-preset medium-obfuscation --string-array true --string-array-encoding
|
|
25
|
+
"obfuscate": "javascript-obfuscator dist/index.js --output dist/index.js --options-preset medium-obfuscation --string-array true --string-array-encoding base64",
|
|
26
26
|
"typecheck": "tsc --noEmit",
|
|
27
27
|
"dev": "tsx --env-file=.env src/cli.tsx",
|
|
28
28
|
"dev:watch": "tsup --watch & sleep 2 && node --watch dist/index.js",
|