prjct-cli 1.37.0 → 1.38.0

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.
@@ -5,8 +5,8 @@ import { dirname as __pathDirname } from 'path';
5
5
  var require = __createRequire(import.meta.url);
6
6
  var __filename = __fileURLToPath(import.meta.url);
7
7
  var __dirname = __pathDirname(__filename);
8
- var H=Object.defineProperty;var Tt=Object.getOwnPropertyDescriptor;var Et=Object.getOwnPropertyNames;var yt=Object.prototype.hasOwnProperty;var o=(r,e)=>H(r,"name",{value:e,configurable:!0}),Le=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+r+'" is not supported')});var j=(r,e)=>()=>(r&&(e=r(r=0)),e);var Re=(r,e)=>{for(var t in e)H(r,t,{get:e[t],enumerable:!0})},It=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Et(e))!yt.call(r,s)&&s!==t&&H(r,s,{get:()=>e[s],enumerable:!(n=Tt(e,s))||n.enumerable});return r};var ue=r=>It(H({},"__esModule",{value:!0}),r);function wt(r){return r instanceof Error&&"code"in r}function V(r){return wt(r)&&r.code==="ENOENT"}function w(r){return r instanceof Error?r.message:typeof r=="string"?r:"Unknown error"}var k=j(()=>{"use strict";o(wt,"isNodeError");o(V,"isNotFoundError");o(w,"getErrorMessage")});var _e={};Re(_e,{deleteCredential:()=>bt,getCredential:()=>X,getCredentialWithSource:()=>vt,hasCredential:()=>At,setCredential:()=>Nt});import{exec as Pt}from"node:child_process";import{promisify as St}from"node:util";async function Nt(r,e){if(process.platform!=="darwin")return console.warn("[keychain] macOS Keychain only available on macOS"),!1;try{return await G(`security delete-generic-password -s "${K}" -a "${r}" 2>/dev/null || true`),await G(`security add-generic-password -s "${K}" -a "${r}" -w "${e}"`),!0}catch(t){return console.error("[keychain] Failed to store credential:",w(t)),!1}}async function X(r){if(process.platform!=="darwin")return me(r);try{let{stdout:e}=await G(`security find-generic-password -s "${K}" -a "${r}" -w 2>/dev/null`);return e.trim()||null}catch{return me(r)}}async function bt(r){if(process.platform!=="darwin")return!1;try{return await G(`security delete-generic-password -s "${K}" -a "${r}" 2>/dev/null`),!0}catch{return!1}}async function At(r){let e=await X(r);return e!==null&&e.length>0}function me(r){let t={"linear-api-key":"LINEAR_API_KEY","jira-api-token":"JIRA_API_TOKEN"}[r];return process.env[t]||null}async function vt(r){if(process.platform==="darwin")try{let{stdout:t}=await G(`security find-generic-password -s "${K}" -a "${r}" -w 2>/dev/null`),n=t.trim();if(n)return{value:n,source:"keychain"}}catch{}let e=me(r);return e?{value:e,source:"env"}:{value:null,source:"none"}}var G,K,Z=j(()=>{"use strict";k();G=St(Pt),K="prjct-cli";o(Nt,"setCredential");o(X,"getCredential");o(bt,"deleteCredential");o(At,"hasCredential");o(me,"getEnvFallback");o(vt,"getCredentialWithSource")});var Fe=j(()=>{"use strict";k()});import ge from"node:fs/promises";async function m(r){try{return await ge.access(r),!0}catch(e){if(V(e))return!1;throw e}}async function fe(r){try{return(await ge.stat(r)).isDirectory()}catch(e){if(V(e))return!1;throw e}}async function L(r){await ge.mkdir(r,{recursive:!0})}var te=j(()=>{"use strict";Fe();k();o(m,"fileExists");o(fe,"dirExists");o(L,"ensureDir")});import{z as v}from"zod";function Ue(r,e){let t=r.split(".").map(Number),n=e.split(".").map(Number);for(let s=0;s<3;s++){let i=t[s]??0,a=n[s]??0;if(i<a)return-1;if(i>a)return 1}return 0}var Wr,Vr,Zr,jt,Qr,Xe=j(()=>{"use strict";Wr=v.enum(["opus","sonnet","haiku"]),Vr=v.enum(["2.5-pro","2.5-flash","2.0-flash"]),Zr=v.string().min(1),jt=v.object({provider:v.string(),model:v.string(),cliVersion:v.string().optional(),recordedAt:v.string()}),Qr=v.object({preferredModel:v.string().optional(),lastAnalysisModel:jt.optional()});o(Ue,"compareSemver")});import he from"node:fs/promises";import Mt from"node:os";import Ge from"node:path";async function Ye(){try{let r=await he.readFile(ze,"utf-8"),e=JSON.parse(r);return!e.timestamp||!e.detection||Date.now()-new Date(e.timestamp).getTime()>$t?null:e.detection}catch{return null}}async function qe(r){let e={timestamp:new Date().toISOString(),detection:r};await he.mkdir(Ke,{recursive:!0}),await he.writeFile(ze,JSON.stringify(e,null,2))}var Ke,ze,$t,Be=j(()=>{"use strict";Ke=Ge.join(Mt.homedir(),".prjct-cli","cache"),ze=Ge.join(Ke,"providers.json"),$t=600*1e3;o(Ye,"readProviderCache");o(qe,"writeProviderCache")});var se={};Re(se,{AntigravityProvider:()=>ye,ClaudeProvider:()=>re,CodexProvider:()=>Ie,CursorProvider:()=>We,GeminiProvider:()=>Ee,Providers:()=>b,WindsurfProvider:()=>Ve,detectAllProviders:()=>we,detectAntigravity:()=>qt,detectCodex:()=>Bt,detectCursorProject:()=>et,detectProvider:()=>Te,detectWindsurfProject:()=>tt,getActiveProvider:()=>Gt,getCommandsDir:()=>Vt,getGlobalContextPath:()=>Jt,getGlobalSettingsPath:()=>Ht,getProjectCommandsPath:()=>Zt,getProviderBranding:()=>ne,getSkillsPath:()=>Wt,hasProviderConfig:()=>Kt,needsCursorRouterRegeneration:()=>zt,needsWindsurfRouterRegeneration:()=>Yt,selectProvider:()=>Qt,validateCliVersion:()=>Qe});import{exec as Ft}from"node:child_process";import R from"node:os";import g from"node:path";import{promisify as Ut}from"node:util";async function Ze(r){try{let{stdout:e}=await Je(`which ${r}`,{timeout:He});return e.trim()}catch{return null}}async function Xt(r){try{let{stdout:e}=await Je(`${r} --version`,{timeout:He}),t=e.match(/\d+\.\d+\.\d+/);return t?t[0]:e.trim()}catch{return null}}async function Te(r){let e=b[r];if(!e.cliCommand)return{installed:!1};let t=await Ze(e.cliCommand);if(!t)return{installed:!1};let n=await Xt(e.cliCommand),s=Qe(r,n||void 0);return{installed:!0,version:n||void 0,path:t,versionWarning:s||void 0}}function Qe(r,e){let t=b[r];return!t.minCliVersion||!e?null:Ue(e,t.minCliVersion)<0?`\u26A0\uFE0F ${t.displayName} v${e} is below minimum v${t.minCliVersion}. Some features may not work correctly.`:null}async function we(r=!1){if(!r){let s=await Ye();if(s)return s}let[e,t]=await Promise.all([Te("claude"),Te("gemini")]),n={claude:e,gemini:t};return await qe(n).catch(()=>{}),n}async function Gt(r){if(r&&b[r])return b[r];let e=await we();return e.claude.installed&&!e.gemini.installed?re:e.gemini.installed&&!e.claude.installed?Ee:re}async function Kt(r){let e=b[r];return e.configDir?m(e.configDir):!1}function ne(r){return{commitFooter:"Generated with [p/](https://www.prjct.app/)",signature:{claude:"\u26A1 prjct + Claude",gemini:"\u26A1 prjct + Gemini",cursor:"\u26A1 prjct + Cursor",antigravity:"\u26A1 prjct + Antigravity",windsurf:"\u26A1 prjct + Windsurf",codex:"\u26A1 prjct + Codex"}[r]||"\u26A1 prjct"}}async function et(r){let e=g.join(r,".cursor"),t=g.join(e,"rules"),n=g.join(t,"prjct.mdc"),[s,i]=await Promise.all([m(e),m(n)]);return{detected:s,routerInstalled:i,projectRoot:s?r:void 0}}async function zt(r){let e=await et(r);return e.detected&&!e.routerInstalled}async function tt(r){let e=g.join(r,".windsurf"),t=g.join(e,"rules"),n=g.join(t,"prjct.md"),[s,i]=await Promise.all([m(e),m(n)]);return{detected:s,routerInstalled:i,projectRoot:s?r:void 0}}async function Yt(r){let e=await tt(r);return e.detected&&!e.routerInstalled}async function qt(){let r=ye.configDir;if(!r)return{installed:!1,skillInstalled:!1};let e=g.join(r,"skills","prjct","SKILL.md"),[t,n]=await Promise.all([m(r),m(e)]);return{installed:t,skillInstalled:n,configPath:t?r:void 0}}async function Bt(){let r=Ie.configDir;if(!r)return{installed:!1,skillInstalled:!1};let e=await Ze("codex"),t=g.join(r,"skills","prjct","SKILL.md"),[n,s]=await Promise.all([m(r),m(t)]),i=!!e||n;return{installed:i,skillInstalled:s,configPath:i?r:void 0}}function Jt(r){let e=b[r];return e.configDir?g.join(e.configDir,e.contextFile):null}function Ht(r){let e=b[r];return!e.configDir||!e.settingsFile?null:g.join(e.configDir,e.settingsFile)}function Wt(r){return b[r].skillsDir}function Vt(r){return b[r].commandsDir}function Zt(r,e){let t=b[r];return g.join(e,t.commandsDir)}async function Qt(){let r=await we(),e=r.claude.installed,t=r.gemini.installed;return!e&&!t?{provider:"claude",userSelected:!1,detection:r}:e&&!t?{provider:"claude",userSelected:!1,detection:r}:t&&!e?{provider:"gemini",userSelected:!1,detection:r}:{provider:"claude",userSelected:!0,detection:r}}var Je,He,re,Ee,ye,We,Ve,Ie,b,z=j(()=>{"use strict";Xe();te();Be();Je=Ut(Ft),He=2e3,re={name:"claude",displayName:"Claude Code",cliCommand:"claude",configDir:g.join(R.homedir(),".claude"),contextFile:"CLAUDE.md",skillsDir:g.join(R.homedir(),".claude","skills"),commandsDir:".claude/commands",commandFormat:"md",settingsFile:"settings.json",projectSettingsFile:"settings.local.json",ignoreFile:".claudeignore",websiteUrl:"https://www.anthropic.com/claude",docsUrl:"https://docs.anthropic.com/claude-code",defaultModel:"sonnet",supportedModels:["opus","sonnet","haiku"],minCliVersion:"1.0.0"},Ee={name:"gemini",displayName:"Gemini CLI",cliCommand:"gemini",configDir:g.join(R.homedir(),".gemini"),contextFile:"GEMINI.md",skillsDir:g.join(R.homedir(),".gemini","skills"),commandsDir:".gemini/commands",commandFormat:"toml",settingsFile:"settings.json",projectSettingsFile:"settings.json",ignoreFile:".geminiignore",websiteUrl:"https://geminicli.com",docsUrl:"https://geminicli.com/docs",defaultModel:"2.5-flash",supportedModels:["2.5-pro","2.5-flash","2.0-flash"],minCliVersion:"1.0.0"},ye={name:"antigravity",displayName:"Google Antigravity",cliCommand:null,configDir:g.join(R.homedir(),".gemini","antigravity"),contextFile:"ANTIGRAVITY.md",skillsDir:g.join(R.homedir(),".gemini","antigravity","global_skills"),commandsDir:".agent/skills",commandFormat:"md",settingsFile:"mcp_config.json",projectSettingsFile:null,ignoreFile:".agentignore",websiteUrl:"https://gemini.google.com/app/antigravity",docsUrl:"https://gemini.google.com/app/antigravity",defaultModel:null,supportedModels:[],minCliVersion:null},We={name:"cursor",displayName:"Cursor IDE",cliCommand:null,configDir:null,contextFile:"prjct.mdc",skillsDir:null,commandsDir:".cursor/commands",rulesDir:".cursor/rules",commandFormat:"md",settingsFile:null,projectSettingsFile:null,ignoreFile:".cursorignore",isProjectLevel:!0,websiteUrl:"https://cursor.com",docsUrl:"https://cursor.com/docs",defaultModel:null,supportedModels:[],minCliVersion:null},Ve={name:"windsurf",displayName:"Windsurf IDE",cliCommand:null,configDir:null,contextFile:"prjct.md",skillsDir:null,commandsDir:".windsurf/workflows",rulesDir:".windsurf/rules",commandFormat:"md",settingsFile:null,projectSettingsFile:null,ignoreFile:".windsurfignore",isProjectLevel:!0,websiteUrl:"https://windsurf.com",docsUrl:"https://docs.windsurf.com",defaultModel:null,supportedModels:[],minCliVersion:null},Ie={name:"codex",displayName:"OpenAI Codex",cliCommand:"codex",configDir:g.join(R.homedir(),".codex"),contextFile:"AGENTS.md",skillsDir:g.join(R.homedir(),".codex","skills"),commandsDir:".agents/skills",commandFormat:"md",settingsFile:null,projectSettingsFile:null,ignoreFile:".codexignore",websiteUrl:"https://openai.com/codex",docsUrl:"https://github.com/openai/codex",defaultModel:null,supportedModels:[],minCliVersion:null},b={claude:re,gemini:Ee,cursor:We,antigravity:ye,windsurf:Ve,codex:Ie};o(Ze,"whichCommand");o(Xt,"getCliVersion");o(Te,"detectProvider");o(Qe,"validateCliVersion");o(we,"detectAllProviders");o(Gt,"getActiveProvider");o(Kt,"hasProviderConfig");o(ne,"getProviderBranding");o(et,"detectCursorProject");o(zt,"needsCursorRouterRegeneration");o(tt,"detectWindsurfProject");o(Yt,"needsWindsurfRouterRegeneration");o(qt,"detectAntigravity");o(Bt,"detectCodex");o(Jt,"getGlobalContextPath");o(Ht,"getGlobalSettingsPath");o(Wt,"getSkillsPath");o(Vt,"getCommandsDir");o(Zt,"getProjectCommandsPath");o(Qt,"selectProvider")});var M=class{static{o(this,"TTLCache")}cache=new Map;ttl;maxSize;constructor(e={}){this.ttl=e.ttl??5e3,this.maxSize=e.maxSize??50}isValid(e){let t=this.cache.get(e);return t?Date.now()-t.timestamp<this.ttl:!1}get(e){let t=this.cache.get(e);return t?this.isValid(e)?t.data:(this.cache.delete(e),null):null}set(e,t){this.cache.set(e,{data:t,timestamp:Date.now()}),this.evictOldEntries()}delete(e){this.cache.delete(e)}clear(){this.cache.clear()}has(e){return this.cache.has(e)}get size(){return this.cache.size}evictOldEntries(){if(this.cache.size<=this.maxSize)return;let t=Array.from(this.cache.entries()).sort((n,s)=>n[1].timestamp-s[1].timestamp).slice(0,this.cache.size-this.maxSize);for(let[n]of t)this.cache.delete(n)}stats(){return{size:this.cache.size,maxSize:this.maxSize,ttl:this.ttl}}prune(){let e=0;for(let t of this.cache.keys())this.isValid(t)||(this.cache.delete(t),e++);return e}};var W=300*1e3,E=new M({ttl:W,maxSize:100}),N=new M({ttl:W,maxSize:10}),F=new M({ttl:W,maxSize:5}),U=new M({ttl:W,maxSize:5});function de(){E.clear(),N.clear(),F.clear(),U.clear()}o(de,"clearLinearCache");function pe(){return{issues:E.stats(),assignedIssues:N.stats(),teams:F.stats(),projects:U.stats()}}o(pe,"getLinearCacheStats");k();Z();var xt={backlog:"backlog",unstarted:"todo",started:"in_progress",completed:"done",canceled:"cancelled",cancelled:"cancelled"},Dt={0:"none",1:"urgent",2:"high",3:"medium",4:"low"},Oe={none:0,urgent:1,high:2,medium:3,low:4},Q=class{static{o(this,"LinearProvider")}name="linear";displayName="Linear";sdk=null;config=null;isConfigured(){return this.sdk!==null&&this.config?.enabled===!0}async initialize(e){this.config=e;let t=e.apiKey||await X("linear-api-key");if(!t)throw new Error("LINEAR_API_KEY not configured. Run `p. linear setup` to configure.");let{LinearClient:n}=await import("@linear/sdk");this.sdk=new n({apiKey:t});try{await this.sdk.viewer}catch(s){throw this.sdk=null,new Error(`Linear connection failed: ${w(s)}`)}}async fetchAssignedIssues(e){if(!this.sdk)throw new Error("Linear not initialized");let t=await this.sdk.viewer,n={};e?.includeCompleted||(n.state={type:{nin:["completed","canceled"]}}),this.config?.defaultTeamId&&(n.team={id:{eq:this.config.defaultTeamId}});let s=await t.assignedIssues({first:e?.limit||50,filter:Object.keys(n).length>0?n:void 0});return Promise.all(s.nodes.map(i=>this.mapIssue(i)))}async fetchTeamIssues(e,t){if(!this.sdk)throw new Error("Linear not initialized");let s=await(await this.sdk.team(e)).issues({first:t?.limit||50,filter:t?.includeCompleted?void 0:{state:{type:{nin:["completed","canceled"]}}}});return Promise.all(s.nodes.map(i=>this.mapIssue(i)))}async fetchIssue(e){if(!this.sdk)throw new Error("Linear not initialized");try{if(e.includes("-")&&/^[A-Z]+-\d+$/.test(e)){let n=e.match(/^([A-Z]+)-(\d+)$/);if(!n)return null;let[,s,i]=n,a=parseInt(i,10),f=(await this.sdk.teams({first:50})).nodes.find(S=>S.key===s);if(!f)return null;let D=await f.issues({first:1,filter:{number:{eq:a}}});return D.nodes.length>0?this.mapIssue(D.nodes[0]):null}let t=await this.sdk.issue(e);return this.mapIssue(t)}catch{return null}}async createIssue(e){if(!this.sdk)throw new Error("Linear not initialized");let t=e.teamId||this.config?.defaultTeamId;if(!t)throw new Error("Team ID required for creating issues");let s=await(await this.sdk.createIssue({teamId:t,title:e.title,description:e.description,priority:e.priority?Oe[e.priority]:void 0,projectId:e.projectId||this.config?.defaultProjectId,assigneeId:e.assigneeId,labelIds:e.labels?await this.resolveLabelIds(t,e.labels):void 0})).issue;if(!s)throw new Error("Failed to create issue");return this.mapIssue(s)}async updateIssue(e,t){if(!this.sdk)throw new Error("Linear not initialized");let n=await this.fetchIssue(e);if(!n)throw new Error(`Issue ${e} not found`);let s={};t.title!==void 0&&(s.title=t.title),t.description!==void 0&&(s.description=t.description),t.priority!==void 0&&(s.priority=Oe[t.priority]),t.assigneeId!==void 0&&(s.assigneeId=t.assigneeId),t.stateId!==void 0&&(s.stateId=t.stateId),t.projectId!==void 0&&(s.projectId=t.projectId),t.labels!==void 0&&n.team&&(s.labelIds=await this.resolveLabelIds(n.team.id,t.labels)),await this.sdk.updateIssue(n.id,s);let i=await this.fetchIssue(n.id);if(!i)throw new Error("Failed to fetch updated issue");return i}async markInProgress(e){if(!this.sdk)throw new Error("Linear not initialized");let t=await this.fetchIssue(e);if(!t)throw new Error(`Issue ${e} not found`);let s=await(await this.sdk.issue(t.id)).team;if(!s)throw new Error("Issue has no team");let a=(await s.states()).nodes.find(l=>l.type==="started");a&&await this.sdk.updateIssue(t.id,{stateId:a.id})}async markDone(e){if(!this.sdk)throw new Error("Linear not initialized");let t=await this.fetchIssue(e);if(!t)throw new Error(`Issue ${e} not found`);let s=await(await this.sdk.issue(t.id)).team;if(!s)throw new Error("Issue has no team");let a=(await s.states()).nodes.find(l=>l.type==="completed");a&&await this.sdk.updateIssue(t.id,{stateId:a.id})}async addComment(e,t){if(!this.sdk)throw new Error("Linear not initialized");let n=await this.fetchIssue(e);if(!n)throw new Error(`Issue ${e} not found`);await this.sdk.createComment({issueId:n.id,body:t})}async getTeams(){if(!this.sdk)throw new Error("Linear not initialized");return(await this.sdk.teams({first:50})).nodes.map(t=>({id:t.id,name:t.name,key:t.key}))}async getProjects(){if(!this.sdk)throw new Error("Linear not initialized");return(await this.sdk.projects({first:50})).nodes.map(t=>({id:t.id,name:t.name}))}async mapIssue(e){let t=await e.state,n=await e.assignee,s=await e.team,i=await e.project,a=await e.labels();return{id:e.id,externalId:e.identifier,provider:"linear",title:e.title,description:e.description||void 0,status:xt[t?.type||"backlog"]||"backlog",priority:Dt[e.priority]||"none",type:this.inferType(e.title,a.nodes.map(l=>l.name)),assignee:n?{id:n.id,name:n.name,email:n.email}:void 0,labels:a.nodes.map(l=>l.name),team:s?{id:s.id,name:s.name,key:s.key}:void 0,project:i?{id:i.id,name:i.name}:void 0,url:e.url,createdAt:e.createdAt.toISOString(),updatedAt:e.updatedAt.toISOString(),raw:e}}inferType(e,t){let n=e.toLowerCase(),s=t.map(i=>i.toLowerCase());return s.includes("bug")||n.includes("fix")||n.includes("bug")?"bug":s.includes("feature")||n.includes("add")||n.includes("implement")?"feature":s.includes("improvement")||n.includes("improve")||n.includes("enhance")?"improvement":s.includes("chore")||n.includes("chore")||n.includes("deps")?"chore":"task"}async resolveLabelIds(e,t){return this.sdk?(await(await this.sdk.team(e)).labels()).nodes.filter(i=>t.includes(i.name)).map(i=>i.id):[]}},I=new Q;var ee=class{static{o(this,"LinearService")}initialized=!1;userId=null;isReady(){return this.initialized&&I.isConfigured()}async initialize(e){this.initialized||(await I.initialize(e),this.initialized=!0)}async initializeFromApiKey(e,t){let n={enabled:!0,provider:"linear",apiKey:e,defaultTeamId:t,syncOn:{task:!0,done:!0,ship:!0},enrichment:{enabled:!0,updateProvider:!0}};await this.initialize(n)}async fetchAssignedIssues(e){this.ensureInitialized();let t=`assigned:${this.userId||"me"}`,n=N.get(t);if(n)return n;let s=await I.fetchAssignedIssues(e);N.set(t,s);for(let i of s)E.set(`issue:${i.id}`,i),E.set(`issue:${i.externalId}`,i);return s}async fetchTeamIssues(e,t){this.ensureInitialized();let n=`team:${e}`,s=N.get(n);if(s)return s;let i=await I.fetchTeamIssues(e,t);N.set(n,i);for(let a of i)E.set(`issue:${a.id}`,a),E.set(`issue:${a.externalId}`,a);return i}async fetchIssue(e){this.ensureInitialized();let t=`issue:${e}`,n=E.get(t);if(n)return n;let s=await I.fetchIssue(e);return s&&(E.set(`issue:${s.id}`,s),E.set(`issue:${s.externalId}`,s)),s}async createIssue(e){this.ensureInitialized();let t=await I.createIssue(e);return E.set(`issue:${t.id}`,t),E.set(`issue:${t.externalId}`,t),N.clear(),t}async updateIssue(e,t){this.ensureInitialized();let n=await I.updateIssue(e,t);return E.set(`issue:${n.id}`,n),E.set(`issue:${n.externalId}`,n),n}async markInProgress(e){this.ensureInitialized(),await I.markInProgress(e),E.delete(`issue:${e}`),N.clear()}async markDone(e){this.ensureInitialized(),await I.markDone(e),E.delete(`issue:${e}`),N.clear()}async addComment(e,t){this.ensureInitialized(),await I.addComment(e,t)}async getTeams(){this.ensureInitialized();let e=F.get("teams");if(e)return e;let t=await I.getTeams();return F.set("teams",t),t}async getProjects(){this.ensureInitialized();let e=U.get("projects");if(e)return e;let t=await I.getProjects();return U.set("projects",t),t}clearCache(){de()}getCacheStats(){return pe()}ensureInitialized(){if(!this.initialized)throw new Error("Linear service not initialized. Call linearService.initialize() first or run `p. linear setup`.")}},p=new ee;import{z as u}from"zod";var je=u.enum(["linear","jira","github","monday","asana","none"]),Ct=u.enum(["backlog","todo","in_progress","in_review","done","cancelled"]),kt=u.enum(["none","urgent","high","medium","low"]),Lt=u.enum(["feature","bug","improvement","task","chore","epic"]),Rt=u.object({id:u.string(),identifier:u.string(),title:u.string(),description:u.string().optional(),status:Ct,priority:kt,type:Lt.optional(),assignee:u.object({id:u.string(),name:u.string(),email:u.string().optional()}).optional(),labels:u.array(u.string()).default([]),team:u.object({id:u.string(),name:u.string(),key:u.string().optional()}).optional(),project:u.object({id:u.string(),name:u.string()}).optional(),url:u.string(),createdAt:u.string(),updatedAt:u.string(),fetchedAt:u.string()}),_r=u.object({provider:je,lastSync:u.string(),staleAfter:u.number().default(18e5),issues:u.record(u.string(),Rt)}),Or=u.object({provider:je,fetched:u.number(),updated:u.number(),errors:u.array(u.object({issueId:u.string(),error:u.string()})),timestamp:u.string()});function Me(r){return{provider:r,lastSync:"",staleAfter:18e5,issues:{}}}o(Me,"createEmptyIssues");import Ne from"node:fs";import st from"node:path";import er from"node:crypto";import x from"node:fs/promises";import Pe from"node:os";import c from"node:path";import{globSync as tr}from"glob";import{formatDistanceToNowStrict as Fr}from"date-fns";function $e(r){return{year:r.getFullYear().toString(),month:(r.getMonth()+1).toString().padStart(2,"0"),day:r.getDate().toString().padStart(2,"0")}}o($e,"getYearMonthDay");te();var Se=class{static{o(this,"PathManager")}globalBaseDir;globalProjectsDir;globalConfigDir;constructor(){let e=process.env.PRJCT_CLI_HOME?.trim();this.globalBaseDir=e?c.resolve(e):c.join(Pe.homedir(),".prjct-cli"),this.globalProjectsDir=c.join(this.globalBaseDir,"projects"),this.globalConfigDir=c.join(this.globalBaseDir,"config")}setGlobalBaseDir(e){this.globalBaseDir=c.resolve(e),this.globalProjectsDir=c.join(this.globalBaseDir,"projects"),this.globalConfigDir=c.join(this.globalBaseDir,"config")}generateProjectId(e){return er.randomUUID()}getGlobalBasePath(){return this.globalBaseDir}getGlobalProjectPath(e){return c.join(this.globalProjectsDir,e)}getLocalConfigPath(e){return c.join(e,".prjct","prjct.config.json")}getGlobalProjectConfigPath(e){return c.join(this.getGlobalProjectPath(e),"project.json")}getLegacyPrjctPath(e){return c.join(e,".prjct")}async hasLegacyStructure(e){let t=this.getLegacyPrjctPath(e);return await fe(t)}async hasConfig(e){let t=this.getLocalConfigPath(e);return await m(t)}async ensureGlobalStructure(){await L(this.globalBaseDir),await L(this.globalProjectsDir),await L(this.globalConfigDir)}async ensureProjectStructure(e){await this.ensureGlobalStructure();let t=this.getGlobalProjectPath(e),n=["core","progress","planning","analysis","memory","agents"];for(let s of n)await L(c.join(t,s));return await L(c.join(t,"planning","tasks")),await L(c.join(t,"sessions")),t}getSessionPath(e,t=new Date){let{year:n,month:s,day:i}=$e(t);return c.join(this.getGlobalProjectPath(e),"sessions",n,s,i)}getCurrentSessionPath(e){return this.getSessionPath(e,new Date)}async ensureSessionPath(e,t=new Date){let n=this.getSessionPath(e,t);return await L(n),n}async listSessions(e,t=null,n=null){let s=c.join(this.getGlobalProjectPath(e),"sessions"),i=[];try{let a=await x.readdir(s,{withFileTypes:!0});for(let l of a){if(!l.isDirectory()||t&&l.name!==t.toString())continue;let f=c.join(s,l.name),D=await x.readdir(f,{withFileTypes:!0});for(let S of D){if(!S.isDirectory()||n&&S.name!==n.toString().padStart(2,"0"))continue;let B=c.join(f,S.name),le=await x.readdir(B,{withFileTypes:!0});for(let J of le)J.isDirectory()&&i.push({year:l.name,month:S.name,day:J.name,path:c.join(B,J.name),date:new Date(`${l.name}-${S.name}-${J.name}`)})}}return i.sort((l,f)=>f.date.getTime()-l.date.getTime()),i}catch{return[]}}async getSessionsInRange(e,t,n=new Date){return(await this.listSessions(e)).filter(i=>i.date>=t&&i.date<=n)}getFilePath(e,t,n){return c.join(this.getGlobalProjectPath(e),t,n)}async listProjects(){try{return await this.ensureGlobalStructure(),(await x.readdir(this.globalProjectsDir,{withFileTypes:!0})).filter(t=>t.isDirectory()).map(t=>t.name)}catch{return[]}}async projectExists(e){let t=this.getGlobalProjectPath(e);return await fe(t)}getDisplayPath(e){let t=Pe.homedir();return e.startsWith(t)?e.replace(t,"~"):e}getAuthConfigPath(){return c.join(this.globalConfigDir,"auth.json")}getSyncPendingPath(e){return c.join(this.getGlobalProjectPath(e),"sync","pending.json")}getLastSyncPath(e){return c.join(this.getGlobalProjectPath(e),"sync","last-sync.json")}getRunningStatusPath(){return c.join(this.globalBaseDir,".running")}getDocsPath(){return c.join(this.globalBaseDir,"docs")}async getAgentDir(){return(await(z(),ue(se)).getActiveProvider()).configDir}async getAgentSettingsPath(){let e=await(z(),ue(se)).getActiveProvider();return(z(),ue(se)).getGlobalSettingsPath(e.name)}getClaudeDir(){return c.join(Pe.homedir(),".claude")}getClaudeSettingsPath(){return c.join(this.getClaudeDir(),"settings.json")}getAgentsPath(e){return e?c.join(this.getGlobalProjectPath(e),"agents"):c.join(this.globalBaseDir,"agents")}getStoragePath(e,t){return c.join(this.getGlobalProjectPath(e),"storage",t)}getContextPath(e){return c.join(this.getGlobalProjectPath(e),"context")}async detectMonorepo(e){let t={isMonorepo:!1,type:null,rootPath:e,packages:[]},n=[{file:"pnpm-workspace.yaml",type:"pnpm"},{file:"lerna.json",type:"lerna"},{file:"nx.json",type:"nx"},{file:"rush.json",type:"rush"},{file:"turbo.json",type:"turborepo"}];for(let s of n){let i=c.join(e,s.file);if(await m(i)){t.isMonorepo=!0,t.type=s.type;break}}if(!t.isMonorepo){let s=c.join(e,"package.json");if(await m(s))try{let i=await x.readFile(s,"utf-8");JSON.parse(i).workspaces&&(t.isMonorepo=!0,t.type="npm")}catch{}}return t.isMonorepo&&(t.packages=await this.discoverMonorepoPackages(e,t.type)),t}async discoverMonorepoPackages(e,t){let n=[],s=[];try{if(t==="pnpm"){let a=(await x.readFile(c.join(e,"pnpm-workspace.yaml"),"utf-8")).match(/packages:\s*\n((?:\s*-\s*.+\n?)+)/);a&&(s=a[1].split(`
9
- `).map(l=>l.replace(/^\s*-\s*['"]?|['"]?\s*$/g,"")).filter(Boolean))}else if(t==="npm"||t==="lerna"){let i=c.join(e,"package.json"),a=await x.readFile(i,"utf-8"),l=JSON.parse(a);if(Array.isArray(l.workspaces)?s=l.workspaces:l.workspaces?.packages&&(s=l.workspaces.packages),t==="lerna"){let f=c.join(e,"lerna.json");if(await m(f)){let D=await x.readFile(f,"utf-8"),S=JSON.parse(D);S.packages&&(s=S.packages)}}}else if(t==="nx")s=["apps/*","libs/*","packages/*"];else if(t==="turborepo"){let i=c.join(e,"package.json"),a=await x.readFile(i,"utf-8"),l=JSON.parse(a);Array.isArray(l.workspaces)&&(s=l.workspaces)}s.length===0&&(s=["packages/*","apps/*","libs/*"]);for(let i of s){if(i.startsWith("!"))continue;let a=tr(i,{cwd:e,absolute:!1});for(let l of a){let f=c.join(e,l),D=c.join(f,"package.json");if(await m(D))try{let S=await x.readFile(D,"utf-8"),B=JSON.parse(S),le=c.join(f,"PRJCT.md");n.push({name:B.name||c.basename(l),path:f,relativePath:l,hasPrjctMd:await m(le)})}catch{}}}}catch{}return n}async findContainingPackage(e,t){if(!t.isMonorepo)return null;let n=c.resolve(e);for(let s of t.packages){let i=c.resolve(s.path);if(n.startsWith(i))return s}return null}async findMonorepoRoot(e){let t=c.resolve(e),n=c.parse(t).root;for(;t!==n;){if((await this.detectMonorepo(t)).isMonorepo)return t;t=c.dirname(t)}return null}},rr=new Se,rt=rr;function nr(){return typeof globalThis<"u"&&"Bun"in globalThis?"bun":"node"}o(nr,"detectRuntime");function nt(){return nr()==="bun"}o(nt,"isBun");function sr(r){if(nt()){let{Database:s}=Le("bun:sqlite");return new s(r,{create:!0})}let e=Le("better-sqlite3"),t=new e(r),n=t.exec.bind(t);return t.run=s=>n(s),t}o(sr,"openDatabase");var ir=[{version:1,name:"initial-schema",up:o(r=>{r.run(`
8
+ var H=Object.defineProperty;var Et=Object.getOwnPropertyDescriptor;var yt=Object.getOwnPropertyNames;var It=Object.prototype.hasOwnProperty;var o=(r,e)=>H(r,"name",{value:e,configurable:!0}),Re=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+r+'" is not supported')});var j=(r,e)=>()=>(r&&(e=r(r=0)),e);var ke=(r,e)=>{for(var t in e)H(r,t,{get:e[t],enumerable:!0})},wt=(r,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of yt(e))!It.call(r,n)&&n!==t&&H(r,n,{get:()=>e[n],enumerable:!(s=Et(e,n))||s.enumerable});return r};var ue=r=>wt(H({},"__esModule",{value:!0}),r);function Pt(r){return r instanceof Error&&"code"in r}function V(r){return Pt(r)&&r.code==="ENOENT"}function w(r){return r instanceof Error?r.message:typeof r=="string"?r:"Unknown error"}var L=j(()=>{"use strict";o(Pt,"isNodeError");o(V,"isNotFoundError");o(w,"getErrorMessage")});var _e={};ke(_e,{deleteCredential:()=>bt,getCredential:()=>X,getCredentialWithSource:()=>vt,hasCredential:()=>xt,setCredential:()=>At});import{exec as St}from"node:child_process";import{promisify as Nt}from"node:util";async function At(r,e){if(process.platform!=="darwin")return console.warn("[keychain] macOS Keychain only available on macOS"),!1;try{return await G(`security delete-generic-password -s "${K}" -a "${r}" 2>/dev/null || true`),await G(`security add-generic-password -s "${K}" -a "${r}" -w "${e}"`),!0}catch(t){return console.error("[keychain] Failed to store credential:",w(t)),!1}}async function X(r){if(process.platform!=="darwin")return me(r);try{let{stdout:e}=await G(`security find-generic-password -s "${K}" -a "${r}" -w 2>/dev/null`);return e.trim()||null}catch{return me(r)}}async function bt(r){if(process.platform!=="darwin")return!1;try{return await G(`security delete-generic-password -s "${K}" -a "${r}" 2>/dev/null`),!0}catch{return!1}}async function xt(r){let e=await X(r);return e!==null&&e.length>0}function me(r){let t={"linear-api-key":"LINEAR_API_KEY","jira-api-token":"JIRA_API_TOKEN"}[r];return process.env[t]||null}async function vt(r){if(process.platform==="darwin")try{let{stdout:t}=await G(`security find-generic-password -s "${K}" -a "${r}" -w 2>/dev/null`),s=t.trim();if(s)return{value:s,source:"keychain"}}catch{}let e=me(r);return e?{value:e,source:"env"}:{value:null,source:"none"}}var G,K,Z=j(()=>{"use strict";L();G=Nt(St),K="prjct-cli";o(At,"setCredential");o(X,"getCredential");o(bt,"deleteCredential");o(xt,"hasCredential");o(me,"getEnvFallback");o(vt,"getCredentialWithSource")});var Fe=j(()=>{"use strict";L()});import ge from"node:fs/promises";async function m(r){try{return await ge.access(r),!0}catch(e){if(V(e))return!1;throw e}}async function fe(r){try{return(await ge.stat(r)).isDirectory()}catch(e){if(V(e))return!1;throw e}}async function R(r){await ge.mkdir(r,{recursive:!0})}var te=j(()=>{"use strict";Fe();L();o(m,"fileExists");o(fe,"dirExists");o(R,"ensureDir")});import{z as x}from"zod";function Ue(r,e){let t=r.split(".").map(Number),s=e.split(".").map(Number);for(let n=0;n<3;n++){let i=t[n]??0,a=s[n]??0;if(i<a)return-1;if(i>a)return 1}return 0}var Wr,Vr,Zr,Mt,Qr,Xe=j(()=>{"use strict";Wr=x.enum(["opus","sonnet","haiku"]),Vr=x.enum(["2.5-pro","2.5-flash","2.0-flash"]),Zr=x.string().min(1),Mt=x.object({provider:x.string(),model:x.string(),cliVersion:x.string().optional(),recordedAt:x.string()}),Qr=x.object({preferredModel:x.string().optional(),lastAnalysisModel:Mt.optional()});o(Ue,"compareSemver")});import he from"node:fs/promises";import $t from"node:os";import Ge from"node:path";async function Ye(){try{let r=await he.readFile(ze,"utf-8"),e=JSON.parse(r);return!e.timestamp||!e.detection||Date.now()-new Date(e.timestamp).getTime()>Ft?null:e.detection}catch{return null}}async function qe(r){let e={timestamp:new Date().toISOString(),detection:r};await he.mkdir(Ke,{recursive:!0}),await he.writeFile(ze,JSON.stringify(e,null,2))}var Ke,ze,Ft,Be=j(()=>{"use strict";Ke=Ge.join($t.homedir(),".prjct-cli","cache"),ze=Ge.join(Ke,"providers.json"),Ft=600*1e3;o(Ye,"readProviderCache");o(qe,"writeProviderCache")});var ne={};ke(ne,{AntigravityProvider:()=>ye,ClaudeProvider:()=>re,CodexProvider:()=>Ie,CursorProvider:()=>We,GeminiProvider:()=>Ee,Providers:()=>A,WindsurfProvider:()=>Ve,detectAllProviders:()=>we,detectAntigravity:()=>Bt,detectCodex:()=>rt,detectCursorProject:()=>et,detectProvider:()=>Te,detectWindsurfProject:()=>tt,getActiveProvider:()=>Kt,getCommandsDir:()=>Vt,getGlobalContextPath:()=>Jt,getGlobalSettingsPath:()=>Ht,getProjectCommandsPath:()=>Zt,getProviderBranding:()=>se,getSkillsPath:()=>Wt,hasProviderConfig:()=>zt,needsCursorRouterRegeneration:()=>Yt,needsWindsurfRouterRegeneration:()=>qt,selectProvider:()=>Qt,validateCliVersion:()=>Qe});import{exec as Ut}from"node:child_process";import k from"node:os";import g from"node:path";import{promisify as Xt}from"node:util";async function Ze(r){try{let{stdout:e}=await Je(`which ${r}`,{timeout:He});return e.trim()}catch{return null}}async function Gt(r){try{let{stdout:e}=await Je(`${r} --version`,{timeout:He}),t=e.match(/\d+\.\d+\.\d+/);return t?t[0]:e.trim()}catch{return null}}async function Te(r){let e=A[r];if(!e.cliCommand)return{installed:!1};let t=await Ze(e.cliCommand);if(!t)return{installed:!1};let s=await Gt(e.cliCommand),n=Qe(r,s||void 0);return{installed:!0,version:s||void 0,path:t,versionWarning:n||void 0}}function Qe(r,e){let t=A[r];return!t.minCliVersion||!e?null:Ue(e,t.minCliVersion)<0?`\u26A0\uFE0F ${t.displayName} v${e} is below minimum v${t.minCliVersion}. Some features may not work correctly.`:null}async function we(r=!1){if(!r){let a=await Ye();if(a)return a}let[e,t,s]=await Promise.all([Te("claude"),Te("gemini"),rt()]),n={installed:s.installed},i={claude:e,gemini:t,codex:n};return await qe(i).catch(()=>{}),i}async function Kt(r){if(r&&A[r])return A[r];let e=await we();return e.claude.installed&&!e.gemini.installed?re:e.gemini.installed&&!e.claude.installed?Ee:re}async function zt(r){let e=A[r];return e.configDir?m(e.configDir):!1}function se(r){return{commitFooter:"Generated with [p/](https://www.prjct.app/)",signature:{claude:"\u26A1 prjct + Claude",gemini:"\u26A1 prjct + Gemini",cursor:"\u26A1 prjct + Cursor",antigravity:"\u26A1 prjct + Antigravity",windsurf:"\u26A1 prjct + Windsurf",codex:"\u26A1 prjct + Codex"}[r]||"\u26A1 prjct"}}async function et(r){let e=g.join(r,".cursor"),t=g.join(e,"rules"),s=g.join(t,"prjct.mdc"),[n,i]=await Promise.all([m(e),m(s)]);return{detected:n,routerInstalled:i,projectRoot:n?r:void 0}}async function Yt(r){let e=await et(r);return e.detected&&!e.routerInstalled}async function tt(r){let e=g.join(r,".windsurf"),t=g.join(e,"rules"),s=g.join(t,"prjct.md"),[n,i]=await Promise.all([m(e),m(s)]);return{detected:n,routerInstalled:i,projectRoot:n?r:void 0}}async function qt(r){let e=await tt(r);return e.detected&&!e.routerInstalled}async function Bt(){let r=ye.configDir;if(!r)return{installed:!1,skillInstalled:!1};let e=g.join(r,"skills","prjct","SKILL.md"),[t,s]=await Promise.all([m(r),m(e)]);return{installed:t,skillInstalled:s,configPath:t?r:void 0}}async function rt(){let r=Ie.configDir;if(!r)return{installed:!1,skillInstalled:!1};let e=await Ze("codex"),t=g.join(r,"skills","prjct","SKILL.md"),[s,n]=await Promise.all([m(r),m(t)]),i=!!e||s;return{installed:i,skillInstalled:n,configPath:i?r:void 0}}function Jt(r){let e=A[r];return e.configDir?g.join(e.configDir,e.contextFile):null}function Ht(r){let e=A[r];return!e.configDir||!e.settingsFile?null:g.join(e.configDir,e.settingsFile)}function Wt(r){return A[r].skillsDir}function Vt(r){return A[r].commandsDir}function Zt(r,e){let t=A[r];return g.join(e,t.commandsDir)}async function Qt(){let r=await we(),e=r.claude.installed,t=r.gemini.installed;return!e&&!t?{provider:"claude",userSelected:!1,detection:r}:e&&!t?{provider:"claude",userSelected:!1,detection:r}:t&&!e?{provider:"gemini",userSelected:!1,detection:r}:{provider:"claude",userSelected:!0,detection:r}}var Je,He,re,Ee,ye,We,Ve,Ie,A,z=j(()=>{"use strict";Xe();te();Be();Je=Xt(Ut),He=2e3,re={name:"claude",displayName:"Claude Code",cliCommand:"claude",configDir:g.join(k.homedir(),".claude"),contextFile:"CLAUDE.md",skillsDir:g.join(k.homedir(),".claude","skills"),commandsDir:".claude/commands",commandFormat:"md",settingsFile:"settings.json",projectSettingsFile:"settings.local.json",ignoreFile:".claudeignore",websiteUrl:"https://www.anthropic.com/claude",docsUrl:"https://docs.anthropic.com/claude-code",defaultModel:"sonnet",supportedModels:["opus","sonnet","haiku"],minCliVersion:"1.0.0"},Ee={name:"gemini",displayName:"Gemini CLI",cliCommand:"gemini",configDir:g.join(k.homedir(),".gemini"),contextFile:"GEMINI.md",skillsDir:g.join(k.homedir(),".gemini","skills"),commandsDir:".gemini/commands",commandFormat:"toml",settingsFile:"settings.json",projectSettingsFile:"settings.json",ignoreFile:".geminiignore",websiteUrl:"https://geminicli.com",docsUrl:"https://geminicli.com/docs",defaultModel:"2.5-flash",supportedModels:["2.5-pro","2.5-flash","2.0-flash"],minCliVersion:"1.0.0"},ye={name:"antigravity",displayName:"Google Antigravity",cliCommand:null,configDir:g.join(k.homedir(),".gemini","antigravity"),contextFile:"ANTIGRAVITY.md",skillsDir:g.join(k.homedir(),".gemini","antigravity","global_skills"),commandsDir:".agent/skills",commandFormat:"md",settingsFile:"mcp_config.json",projectSettingsFile:null,ignoreFile:".agentignore",websiteUrl:"https://gemini.google.com/app/antigravity",docsUrl:"https://gemini.google.com/app/antigravity",defaultModel:null,supportedModels:[],minCliVersion:null},We={name:"cursor",displayName:"Cursor IDE",cliCommand:null,configDir:null,contextFile:"prjct.mdc",skillsDir:null,commandsDir:".cursor/commands",rulesDir:".cursor/rules",commandFormat:"md",settingsFile:null,projectSettingsFile:null,ignoreFile:".cursorignore",isProjectLevel:!0,websiteUrl:"https://cursor.com",docsUrl:"https://cursor.com/docs",defaultModel:null,supportedModels:[],minCliVersion:null},Ve={name:"windsurf",displayName:"Windsurf IDE",cliCommand:null,configDir:null,contextFile:"prjct.md",skillsDir:null,commandsDir:".windsurf/workflows",rulesDir:".windsurf/rules",commandFormat:"md",settingsFile:null,projectSettingsFile:null,ignoreFile:".windsurfignore",isProjectLevel:!0,websiteUrl:"https://windsurf.com",docsUrl:"https://docs.windsurf.com",defaultModel:null,supportedModels:[],minCliVersion:null},Ie={name:"codex",displayName:"OpenAI Codex",cliCommand:"codex",configDir:g.join(k.homedir(),".codex"),contextFile:"AGENTS.md",skillsDir:g.join(k.homedir(),".codex","skills"),commandsDir:".agents/skills",commandFormat:"md",settingsFile:null,projectSettingsFile:null,ignoreFile:".codexignore",websiteUrl:"https://openai.com/codex",docsUrl:"https://github.com/openai/codex",defaultModel:null,supportedModels:[],minCliVersion:null},A={claude:re,gemini:Ee,cursor:We,antigravity:ye,windsurf:Ve,codex:Ie};o(Ze,"whichCommand");o(Gt,"getCliVersion");o(Te,"detectProvider");o(Qe,"validateCliVersion");o(we,"detectAllProviders");o(Kt,"getActiveProvider");o(zt,"hasProviderConfig");o(se,"getProviderBranding");o(et,"detectCursorProject");o(Yt,"needsCursorRouterRegeneration");o(tt,"detectWindsurfProject");o(qt,"needsWindsurfRouterRegeneration");o(Bt,"detectAntigravity");o(rt,"detectCodex");o(Jt,"getGlobalContextPath");o(Ht,"getGlobalSettingsPath");o(Wt,"getSkillsPath");o(Vt,"getCommandsDir");o(Zt,"getProjectCommandsPath");o(Qt,"selectProvider")});var M=class{static{o(this,"TTLCache")}cache=new Map;ttl;maxSize;constructor(e={}){this.ttl=e.ttl??5e3,this.maxSize=e.maxSize??50}isValid(e){let t=this.cache.get(e);return t?Date.now()-t.timestamp<this.ttl:!1}get(e){let t=this.cache.get(e);return t?this.isValid(e)?t.data:(this.cache.delete(e),null):null}set(e,t){this.cache.set(e,{data:t,timestamp:Date.now()}),this.evictOldEntries()}delete(e){this.cache.delete(e)}clear(){this.cache.clear()}has(e){return this.cache.has(e)}get size(){return this.cache.size}evictOldEntries(){if(this.cache.size<=this.maxSize)return;let t=Array.from(this.cache.entries()).sort((s,n)=>s[1].timestamp-n[1].timestamp).slice(0,this.cache.size-this.maxSize);for(let[s]of t)this.cache.delete(s)}stats(){return{size:this.cache.size,maxSize:this.maxSize,ttl:this.ttl}}prune(){let e=0;for(let t of this.cache.keys())this.isValid(t)||(this.cache.delete(t),e++);return e}};var W=300*1e3,E=new M({ttl:W,maxSize:100}),N=new M({ttl:W,maxSize:10}),F=new M({ttl:W,maxSize:5}),U=new M({ttl:W,maxSize:5});function de(){E.clear(),N.clear(),F.clear(),U.clear()}o(de,"clearLinearCache");function pe(){return{issues:E.stats(),assignedIssues:N.stats(),teams:F.stats(),projects:U.stats()}}o(pe,"getLinearCacheStats");L();Z();var Dt={backlog:"backlog",unstarted:"todo",started:"in_progress",completed:"done",canceled:"cancelled",cancelled:"cancelled"},Ct={0:"none",1:"urgent",2:"high",3:"medium",4:"low"},Oe={none:0,urgent:1,high:2,medium:3,low:4},Q=class{static{o(this,"LinearProvider")}name="linear";displayName="Linear";sdk=null;config=null;isConfigured(){return this.sdk!==null&&this.config?.enabled===!0}async initialize(e){this.config=e;let t=e.apiKey||await X("linear-api-key");if(!t)throw new Error("LINEAR_API_KEY not configured. Run `p. linear setup` to configure.");let{LinearClient:s}=await import("@linear/sdk");this.sdk=new s({apiKey:t});try{await this.sdk.viewer}catch(n){throw this.sdk=null,new Error(`Linear connection failed: ${w(n)}`)}}async fetchAssignedIssues(e){if(!this.sdk)throw new Error("Linear not initialized");let t=await this.sdk.viewer,s={};e?.includeCompleted||(s.state={type:{nin:["completed","canceled"]}}),this.config?.defaultTeamId&&(s.team={id:{eq:this.config.defaultTeamId}});let n=await t.assignedIssues({first:e?.limit||50,filter:Object.keys(s).length>0?s:void 0});return Promise.all(n.nodes.map(i=>this.mapIssue(i)))}async fetchTeamIssues(e,t){if(!this.sdk)throw new Error("Linear not initialized");let n=await(await this.sdk.team(e)).issues({first:t?.limit||50,filter:t?.includeCompleted?void 0:{state:{type:{nin:["completed","canceled"]}}}});return Promise.all(n.nodes.map(i=>this.mapIssue(i)))}async fetchIssue(e){if(!this.sdk)throw new Error("Linear not initialized");try{if(e.includes("-")&&/^[A-Z]+-\d+$/.test(e)){let s=e.match(/^([A-Z]+)-(\d+)$/);if(!s)return null;let[,n,i]=s,a=parseInt(i,10),f=(await this.sdk.teams({first:50})).nodes.find(S=>S.key===n);if(!f)return null;let D=await f.issues({first:1,filter:{number:{eq:a}}});return D.nodes.length>0?this.mapIssue(D.nodes[0]):null}let t=await this.sdk.issue(e);return this.mapIssue(t)}catch{return null}}async createIssue(e){if(!this.sdk)throw new Error("Linear not initialized");let t=e.teamId||this.config?.defaultTeamId;if(!t)throw new Error("Team ID required for creating issues");let n=await(await this.sdk.createIssue({teamId:t,title:e.title,description:e.description,priority:e.priority?Oe[e.priority]:void 0,projectId:e.projectId||this.config?.defaultProjectId,assigneeId:e.assigneeId,labelIds:e.labels?await this.resolveLabelIds(t,e.labels):void 0})).issue;if(!n)throw new Error("Failed to create issue");return this.mapIssue(n)}async updateIssue(e,t){if(!this.sdk)throw new Error("Linear not initialized");let s=await this.fetchIssue(e);if(!s)throw new Error(`Issue ${e} not found`);let n={};t.title!==void 0&&(n.title=t.title),t.description!==void 0&&(n.description=t.description),t.priority!==void 0&&(n.priority=Oe[t.priority]),t.assigneeId!==void 0&&(n.assigneeId=t.assigneeId),t.stateId!==void 0&&(n.stateId=t.stateId),t.projectId!==void 0&&(n.projectId=t.projectId),t.labels!==void 0&&s.team&&(n.labelIds=await this.resolveLabelIds(s.team.id,t.labels)),await this.sdk.updateIssue(s.id,n);let i=await this.fetchIssue(s.id);if(!i)throw new Error("Failed to fetch updated issue");return i}async markInProgress(e){if(!this.sdk)throw new Error("Linear not initialized");let t=await this.fetchIssue(e);if(!t)throw new Error(`Issue ${e} not found`);let n=await(await this.sdk.issue(t.id)).team;if(!n)throw new Error("Issue has no team");let a=(await n.states()).nodes.find(l=>l.type==="started");a&&await this.sdk.updateIssue(t.id,{stateId:a.id})}async markDone(e){if(!this.sdk)throw new Error("Linear not initialized");let t=await this.fetchIssue(e);if(!t)throw new Error(`Issue ${e} not found`);let n=await(await this.sdk.issue(t.id)).team;if(!n)throw new Error("Issue has no team");let a=(await n.states()).nodes.find(l=>l.type==="completed");a&&await this.sdk.updateIssue(t.id,{stateId:a.id})}async addComment(e,t){if(!this.sdk)throw new Error("Linear not initialized");let s=await this.fetchIssue(e);if(!s)throw new Error(`Issue ${e} not found`);await this.sdk.createComment({issueId:s.id,body:t})}async getTeams(){if(!this.sdk)throw new Error("Linear not initialized");return(await this.sdk.teams({first:50})).nodes.map(t=>({id:t.id,name:t.name,key:t.key}))}async getProjects(){if(!this.sdk)throw new Error("Linear not initialized");return(await this.sdk.projects({first:50})).nodes.map(t=>({id:t.id,name:t.name}))}async mapIssue(e){let t=await e.state,s=await e.assignee,n=await e.team,i=await e.project,a=await e.labels();return{id:e.id,externalId:e.identifier,provider:"linear",title:e.title,description:e.description||void 0,status:Dt[t?.type||"backlog"]||"backlog",priority:Ct[e.priority]||"none",type:this.inferType(e.title,a.nodes.map(l=>l.name)),assignee:s?{id:s.id,name:s.name,email:s.email}:void 0,labels:a.nodes.map(l=>l.name),team:n?{id:n.id,name:n.name,key:n.key}:void 0,project:i?{id:i.id,name:i.name}:void 0,url:e.url,createdAt:e.createdAt.toISOString(),updatedAt:e.updatedAt.toISOString(),raw:e}}inferType(e,t){let s=e.toLowerCase(),n=t.map(i=>i.toLowerCase());return n.includes("bug")||s.includes("fix")||s.includes("bug")?"bug":n.includes("feature")||s.includes("add")||s.includes("implement")?"feature":n.includes("improvement")||s.includes("improve")||s.includes("enhance")?"improvement":n.includes("chore")||s.includes("chore")||s.includes("deps")?"chore":"task"}async resolveLabelIds(e,t){return this.sdk?(await(await this.sdk.team(e)).labels()).nodes.filter(i=>t.includes(i.name)).map(i=>i.id):[]}},I=new Q;var ee=class{static{o(this,"LinearService")}initialized=!1;userId=null;isReady(){return this.initialized&&I.isConfigured()}async initialize(e){this.initialized||(await I.initialize(e),this.initialized=!0)}async initializeFromApiKey(e,t){let s={enabled:!0,provider:"linear",apiKey:e,defaultTeamId:t,syncOn:{task:!0,done:!0,ship:!0},enrichment:{enabled:!0,updateProvider:!0}};await this.initialize(s)}async fetchAssignedIssues(e){this.ensureInitialized();let t=`assigned:${this.userId||"me"}`,s=N.get(t);if(s)return s;let n=await I.fetchAssignedIssues(e);N.set(t,n);for(let i of n)E.set(`issue:${i.id}`,i),E.set(`issue:${i.externalId}`,i);return n}async fetchTeamIssues(e,t){this.ensureInitialized();let s=`team:${e}`,n=N.get(s);if(n)return n;let i=await I.fetchTeamIssues(e,t);N.set(s,i);for(let a of i)E.set(`issue:${a.id}`,a),E.set(`issue:${a.externalId}`,a);return i}async fetchIssue(e){this.ensureInitialized();let t=`issue:${e}`,s=E.get(t);if(s)return s;let n=await I.fetchIssue(e);return n&&(E.set(`issue:${n.id}`,n),E.set(`issue:${n.externalId}`,n)),n}async createIssue(e){this.ensureInitialized();let t=await I.createIssue(e);return E.set(`issue:${t.id}`,t),E.set(`issue:${t.externalId}`,t),N.clear(),t}async updateIssue(e,t){this.ensureInitialized();let s=await I.updateIssue(e,t);return E.set(`issue:${s.id}`,s),E.set(`issue:${s.externalId}`,s),s}async markInProgress(e){this.ensureInitialized(),await I.markInProgress(e),E.delete(`issue:${e}`),N.clear()}async markDone(e){this.ensureInitialized(),await I.markDone(e),E.delete(`issue:${e}`),N.clear()}async addComment(e,t){this.ensureInitialized(),await I.addComment(e,t)}async getTeams(){this.ensureInitialized();let e=F.get("teams");if(e)return e;let t=await I.getTeams();return F.set("teams",t),t}async getProjects(){this.ensureInitialized();let e=U.get("projects");if(e)return e;let t=await I.getProjects();return U.set("projects",t),t}clearCache(){de()}getCacheStats(){return pe()}ensureInitialized(){if(!this.initialized)throw new Error("Linear service not initialized. Call linearService.initialize() first or run `p. linear setup`.")}},p=new ee;import{z as u}from"zod";var je=u.enum(["linear","jira","github","monday","asana","none"]),Lt=u.enum(["backlog","todo","in_progress","in_review","done","cancelled"]),Rt=u.enum(["none","urgent","high","medium","low"]),kt=u.enum(["feature","bug","improvement","task","chore","epic"]),_t=u.object({id:u.string(),identifier:u.string(),title:u.string(),description:u.string().optional(),status:Lt,priority:Rt,type:kt.optional(),assignee:u.object({id:u.string(),name:u.string(),email:u.string().optional()}).optional(),labels:u.array(u.string()).default([]),team:u.object({id:u.string(),name:u.string(),key:u.string().optional()}).optional(),project:u.object({id:u.string(),name:u.string()}).optional(),url:u.string(),createdAt:u.string(),updatedAt:u.string(),fetchedAt:u.string()}),_r=u.object({provider:je,lastSync:u.string(),staleAfter:u.number().default(18e5),issues:u.record(u.string(),_t)}),Or=u.object({provider:je,fetched:u.number(),updated:u.number(),errors:u.array(u.object({issueId:u.string(),error:u.string()})),timestamp:u.string()});function Me(r){return{provider:r,lastSync:"",staleAfter:18e5,issues:{}}}o(Me,"createEmptyIssues");import Ne from"node:fs";import it from"node:path";import er from"node:crypto";import v from"node:fs/promises";import Pe from"node:os";import c from"node:path";import{globSync as tr}from"glob";import{formatDistanceToNowStrict as Fr}from"date-fns";function $e(r){return{year:r.getFullYear().toString(),month:(r.getMonth()+1).toString().padStart(2,"0"),day:r.getDate().toString().padStart(2,"0")}}o($e,"getYearMonthDay");te();var Se=class{static{o(this,"PathManager")}globalBaseDir;globalProjectsDir;globalConfigDir;constructor(){let e=process.env.PRJCT_CLI_HOME?.trim();this.globalBaseDir=e?c.resolve(e):c.join(Pe.homedir(),".prjct-cli"),this.globalProjectsDir=c.join(this.globalBaseDir,"projects"),this.globalConfigDir=c.join(this.globalBaseDir,"config")}setGlobalBaseDir(e){this.globalBaseDir=c.resolve(e),this.globalProjectsDir=c.join(this.globalBaseDir,"projects"),this.globalConfigDir=c.join(this.globalBaseDir,"config")}generateProjectId(e){return er.randomUUID()}getGlobalBasePath(){return this.globalBaseDir}getGlobalProjectPath(e){return c.join(this.globalProjectsDir,e)}getLocalConfigPath(e){return c.join(e,".prjct","prjct.config.json")}getGlobalProjectConfigPath(e){return c.join(this.getGlobalProjectPath(e),"project.json")}getLegacyPrjctPath(e){return c.join(e,".prjct")}async hasLegacyStructure(e){let t=this.getLegacyPrjctPath(e);return await fe(t)}async hasConfig(e){let t=this.getLocalConfigPath(e);return await m(t)}async ensureGlobalStructure(){await R(this.globalBaseDir),await R(this.globalProjectsDir),await R(this.globalConfigDir)}async ensureProjectStructure(e){await this.ensureGlobalStructure();let t=this.getGlobalProjectPath(e),s=["core","progress","planning","analysis","memory","agents"];for(let n of s)await R(c.join(t,n));return await R(c.join(t,"planning","tasks")),await R(c.join(t,"sessions")),t}getSessionPath(e,t=new Date){let{year:s,month:n,day:i}=$e(t);return c.join(this.getGlobalProjectPath(e),"sessions",s,n,i)}getCurrentSessionPath(e){return this.getSessionPath(e,new Date)}async ensureSessionPath(e,t=new Date){let s=this.getSessionPath(e,t);return await R(s),s}async listSessions(e,t=null,s=null){let n=c.join(this.getGlobalProjectPath(e),"sessions"),i=[];try{let a=await v.readdir(n,{withFileTypes:!0});for(let l of a){if(!l.isDirectory()||t&&l.name!==t.toString())continue;let f=c.join(n,l.name),D=await v.readdir(f,{withFileTypes:!0});for(let S of D){if(!S.isDirectory()||s&&S.name!==s.toString().padStart(2,"0"))continue;let B=c.join(f,S.name),le=await v.readdir(B,{withFileTypes:!0});for(let J of le)J.isDirectory()&&i.push({year:l.name,month:S.name,day:J.name,path:c.join(B,J.name),date:new Date(`${l.name}-${S.name}-${J.name}`)})}}return i.sort((l,f)=>f.date.getTime()-l.date.getTime()),i}catch{return[]}}async getSessionsInRange(e,t,s=new Date){return(await this.listSessions(e)).filter(i=>i.date>=t&&i.date<=s)}getFilePath(e,t,s){return c.join(this.getGlobalProjectPath(e),t,s)}async listProjects(){try{return await this.ensureGlobalStructure(),(await v.readdir(this.globalProjectsDir,{withFileTypes:!0})).filter(t=>t.isDirectory()).map(t=>t.name)}catch{return[]}}async projectExists(e){let t=this.getGlobalProjectPath(e);return await fe(t)}getDisplayPath(e){let t=Pe.homedir();return e.startsWith(t)?e.replace(t,"~"):e}getAuthConfigPath(){return c.join(this.globalConfigDir,"auth.json")}getSyncPendingPath(e){return c.join(this.getGlobalProjectPath(e),"sync","pending.json")}getLastSyncPath(e){return c.join(this.getGlobalProjectPath(e),"sync","last-sync.json")}getRunningStatusPath(){return c.join(this.globalBaseDir,".running")}getDocsPath(){return c.join(this.globalBaseDir,"docs")}async getAgentDir(){return(await(z(),ue(ne)).getActiveProvider()).configDir}async getAgentSettingsPath(){let e=await(z(),ue(ne)).getActiveProvider();return(z(),ue(ne)).getGlobalSettingsPath(e.name)}getClaudeDir(){return c.join(Pe.homedir(),".claude")}getClaudeSettingsPath(){return c.join(this.getClaudeDir(),"settings.json")}getAgentsPath(e){return e?c.join(this.getGlobalProjectPath(e),"agents"):c.join(this.globalBaseDir,"agents")}getStoragePath(e,t){return c.join(this.getGlobalProjectPath(e),"storage",t)}getContextPath(e){return c.join(this.getGlobalProjectPath(e),"context")}async detectMonorepo(e){let t={isMonorepo:!1,type:null,rootPath:e,packages:[]},s=[{file:"pnpm-workspace.yaml",type:"pnpm"},{file:"lerna.json",type:"lerna"},{file:"nx.json",type:"nx"},{file:"rush.json",type:"rush"},{file:"turbo.json",type:"turborepo"}];for(let n of s){let i=c.join(e,n.file);if(await m(i)){t.isMonorepo=!0,t.type=n.type;break}}if(!t.isMonorepo){let n=c.join(e,"package.json");if(await m(n))try{let i=await v.readFile(n,"utf-8");JSON.parse(i).workspaces&&(t.isMonorepo=!0,t.type="npm")}catch{}}return t.isMonorepo&&(t.packages=await this.discoverMonorepoPackages(e,t.type)),t}async discoverMonorepoPackages(e,t){let s=[],n=[];try{if(t==="pnpm"){let a=(await v.readFile(c.join(e,"pnpm-workspace.yaml"),"utf-8")).match(/packages:\s*\n((?:\s*-\s*.+\n?)+)/);a&&(n=a[1].split(`
9
+ `).map(l=>l.replace(/^\s*-\s*['"]?|['"]?\s*$/g,"")).filter(Boolean))}else if(t==="npm"||t==="lerna"){let i=c.join(e,"package.json"),a=await v.readFile(i,"utf-8"),l=JSON.parse(a);if(Array.isArray(l.workspaces)?n=l.workspaces:l.workspaces?.packages&&(n=l.workspaces.packages),t==="lerna"){let f=c.join(e,"lerna.json");if(await m(f)){let D=await v.readFile(f,"utf-8"),S=JSON.parse(D);S.packages&&(n=S.packages)}}}else if(t==="nx")n=["apps/*","libs/*","packages/*"];else if(t==="turborepo"){let i=c.join(e,"package.json"),a=await v.readFile(i,"utf-8"),l=JSON.parse(a);Array.isArray(l.workspaces)&&(n=l.workspaces)}n.length===0&&(n=["packages/*","apps/*","libs/*"]);for(let i of n){if(i.startsWith("!"))continue;let a=tr(i,{cwd:e,absolute:!1});for(let l of a){let f=c.join(e,l),D=c.join(f,"package.json");if(await m(D))try{let S=await v.readFile(D,"utf-8"),B=JSON.parse(S),le=c.join(f,"PRJCT.md");s.push({name:B.name||c.basename(l),path:f,relativePath:l,hasPrjctMd:await m(le)})}catch{}}}}catch{}return s}async findContainingPackage(e,t){if(!t.isMonorepo)return null;let s=c.resolve(e);for(let n of t.packages){let i=c.resolve(n.path);if(s.startsWith(i))return n}return null}async findMonorepoRoot(e){let t=c.resolve(e),s=c.parse(t).root;for(;t!==s;){if((await this.detectMonorepo(t)).isMonorepo)return t;t=c.dirname(t)}return null}},rr=new Se,st=rr;function sr(){return typeof globalThis<"u"&&"Bun"in globalThis?"bun":"node"}o(sr,"detectRuntime");function nt(){return sr()==="bun"}o(nt,"isBun");function nr(r){if(nt()){let{Database:n}=Re("bun:sqlite");return new n(r,{create:!0})}let e=Re("better-sqlite3"),t=new e(r),s=t.exec.bind(t);return t.run=n=>s(n),t}o(nr,"openDatabase");var ir=[{version:1,name:"initial-schema",up:o(r=>{r.run(`
10
10
  -- =======================================================================
11
11
  -- Document storage (backward-compatible with JSON file pattern)
12
12
  -- =======================================================================
@@ -280,18 +280,34 @@ var H=Object.defineProperty;var Tt=Object.getOwnPropertyDescriptor;var Et=Object
280
280
  ('done', 'Complete current task/subtask', 1, 1, datetime('now'), datetime('now')),
281
281
  ('ship', 'Ship feature with version bump and PR', 1, 1, datetime('now'), datetime('now')),
282
282
  ('sync', 'Analyze project and regenerate context', 1, 1, datetime('now'), datetime('now'));
283
- `)},"up")}],be=class{static{o(this,"PrjctDatabase")}connections=new Map;getDbPath(e){return st.join(rt.getGlobalProjectPath(e),"prjct.db")}getDb(e){let t=this.connections.get(e);if(t)return t;let n=this.getDbPath(e),s=st.dirname(n);Ne.existsSync(s)||Ne.mkdirSync(s,{recursive:!0});let i=sr(n);return i.run("PRAGMA journal_mode = WAL"),i.run("PRAGMA synchronous = NORMAL"),i.run("PRAGMA cache_size = -2000"),i.run("PRAGMA temp_store = MEMORY"),i.run("PRAGMA mmap_size = 268435456"),this.runMigrations(i),this.connections.set(e,i),i}close(e){if(e){let t=this.connections.get(e);t&&(t.close(),this.connections.delete(e))}else this.connections.forEach(t=>{t.close()}),this.connections.clear()}exists(e){return Ne.existsSync(this.getDbPath(e))}getDoc(e,t){let s=this.getDb(e).prepare("SELECT data FROM kv_store WHERE key = ?").get(t);return s?JSON.parse(s.data):null}setDoc(e,t,n){let s=this.getDb(e),i=JSON.stringify(n),a=new Date().toISOString();s.prepare("INSERT OR REPLACE INTO kv_store (key, data, updated_at) VALUES (?, ?, ?)").run(t,i,a)}deleteDoc(e,t){this.getDb(e).prepare("DELETE FROM kv_store WHERE key = ?").run(t)}hasDoc(e,t){return this.getDb(e).prepare("SELECT 1 FROM kv_store WHERE key = ?").get(t)!==null}appendEvent(e,t,n,s){let i=this.getDb(e),a=new Date().toISOString();i.prepare("INSERT INTO events (type, task_id, data, timestamp) VALUES (?, ?, ?, ?)").run(t,s??null,JSON.stringify(n),a)}getEvents(e,t,n=100){let s=this.getDb(e);return t?s.prepare("SELECT * FROM events WHERE type = ? ORDER BY id DESC LIMIT ?").all(t,n):s.prepare("SELECT * FROM events ORDER BY id DESC LIMIT ?").all(n)}query(e,t,...n){return this.getDb(e).prepare(t).all(...n)}run(e,t,...n){this.getDb(e).prepare(t).run(...n)}get(e,t,...n){return this.getDb(e).prepare(t).get(...n)??null}transaction(e,t){let n=this.getDb(e);return n.transaction(t)(n)}runMigrations(e){e.run(`
283
+ `)},"up")},{version:5,name:"llm-analysis-table",up:o(r=>{r.run(`
284
+ -- =======================================================================
285
+ -- LLM Analysis: Structured findings from hybrid sync pipeline
286
+ -- Pipeline: CLI (collect) \u2192 LLM (analyze) \u2192 CLI (store)
287
+ -- =======================================================================
288
+ CREATE TABLE llm_analysis (
289
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
290
+ commit_hash TEXT,
291
+ status TEXT NOT NULL DEFAULT 'active',
292
+ analysis TEXT NOT NULL,
293
+ analyzed_at TEXT NOT NULL,
294
+ superseded_at TEXT
295
+ );
296
+
297
+ CREATE INDEX idx_llm_analysis_status ON llm_analysis(status);
298
+ CREATE INDEX idx_llm_analysis_commit ON llm_analysis(commit_hash);
299
+ `)},"up")}],Ae=class{static{o(this,"PrjctDatabase")}connections=new Map;getDbPath(e){return it.join(st.getGlobalProjectPath(e),"prjct.db")}getDb(e){let t=this.connections.get(e);if(t)return t;let s=this.getDbPath(e),n=it.dirname(s);Ne.existsSync(n)||Ne.mkdirSync(n,{recursive:!0});let i=nr(s);return i.run("PRAGMA journal_mode = WAL"),i.run("PRAGMA synchronous = NORMAL"),i.run("PRAGMA cache_size = -2000"),i.run("PRAGMA temp_store = MEMORY"),i.run("PRAGMA mmap_size = 268435456"),this.runMigrations(i),this.connections.set(e,i),i}close(e){if(e){let t=this.connections.get(e);t&&(t.close(),this.connections.delete(e))}else this.connections.forEach(t=>{t.close()}),this.connections.clear()}exists(e){return Ne.existsSync(this.getDbPath(e))}getDoc(e,t){let n=this.getDb(e).prepare("SELECT data FROM kv_store WHERE key = ?").get(t);return n?JSON.parse(n.data):null}setDoc(e,t,s){let n=this.getDb(e),i=JSON.stringify(s),a=new Date().toISOString();n.prepare("INSERT OR REPLACE INTO kv_store (key, data, updated_at) VALUES (?, ?, ?)").run(t,i,a)}deleteDoc(e,t){this.getDb(e).prepare("DELETE FROM kv_store WHERE key = ?").run(t)}hasDoc(e,t){return this.getDb(e).prepare("SELECT 1 FROM kv_store WHERE key = ?").get(t)!==null}appendEvent(e,t,s,n){let i=this.getDb(e),a=new Date().toISOString();i.prepare("INSERT INTO events (type, task_id, data, timestamp) VALUES (?, ?, ?, ?)").run(t,n??null,JSON.stringify(s),a)}getEvents(e,t,s=100){let n=this.getDb(e);return t?n.prepare("SELECT * FROM events WHERE type = ? ORDER BY id DESC LIMIT ?").all(t,s):n.prepare("SELECT * FROM events ORDER BY id DESC LIMIT ?").all(s)}query(e,t,...s){return this.getDb(e).prepare(t).all(...s)}run(e,t,...s){this.getDb(e).prepare(t).run(...s)}get(e,t,...s){return this.getDb(e).prepare(t).get(...s)??null}transaction(e,t){let s=this.getDb(e);return s.transaction(t)(s)}runMigrations(e){e.run(`
284
300
  CREATE TABLE IF NOT EXISTS _migrations (
285
301
  version INTEGER PRIMARY KEY,
286
302
  name TEXT NOT NULL,
287
303
  applied_at TEXT NOT NULL
288
304
  )
289
- `);let t=new Set(e.prepare("SELECT version FROM _migrations").all().map(n=>n.version));for(let n of ir)t.has(n.version)||e.transaction(()=>{n.up(e),e.prepare("INSERT INTO _migrations (version, name, applied_at) VALUES (?, ?, ?)").run(n.version,n.name,new Date().toISOString())})()}getMigrations(e){return this.getDb(e).prepare("SELECT * FROM _migrations ORDER BY version").all()}getSchemaVersion(e){return this.getDb(e).prepare("SELECT MAX(version) as version FROM _migrations").get()?.version??0}},ie=new be;k();var it=1800*1e3,oe=class{static{o(this,"LinearSync")}async pullAll(e){let t=new Date().toISOString(),n=[];try{let s=await p.fetchAssignedIssues({limit:100}),i={};for(let l of s)try{i[l.externalId]=this.toCachedIssue(l,t)}catch(f){n.push({issueId:l.externalId||l.id,error:w(f)})}let a={provider:"linear",lastSync:t,staleAfter:it,issues:i};return ie.setDoc(e,"issues",a),{provider:"linear",fetched:s.length,updated:Object.keys(i).length,errors:n,timestamp:t}}catch(s){return n.push({issueId:"all",error:w(s)}),{provider:"linear",fetched:0,updated:0,errors:n,timestamp:t}}}async getIssue(e,t){let n=this.loadIssues(e);if(n?.issues[t]){let s=n.issues[t],i=new Date(s.fetchedAt).getTime(),a=Date.now(),l=600*1e3;if(a-i<l)return s}try{let s=await p.fetchIssue(t);if(!s)return null;let i=new Date().toISOString(),a=this.toCachedIssue(s,i);return this.updateIssueInCache(e,t,a),a}catch{return n?.issues[t]?n.issues[t]:null}}async getIssueLocal(e,t){return this.loadIssues(e)?.issues[t]||null}async pushStatus(e,t,n){n==="in_progress"?await p.markInProgress(t):n==="done"&&await p.markDone(t);let s=this.loadIssues(e);if(s?.issues[t]){let i=n==="done"?"done":"in_progress";s.issues[t].status=i,s.issues[t].fetchedAt=new Date().toISOString(),this.saveIssues(e,s)}}async isStale(e){let t=this.loadIssues(e);if(!t||!t.lastSync)return!0;let n=new Date(t.lastSync).getTime(),s=Date.now(),i=t.staleAfter||it;return s-n>i}async getSyncStatus(e){let t=this.loadIssues(e);return t?{hasCache:!0,lastSync:t.lastSync||null,issueCount:Object.keys(t.issues).length,isStale:await this.isStale(e)}:{hasCache:!1,lastSync:null,issueCount:0,isStale:!0}}async listCachedIssues(e){let t=this.loadIssues(e);return t?Object.values(t.issues):[]}loadIssues(e){try{return ie.getDoc(e,"issues")}catch{return null}}saveIssues(e,t){ie.setDoc(e,"issues",t)}updateIssueInCache(e,t,n){let s=this.loadIssues(e);s||(s=Me("linear")),s.issues[t]=n,this.saveIssues(e,s)}toCachedIssue(e,t){return{id:e.id,identifier:e.externalId,title:e.title,description:e.description,status:e.status,priority:e.priority,type:e.type,assignee:e.assignee,labels:e.labels,team:e.team,project:e.project,url:e.url,createdAt:e.createdAt,updatedAt:e.updatedAt,fetchedAt:t}}},Y=new oe;k();import P from"chalk";z();import $ from"chalk";var ot=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],or=80,ar={name:"prjct",icon:"\u26A1",signature:"\u26A1 prjct",spinner:{frames:ot,speed:or},cli:{header:o(()=>`${$.cyan.bold("\u26A1")} ${$.cyan("prjct")}`,"header"),footer:o(()=>$.dim("\u26A1 prjct"),"footer"),spin:o((r,e)=>`${$.cyan("\u26A1")} ${$.cyan("prjct")} ${$.cyan(ot[r%10])} ${$.dim(e||"")}`,"spin")},template:{header:"\u26A1 prjct",footer:"\u26A1 prjct"},commitFooter:"Generated with [p/](https://www.prjct.app/)",urls:{website:"https://prjct.app",docs:"https://prjct.app/docs"},getCommitFooter:o((r="claude")=>ne(r).commitFooter,"getCommitFooter"),getSignature:o((r="claude")=>ne(r).signature,"getSignature")},Ae=ar;var ve={SPINNER_MSG:45,DONE_MSG:50,FAIL_MSG:65,WARN_MSG:65,STEP_MSG:35,PROGRESS_TEXT:25,ISSUE_TITLE:50,FALLBACK_TRUNCATE:50,CLEAR_WIDTH:80};var ss=Ae.spinner.frames,is=Ae.spinner.speed,lr={silent:{maxLines:0,maxCharsPerLine:0,showMetrics:!1},minimal:{maxLines:1,maxCharsPerLine:65,showMetrics:!1},compact:{maxLines:4,maxCharsPerLine:80,showMetrics:!0},verbose:{maxLines:1/0,maxCharsPerLine:1/0,showMetrics:!0}},q="compact";function ct(r){q=r}o(ct,"setOutputTier");function De(){return lr[q]}o(De,"getTierConfig");var os={success:P.green("\u2713"),fail:P.red("\u2717"),warn:P.yellow("\u26A0"),info:P.blue("\u2139"),debug:P.dim("\u{1F527}"),bullet:P.dim("\u2022"),arrow:P.dim("\u2192"),check:P.green("\u2713"),cross:P.red("\u2717"),spinner:P.cyan("\u25D0")};var ae=o((r,e)=>{let t=e??(De().maxCharsPerLine||ve.FALLBACK_TRUNCATE);return r&&r.length>t?`${r.slice(0,t-1)}\u2026`:r||""},"truncate");function xe(r,e){let t=e??De().maxLines;if(t===1/0||t===0)return r;let n=r.split(`
290
- `);if(n.length<=t)return r;let s=n.slice(0,t),i=n.length-t;return`${s.join(`
305
+ `);let t=new Set(e.prepare("SELECT version FROM _migrations").all().map(s=>s.version));for(let s of ir)t.has(s.version)||e.transaction(()=>{s.up(e),e.prepare("INSERT INTO _migrations (version, name, applied_at) VALUES (?, ?, ?)").run(s.version,s.name,new Date().toISOString())})()}getMigrations(e){return this.getDb(e).prepare("SELECT * FROM _migrations ORDER BY version").all()}getSchemaVersion(e){return this.getDb(e).prepare("SELECT MAX(version) as version FROM _migrations").get()?.version??0}},ie=new Ae;L();var ot=1800*1e3,oe=class{static{o(this,"LinearSync")}async pullAll(e){let t=new Date().toISOString(),s=[];try{let n=await p.fetchAssignedIssues({limit:100}),i={};for(let l of n)try{i[l.externalId]=this.toCachedIssue(l,t)}catch(f){s.push({issueId:l.externalId||l.id,error:w(f)})}let a={provider:"linear",lastSync:t,staleAfter:ot,issues:i};return ie.setDoc(e,"issues",a),{provider:"linear",fetched:n.length,updated:Object.keys(i).length,errors:s,timestamp:t}}catch(n){return s.push({issueId:"all",error:w(n)}),{provider:"linear",fetched:0,updated:0,errors:s,timestamp:t}}}async getIssue(e,t){let s=this.loadIssues(e);if(s?.issues[t]){let n=s.issues[t],i=new Date(n.fetchedAt).getTime(),a=Date.now(),l=600*1e3;if(a-i<l)return n}try{let n=await p.fetchIssue(t);if(!n)return null;let i=new Date().toISOString(),a=this.toCachedIssue(n,i);return this.updateIssueInCache(e,t,a),a}catch{return s?.issues[t]?s.issues[t]:null}}async getIssueLocal(e,t){return this.loadIssues(e)?.issues[t]||null}async pushStatus(e,t,s){s==="in_progress"?await p.markInProgress(t):s==="done"&&await p.markDone(t);let n=this.loadIssues(e);if(n?.issues[t]){let i=s==="done"?"done":"in_progress";n.issues[t].status=i,n.issues[t].fetchedAt=new Date().toISOString(),this.saveIssues(e,n)}}async isStale(e){let t=this.loadIssues(e);if(!t||!t.lastSync)return!0;let s=new Date(t.lastSync).getTime(),n=Date.now(),i=t.staleAfter||ot;return n-s>i}async getSyncStatus(e){let t=this.loadIssues(e);return t?{hasCache:!0,lastSync:t.lastSync||null,issueCount:Object.keys(t.issues).length,isStale:await this.isStale(e)}:{hasCache:!1,lastSync:null,issueCount:0,isStale:!0}}async listCachedIssues(e){let t=this.loadIssues(e);return t?Object.values(t.issues):[]}loadIssues(e){try{return ie.getDoc(e,"issues")}catch{return null}}saveIssues(e,t){ie.setDoc(e,"issues",t)}updateIssueInCache(e,t,s){let n=this.loadIssues(e);n||(n=Me("linear")),n.issues[t]=s,this.saveIssues(e,n)}toCachedIssue(e,t){return{id:e.id,identifier:e.externalId,title:e.title,description:e.description,status:e.status,priority:e.priority,type:e.type,assignee:e.assignee,labels:e.labels,team:e.team,project:e.project,url:e.url,createdAt:e.createdAt,updatedAt:e.updatedAt,fetchedAt:t}}},Y=new oe;L();import P from"chalk";z();import $ from"chalk";var at=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],or=80,ar={name:"prjct",icon:"\u26A1",signature:"\u26A1 prjct",spinner:{frames:at,speed:or},cli:{header:o(()=>`${$.cyan.bold("\u26A1")} ${$.cyan("prjct")}`,"header"),footer:o(()=>$.dim("\u26A1 prjct"),"footer"),spin:o((r,e)=>`${$.cyan("\u26A1")} ${$.cyan("prjct")} ${$.cyan(at[r%10])} ${$.dim(e||"")}`,"spin")},template:{header:"\u26A1 prjct",footer:"\u26A1 prjct"},commitFooter:"Generated with [p/](https://www.prjct.app/)",urls:{website:"https://prjct.app",docs:"https://prjct.app/docs"},getCommitFooter:o((r="claude")=>se(r).commitFooter,"getCommitFooter"),getSignature:o((r="claude")=>se(r).signature,"getSignature")},be=ar;var xe={SPINNER_MSG:45,DONE_MSG:50,FAIL_MSG:65,WARN_MSG:65,STEP_MSG:35,PROGRESS_TEXT:25,ISSUE_TITLE:50,FALLBACK_TRUNCATE:50,CLEAR_WIDTH:80};var sn=be.spinner.frames,nn=be.spinner.speed,lr={silent:{maxLines:0,maxCharsPerLine:0,showMetrics:!1},minimal:{maxLines:1,maxCharsPerLine:65,showMetrics:!1},compact:{maxLines:4,maxCharsPerLine:80,showMetrics:!0},verbose:{maxLines:1/0,maxCharsPerLine:1/0,showMetrics:!0}},q="compact";function lt(r){q=r}o(lt,"setOutputTier");function De(){return lr[q]}o(De,"getTierConfig");var on={success:P.green("\u2713"),fail:P.red("\u2717"),warn:P.yellow("\u26A0"),info:P.blue("\u2139"),debug:P.dim("\u{1F527}"),bullet:P.dim("\u2022"),arrow:P.dim("\u2192"),check:P.green("\u2713"),cross:P.red("\u2717"),spinner:P.cyan("\u25D0")};var ae=o((r,e)=>{let t=e??(De().maxCharsPerLine||xe.FALLBACK_TRUNCATE);return r&&r.length>t?`${r.slice(0,t-1)}\u2026`:r||""},"truncate");function ve(r,e){let t=e??De().maxLines;if(t===1/0||t===0)return r;let s=r.split(`
306
+ `);if(s.length<=t)return r;let n=s.slice(0,t),i=s.length-t;return`${n.join(`
291
307
  `)}
292
- ${P.dim(`...${i} more lines`)}`}o(xe,"limitLines");function lt(r){let e=De();if(q==="silent")return"";if(q==="verbose")return JSON.stringify(r,null,2);if(typeof r!="object"||r===null)return ae(String(r),e.maxCharsPerLine);let t=r;if("identifier"in t&&"title"in t){let i=[];return i.push(`${t.identifier}: ${ae(String(t.title),e.maxCharsPerLine-10)}`),t.status&&i.push(`Status: ${t.status}`),t.priority&&t.priority!=="none"&&i.push(`Priority: ${t.priority}`),t.url&&q==="compact"&&i.push(P.dim(String(t.url))),xe(i.join(`
293
- `),e.maxLines)}if("issues"in t&&Array.isArray(t.issues)){let i=t.issues,a=i.slice(0,e.maxLines).map(l=>{let f=l.priority&&l.priority!=="none"?` [${l.priority}]`:"";return`${l.identifier} ${ae(String(l.title),ve.ISSUE_TITLE)}${f}`});return i.length>e.maxLines&&a.push(P.dim(`...${i.length-e.maxLines} more`)),a.join(`
294
- `)}let s=["id","name","title","status","message","success","error"].filter(i=>i in t);return s.length>0?xe(s.map(i=>`${i}: ${ae(String(t[i]),e.maxCharsPerLine-i.length-2)}`).join(`
295
- `),e.maxLines):xe(JSON.stringify(r,null,2),e.maxLines)}o(lt,"formatForHuman");k();te();Z();import Ce from"node:fs/promises";import ur from"node:os";import ut from"node:path";function dt(r){return ut.join(ur.homedir(),".prjct-cli","projects",r,"config","credentials.json")}o(dt,"getCredentialsPath");async function _(r){let e=dt(r);if(!await m(e))return{};try{return JSON.parse(await Ce.readFile(e,"utf-8"))}catch(t){return console.error("[project-credentials] Failed to read credentials:",w(t)),{}}}o(_,"getProjectCredentials");async function pt(r,e){let t=dt(r),n=ut.dirname(t);await m(n)||await Ce.mkdir(n,{recursive:!0});let s=await _(r);s.linear=e,await Ce.writeFile(t,JSON.stringify(s,null,2))}o(pt,"setLinearCredentials");async function ke(r){let e=await _(r);return e.linear?.apiKey?e.linear.apiKey:X("linear-api-key")}o(ke,"getLinearApiKey");async function mt(r){if((await _(r)).linear?.apiKey)return"project";let{getCredentialWithSource:t}=await Promise.resolve().then(()=>(Z(),_e)),n=await t("linear-api-key");return n.value?n.source==="keychain"?"keychain":"env":"none"}o(mt,"getCredentialSource");var C=process.argv.slice(2),ce=C.indexOf("--project"),T=null;ce!==-1&&C[ce+1]&&(T=C[ce+1],C.splice(ce,2));var ft=C.indexOf("--json"),O=ft!==-1;O&&C.splice(ft,1);var ht=C.indexOf("--verbose"),dr=ht!==-1;dr&&(C.splice(ht,1),ct("verbose"));var[gt,...y]=C;function h(r){console.log(O?JSON.stringify(r,null,2):lt(r))}o(h,"output");function d(r,e=1){console.error(O?JSON.stringify({error:r}):`Error: ${r}`),process.exit(e)}o(d,"error");async function A(){T||d("No --project specified. Usage: linear.ts --project <projectId> <command>");let r=await ke(T);r||d("Linear not configured. Run: p. linear setup");let e=await _(T);await p.initializeFromApiKey(r,e.linear?.teamId)}o(A,"initFromProject");async function pr(){try{switch(gt){case"setup":{T||d("--project required for setup");let r=y[0],e=y[1];r||d("API key required. Usage: setup <apiKey> [teamId]"),await p.initializeFromApiKey(r,e);let t=await p.getTeams();t.length===0&&d("No teams found. Check your API key permissions.");let n=e,s;if(!n&&t.length===1)n=t[0].id,s=t[0].key;else if(n){let i=t.find(a=>a.id===n||a.key===n);i&&(n=i.id,s=i.key)}await pt(T,{apiKey:r,teamId:n,teamKey:s,setupAt:new Date().toISOString()}),h({success:!0,teams:t,defaultTeam:n?{id:n,key:s}:null});break}case"list":{await A();let r=y[0]?parseInt(y[0],10):20,e=await _(T),t;e.linear?.teamId?t=await p.fetchTeamIssues(e.linear.teamId,{limit:r}):t=await p.fetchAssignedIssues({limit:r});let n=t.map(s=>({id:s.id,identifier:s.externalId,title:s.title,status:s.status,priority:s.priority,url:s.url}));if(O)h({count:t.length,issues:n});else{console.log(`Your issues (${t.length}):`);for(let s of n.slice(0,10)){let i=s.priority&&s.priority!=="none"?` [${s.priority}]`:"";console.log(` ${s.identifier} ${s.title.slice(0,50)}${i}`)}t.length>10&&console.log(` ...${t.length-10} more`)}break}case"list-team":{await A();let r=y[0],e=y[1]?parseInt(y[1],10):20;r||d("Team ID required. Usage: list-team <teamId> [limit]");let t=await p.fetchTeamIssues(r,{limit:e});h({count:t.length,issues:t.map(n=>({id:n.id,identifier:n.externalId,title:n.title,status:n.status,priority:n.priority,url:n.url}))});break}case"get":{await A();let r=y[0];r||d("Issue ID required. Usage: get <id>");let e=await p.fetchIssue(r);if(e||d(`Issue not found: ${r}`),O)h(e);else{if(console.log(`${e.externalId}: ${e.title}`),console.log(`Status: ${e.status} | Priority: ${e.priority||"none"}`),e.description){let t=e.description.slice(0,200);console.log(`
308
+ ${P.dim(`...${i} more lines`)}`}o(ve,"limitLines");function ut(r){let e=De();if(q==="silent")return"";if(q==="verbose")return JSON.stringify(r,null,2);if(typeof r!="object"||r===null)return ae(String(r),e.maxCharsPerLine);let t=r;if("identifier"in t&&"title"in t){let i=[];return i.push(`${t.identifier}: ${ae(String(t.title),e.maxCharsPerLine-10)}`),t.status&&i.push(`Status: ${t.status}`),t.priority&&t.priority!=="none"&&i.push(`Priority: ${t.priority}`),t.url&&q==="compact"&&i.push(P.dim(String(t.url))),ve(i.join(`
309
+ `),e.maxLines)}if("issues"in t&&Array.isArray(t.issues)){let i=t.issues,a=i.slice(0,e.maxLines).map(l=>{let f=l.priority&&l.priority!=="none"?` [${l.priority}]`:"";return`${l.identifier} ${ae(String(l.title),xe.ISSUE_TITLE)}${f}`});return i.length>e.maxLines&&a.push(P.dim(`...${i.length-e.maxLines} more`)),a.join(`
310
+ `)}let n=["id","name","title","status","message","success","error"].filter(i=>i in t);return n.length>0?ve(n.map(i=>`${i}: ${ae(String(t[i]),e.maxCharsPerLine-i.length-2)}`).join(`
311
+ `),e.maxLines):ve(JSON.stringify(r,null,2),e.maxLines)}o(ut,"formatForHuman");L();te();Z();import Ce from"node:fs/promises";import ur from"node:os";import dt from"node:path";function pt(r){return dt.join(ur.homedir(),".prjct-cli","projects",r,"config","credentials.json")}o(pt,"getCredentialsPath");async function _(r){let e=pt(r);if(!await m(e))return{};try{return JSON.parse(await Ce.readFile(e,"utf-8"))}catch(t){return console.error("[project-credentials] Failed to read credentials:",w(t)),{}}}o(_,"getProjectCredentials");async function mt(r,e){let t=pt(r),s=dt.dirname(t);await m(s)||await Ce.mkdir(s,{recursive:!0});let n=await _(r);n.linear=e,await Ce.writeFile(t,JSON.stringify(n,null,2))}o(mt,"setLinearCredentials");async function Le(r){let e=await _(r);return e.linear?.apiKey?e.linear.apiKey:X("linear-api-key")}o(Le,"getLinearApiKey");async function gt(r){if((await _(r)).linear?.apiKey)return"project";let{getCredentialWithSource:t}=await Promise.resolve().then(()=>(Z(),_e)),s=await t("linear-api-key");return s.value?s.source==="keychain"?"keychain":"env":"none"}o(gt,"getCredentialSource");var C=process.argv.slice(2),ce=C.indexOf("--project"),T=null;ce!==-1&&C[ce+1]&&(T=C[ce+1],C.splice(ce,2));var ht=C.indexOf("--json"),O=ht!==-1;O&&C.splice(ht,1);var Tt=C.indexOf("--verbose"),dr=Tt!==-1;dr&&(C.splice(Tt,1),lt("verbose"));var[ft,...y]=C;function h(r){console.log(O?JSON.stringify(r,null,2):ut(r))}o(h,"output");function d(r,e=1){console.error(O?JSON.stringify({error:r}):`Error: ${r}`),process.exit(e)}o(d,"error");async function b(){T||d("No --project specified. Usage: linear.ts --project <projectId> <command>");let r=await Le(T);r||d("Linear not configured. Run: p. linear setup");let e=await _(T);await p.initializeFromApiKey(r,e.linear?.teamId)}o(b,"initFromProject");async function pr(){try{switch(ft){case"setup":{T||d("--project required for setup");let r=y[0],e=y[1];r||d("API key required. Usage: setup <apiKey> [teamId]"),await p.initializeFromApiKey(r,e);let t=await p.getTeams();t.length===0&&d("No teams found. Check your API key permissions.");let s=e,n;if(!s&&t.length===1)s=t[0].id,n=t[0].key;else if(s){let i=t.find(a=>a.id===s||a.key===s);i&&(s=i.id,n=i.key)}await mt(T,{apiKey:r,teamId:s,teamKey:n,setupAt:new Date().toISOString()}),h({success:!0,teams:t,defaultTeam:s?{id:s,key:n}:null});break}case"list":{await b();let r=y[0]?parseInt(y[0],10):20,e=await _(T),t;e.linear?.teamId?t=await p.fetchTeamIssues(e.linear.teamId,{limit:r}):t=await p.fetchAssignedIssues({limit:r});let s=t.map(n=>({id:n.id,identifier:n.externalId,title:n.title,status:n.status,priority:n.priority,url:n.url}));if(O)h({count:t.length,issues:s});else{console.log(`Your issues (${t.length}):`);for(let n of s.slice(0,10)){let i=n.priority&&n.priority!=="none"?` [${n.priority}]`:"";console.log(` ${n.identifier} ${n.title.slice(0,50)}${i}`)}t.length>10&&console.log(` ...${t.length-10} more`)}break}case"list-team":{await b();let r=y[0],e=y[1]?parseInt(y[1],10):20;r||d("Team ID required. Usage: list-team <teamId> [limit]");let t=await p.fetchTeamIssues(r,{limit:e});h({count:t.length,issues:t.map(s=>({id:s.id,identifier:s.externalId,title:s.title,status:s.status,priority:s.priority,url:s.url}))});break}case"get":{await b();let r=y[0];r||d("Issue ID required. Usage: get <id>");let e=await p.fetchIssue(r);if(e||d(`Issue not found: ${r}`),O)h(e);else{if(console.log(`${e.externalId}: ${e.title}`),console.log(`Status: ${e.status} | Priority: ${e.priority||"none"}`),e.description){let t=e.description.slice(0,200);console.log(`
296
312
  ${t}${e.description.length>200?"...":""}`)}console.log(`
297
- ${e.url}`)}break}case"get-local":{T||d("--project required for get-local");let r=y[0];r||d("Issue ID required. Usage: get-local <id>");let e=await Y.getIssueLocal(T,r);e||d(`Issue not in local cache: ${r}. Run 'sync' first.`),h(e);break}case"sync":{T||d("--project required for sync"),await A();let r=await Y.pullAll(T);h({success:r.errors.length===0,...r});break}case"sync-status":{T||d("--project required for sync-status");let r=await Y.getSyncStatus(T);h(r);break}case"create":{await A();let r=y[0];r||d(`JSON input required. Usage: create '{"title":"...", "teamId":"..."}'`);let e;try{e=JSON.parse(r)}catch{d(`Invalid JSON: ${r}`)}if(e.title||d("title is required"),!e.teamId){let n=await _(T);n.linear?.teamId?e.teamId=n.linear.teamId:d("teamId is required (no default team configured)")}let t=await p.createIssue(e);h(t);break}case"update":{await A();let r=y[0],e=y[1];r||d(`Issue ID required. Usage: update <id> '{"description":"..."}'`),e||d(`JSON input required. Usage: update <id> '{"description":"..."}'`);let t;try{t=JSON.parse(e)}catch{d(`Invalid JSON: ${e}`)}let n=await p.updateIssue(r,t);h(n);break}case"start":{await A();let r=y[0];r||d("Issue ID required. Usage: start <id>"),await p.markInProgress(r),h({success:!0,id:r,status:"in_progress"});break}case"done":{await A();let r=y[0];r||d("Issue ID required. Usage: done <id>"),await p.markDone(r),h({success:!0,id:r,status:"done"});break}case"comment":{await A();let r=y[0],e=y.slice(1).join(" ");r||d("Issue ID required. Usage: comment <id> <text>"),e||d("Comment text required. Usage: comment <id> <text>"),await p.addComment(r,e),h({success:!0,id:r});break}case"teams":{await A();let r=await p.getTeams();h({count:r.length,teams:r});break}case"projects":{await A();let r=await p.getProjects();h({count:r.length,projects:r});break}case"status":{T||d("--project required for status");let r=await mt(T),e=await ke(T),t=await _(T);if(!e){O?h({configured:!1,source:"none",message:"Linear not configured"}):(console.log("Linear: Not configured"),console.log("Run: p. linear setup"));break}try{await p.initializeFromApiKey(e,t.linear?.teamId);let n=await p.getTeams();O?h({configured:!0,source:r,teamId:t.linear?.teamId,teamKey:t.linear?.teamKey,teamsAvailable:n.length}):(console.log("Linear: Connected"),t.linear?.teamKey&&console.log(`Team: ${t.linear.teamKey}`),console.log(`Teams: ${n.length} available`))}catch(n){O?h({configured:!0,source:r,connectionError:w(n)}):(console.log("Linear: Connection error"),console.log(`Error: ${w(n)}`))}break}case"help":case"--help":case"-h":case void 0:{h({usage:"linear.ts --project <projectId> <command> [args...]",commands:{setup:"setup <apiKey> [teamId] - Store API key",list:"list [limit] - List my assigned issues","list-team":"list-team <teamId> [limit] - List team issues",get:"get <id> - Get issue by ID or identifier","get-local":"get-local <id> - Get from local cache (no API)",sync:"sync - Pull all assigned issues to local storage","sync-status":"sync-status - Check local cache status",create:"create <json> - Create issue",update:"update <id> <json> - Update issue",start:"start <id> - Mark as in progress",done:"done <id> - Mark as done",comment:"comment <id> <text> - Add comment",teams:"teams - List available teams",projects:"projects - List available projects",status:"status - Check connection"}});break}default:d(`Unknown command: ${gt}. Use --help to see available commands.`)}}catch(r){d(w(r))}}o(pr,"main");pr();
313
+ ${e.url}`)}break}case"get-local":{T||d("--project required for get-local");let r=y[0];r||d("Issue ID required. Usage: get-local <id>");let e=await Y.getIssueLocal(T,r);e||d(`Issue not in local cache: ${r}. Run 'sync' first.`),h(e);break}case"sync":{T||d("--project required for sync"),await b();let r=await Y.pullAll(T);h({success:r.errors.length===0,...r});break}case"sync-status":{T||d("--project required for sync-status");let r=await Y.getSyncStatus(T);h(r);break}case"create":{await b();let r=y[0];r||d(`JSON input required. Usage: create '{"title":"...", "teamId":"..."}'`);let e;try{e=JSON.parse(r)}catch{d(`Invalid JSON: ${r}`)}if(e.title||d("title is required"),!e.teamId){let s=await _(T);s.linear?.teamId?e.teamId=s.linear.teamId:d("teamId is required (no default team configured)")}let t=await p.createIssue(e);h(t);break}case"update":{await b();let r=y[0],e=y[1];r||d(`Issue ID required. Usage: update <id> '{"description":"..."}'`),e||d(`JSON input required. Usage: update <id> '{"description":"..."}'`);let t;try{t=JSON.parse(e)}catch{d(`Invalid JSON: ${e}`)}let s=await p.updateIssue(r,t);h(s);break}case"start":{await b();let r=y[0];r||d("Issue ID required. Usage: start <id>"),await p.markInProgress(r),h({success:!0,id:r,status:"in_progress"});break}case"done":{await b();let r=y[0];r||d("Issue ID required. Usage: done <id>"),await p.markDone(r),h({success:!0,id:r,status:"done"});break}case"comment":{await b();let r=y[0],e=y.slice(1).join(" ");r||d("Issue ID required. Usage: comment <id> <text>"),e||d("Comment text required. Usage: comment <id> <text>"),await p.addComment(r,e),h({success:!0,id:r});break}case"teams":{await b();let r=await p.getTeams();h({count:r.length,teams:r});break}case"projects":{await b();let r=await p.getProjects();h({count:r.length,projects:r});break}case"status":{T||d("--project required for status");let r=await gt(T),e=await Le(T),t=await _(T);if(!e){O?h({configured:!1,source:"none",message:"Linear not configured"}):(console.log("Linear: Not configured"),console.log("Run: p. linear setup"));break}try{await p.initializeFromApiKey(e,t.linear?.teamId);let s=await p.getTeams();O?h({configured:!0,source:r,teamId:t.linear?.teamId,teamKey:t.linear?.teamKey,teamsAvailable:s.length}):(console.log("Linear: Connected"),t.linear?.teamKey&&console.log(`Team: ${t.linear.teamKey}`),console.log(`Teams: ${s.length} available`))}catch(s){O?h({configured:!0,source:r,connectionError:w(s)}):(console.log("Linear: Connection error"),console.log(`Error: ${w(s)}`))}break}case"help":case"--help":case"-h":case void 0:{h({usage:"linear.ts --project <projectId> <command> [args...]",commands:{setup:"setup <apiKey> [teamId] - Store API key",list:"list [limit] - List my assigned issues","list-team":"list-team <teamId> [limit] - List team issues",get:"get <id> - Get issue by ID or identifier","get-local":"get-local <id> - Get from local cache (no API)",sync:"sync - Pull all assigned issues to local storage","sync-status":"sync-status - Check local cache status",create:"create <json> - Create issue",update:"update <id> <json> - Update issue",start:"start <id> - Mark as in progress",done:"done <id> - Mark as done",comment:"comment <id> <text> - Add comment",teams:"teams - List available teams",projects:"projects - List available projects",status:"status - Check connection"}});break}default:d(`Unknown command: ${ft}. Use --help to see available commands.`)}}catch(r){d(w(r))}}o(pr,"main");pr();