@xship/cli 0.0.143 → 0.0.144

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.
@@ -10,7 +10,7 @@
10
10
  "claude": [
11
11
  {
12
12
  "description": "100 万上下文 | 高强度推理 | 长时 Agent | SWE-bench Verified 95%",
13
- "group": "grp_6eg2dq9ywgrg",
13
+ "group": "grp_rld6af0zorqd",
14
14
  "group_name": "",
15
15
  "hidden": false,
16
16
  "id": "claude-fable-5",
@@ -19,7 +19,7 @@
19
19
  },
20
20
  {
21
21
  "description": "100 万上下文 | 12.8 万输出 | 自适应思考常开 | 长时 Agent 与多步研究",
22
- "group": "grp_6eg2dq9ywgrg",
22
+ "group": "grp_pzxnceygmqlp",
23
23
  "group_name": "",
24
24
  "hidden": false,
25
25
  "id": "claude-fable-5-1",
@@ -28,7 +28,7 @@
28
28
  },
29
29
  {
30
30
  "description": "轻量档 | 低延迟 | 高频短任务",
31
- "group": "grp_6lyxfgbs440g",
31
+ "group": "grp_6co8aqwefsoh",
32
32
  "group_name": "",
33
33
  "hidden": false,
34
34
  "id": "claude-haiku-4-5-20251001",
@@ -55,7 +55,7 @@
55
55
  },
56
56
  {
57
57
  "description": "100 万上下文 | 推理 | 编程 | 长上下文不加价",
58
- "group": "grp_pzxnceygmqlp",
58
+ "group": "grp_6lyxfgbs440g",
59
59
  "group_name": "",
60
60
  "hidden": false,
61
61
  "id": "claude-opus-4-7",
@@ -64,7 +64,7 @@
64
64
  },
65
65
  {
66
66
  "description": "100 万上下文 | 推理 | 编程 | 长上下文不加价",
67
- "group": "grp_6lyxfgbs440g",
67
+ "group": "grp_6eg2dq9ywgrg",
68
68
  "group_name": "",
69
69
  "hidden": false,
70
70
  "id": "claude-opus-4-8",
@@ -73,7 +73,7 @@
73
73
  },
74
74
  {
75
75
  "description": "100 万上下文 | 12.8 万输出 | 自适应思考五档 | Agent 编程",
76
- "group": "grp_6lyxfgbs440g",
76
+ "group": "grp_6eg2dq9ywgrg",
77
77
  "group_name": "",
78
78
  "hidden": false,
79
79
  "id": "claude-opus-5",
@@ -91,7 +91,7 @@
91
91
  },
92
92
  {
93
93
  "description": "100 万上下文 | Agent 编程 | 长上下文不加价",
94
- "group": "grp_rld6af0zorqd",
94
+ "group": "grp_irydsgijuckh",
95
95
  "group_name": "",
96
96
  "hidden": false,
97
97
  "id": "claude-sonnet-4-6",
@@ -100,7 +100,7 @@
100
100
  },
101
101
  {
102
102
  "description": "100 万上下文 | Agent 编程 | 工具调用 | 知识工作",
103
- "group": "grp_irydsgijuckh",
103
+ "group": "grp_6eg2dq9ywgrg",
104
104
  "group_name": "",
105
105
  "hidden": false,
106
106
  "id": "claude-sonnet-5",
@@ -109,7 +109,7 @@
109
109
  },
110
110
  {
111
111
  "description": "100 万上下文 | 12.8 万输出 | Agent 编程 | 知识工作",
112
- "group": "grp_6co8aqwefsoh",
112
+ "group": "grp_6eg2dq9ywgrg",
113
113
  "group_name": "",
114
114
  "hidden": false,
115
115
  "id": "claude-sonnet-5-5",
@@ -120,7 +120,7 @@
120
120
  "codex": [
121
121
  {
122
122
  "description": "105 万上下文 | 12.8 万输出 | 大批量低成本档",
123
- "group": "grp_bsbtt432saoq",
123
+ "group": "grp_irydsgijuckh",
124
124
  "group_name": "",
125
125
  "hidden": false,
126
126
  "id": "gpt-5.6-luna",
@@ -129,7 +129,7 @@
129
129
  },
130
130
  {
131
131
  "description": "105 万上下文 | 12.8 万输出 | 前沿档",
132
- "group": "grp_irydsgijuckh",
132
+ "group": "grp_squ2qzjnehps",
133
133
  "group_name": "",
134
134
  "hidden": false,
135
135
  "id": "gpt-5.6-sol",
@@ -138,7 +138,7 @@
138
138
  },
139
139
  {
140
140
  "description": "105 万上下文 | 12.8 万输出 | 均衡生产档",
141
- "group": "grp_bsbtt432saoq",
141
+ "group": "grp_squ2qzjnehps",
142
142
  "group_name": "",
143
143
  "hidden": false,
144
144
  "id": "gpt-5.6-terra",
@@ -147,7 +147,7 @@
147
147
  },
148
148
  {
149
149
  "description": "105 万上下文 | 12.8 万输出 | 思考强度至 max | 计算机操作 / 编码 / 科学基准接近饱和",
150
- "group": "grp_mb5v069lpnze",
150
+ "group": "grp_6co8aqwefsoh",
151
151
  "group_name": "",
152
152
  "hidden": false,
153
153
  "id": "gpt-6-astra",
@@ -165,7 +165,7 @@
165
165
  },
166
166
  {
167
167
  "description": "105 万上下文 | 12.8 万输出 | 复杂编程与 Agent 工作流",
168
- "group": "grp_mb5v069lpnze",
168
+ "group": "grp_irydsgijuckh",
169
169
  "group_name": "",
170
170
  "hidden": false,
171
171
  "id": "gpt-6-sol",
@@ -203,7 +203,7 @@
203
203
  },
204
204
  {
205
205
  "description": "约 100 万上下文 | 深度推理 | 长文档一致性",
206
- "group": "grp_3pi5kyqkp51b",
206
+ "group": "grp_z5khwusxuh2j",
207
207
  "group_name": "",
208
208
  "hidden": false,
209
209
  "id": "gemini-3-pro",
@@ -266,7 +266,7 @@
266
266
  },
267
267
  {
268
268
  "description": "推理与编码 | HLE-Verified 54.9% | 长文档工作流",
269
- "group": "grp_3pi5kyqkp51b",
269
+ "group": "grp_z5khwusxuh2j",
270
270
  "group_name": "",
271
271
  "hidden": false,
272
272
  "id": "gemini-3.8-flash",
@@ -295,7 +295,7 @@
295
295
  "grok": [
296
296
  {
297
297
  "description": "50 万上下文 | 1.5 万亿参数 MoE | 编码与 Agent",
298
- "group": "grp_irydsgijuckh",
298
+ "group": "grp_l34dwliv4yas",
299
299
  "group_name": "",
300
300
  "hidden": false,
301
301
  "id": "grok-4.5",
@@ -10,7 +10,7 @@
10
10
  "claude": [
11
11
  {
12
12
  "description": "100 万上下文 | 高强度推理 | 长时 Agent | SWE-bench Verified 95%",
13
- "group": "grp_6eg2dq9ywgrg",
13
+ "group": "grp_rld6af0zorqd",
14
14
  "group_name": "",
15
15
  "hidden": false,
16
16
  "id": "claude-fable-5",
@@ -19,7 +19,7 @@
19
19
  },
20
20
  {
21
21
  "description": "100 万上下文 | 12.8 万输出 | 自适应思考常开 | 长时 Agent 与多步研究",
22
- "group": "grp_6eg2dq9ywgrg",
22
+ "group": "grp_pzxnceygmqlp",
23
23
  "group_name": "",
24
24
  "hidden": false,
25
25
  "id": "claude-fable-5-1",
@@ -28,7 +28,7 @@
28
28
  },
29
29
  {
30
30
  "description": "轻量档 | 低延迟 | 高频短任务",
31
- "group": "grp_6lyxfgbs440g",
31
+ "group": "grp_6co8aqwefsoh",
32
32
  "group_name": "",
33
33
  "hidden": false,
34
34
  "id": "claude-haiku-4-5-20251001",
@@ -55,7 +55,7 @@
55
55
  },
56
56
  {
57
57
  "description": "100 万上下文 | 推理 | 编程 | 长上下文不加价",
58
- "group": "grp_pzxnceygmqlp",
58
+ "group": "grp_6lyxfgbs440g",
59
59
  "group_name": "",
60
60
  "hidden": false,
61
61
  "id": "claude-opus-4-7",
@@ -64,7 +64,7 @@
64
64
  },
65
65
  {
66
66
  "description": "100 万上下文 | 推理 | 编程 | 长上下文不加价",
67
- "group": "grp_6lyxfgbs440g",
67
+ "group": "grp_6eg2dq9ywgrg",
68
68
  "group_name": "",
69
69
  "hidden": false,
70
70
  "id": "claude-opus-4-8",
@@ -73,7 +73,7 @@
73
73
  },
74
74
  {
75
75
  "description": "100 万上下文 | 12.8 万输出 | 自适应思考五档 | Agent 编程",
76
- "group": "grp_6lyxfgbs440g",
76
+ "group": "grp_6eg2dq9ywgrg",
77
77
  "group_name": "",
78
78
  "hidden": false,
79
79
  "id": "claude-opus-5",
@@ -91,7 +91,7 @@
91
91
  },
92
92
  {
93
93
  "description": "100 万上下文 | Agent 编程 | 长上下文不加价",
94
- "group": "grp_rld6af0zorqd",
94
+ "group": "grp_irydsgijuckh",
95
95
  "group_name": "",
96
96
  "hidden": false,
97
97
  "id": "claude-sonnet-4-6",
@@ -100,7 +100,7 @@
100
100
  },
101
101
  {
102
102
  "description": "100 万上下文 | Agent 编程 | 工具调用 | 知识工作",
103
- "group": "grp_irydsgijuckh",
103
+ "group": "grp_6eg2dq9ywgrg",
104
104
  "group_name": "",
105
105
  "hidden": false,
106
106
  "id": "claude-sonnet-5",
@@ -109,7 +109,7 @@
109
109
  },
110
110
  {
111
111
  "description": "100 万上下文 | 12.8 万输出 | Agent 编程 | 知识工作",
112
- "group": "grp_6co8aqwefsoh",
112
+ "group": "grp_6eg2dq9ywgrg",
113
113
  "group_name": "",
114
114
  "hidden": false,
115
115
  "id": "claude-sonnet-5-5",
@@ -120,7 +120,7 @@
120
120
  "codex": [
121
121
  {
122
122
  "description": "105 万上下文 | 12.8 万输出 | 大批量低成本档",
123
- "group": "grp_bsbtt432saoq",
123
+ "group": "grp_irydsgijuckh",
124
124
  "group_name": "",
125
125
  "hidden": false,
126
126
  "id": "gpt-5.6-luna",
@@ -129,7 +129,7 @@
129
129
  },
130
130
  {
131
131
  "description": "105 万上下文 | 12.8 万输出 | 前沿档",
132
- "group": "grp_irydsgijuckh",
132
+ "group": "grp_squ2qzjnehps",
133
133
  "group_name": "",
134
134
  "hidden": false,
135
135
  "id": "gpt-5.6-sol",
@@ -138,7 +138,7 @@
138
138
  },
139
139
  {
140
140
  "description": "105 万上下文 | 12.8 万输出 | 均衡生产档",
141
- "group": "grp_bsbtt432saoq",
141
+ "group": "grp_squ2qzjnehps",
142
142
  "group_name": "",
143
143
  "hidden": false,
144
144
  "id": "gpt-5.6-terra",
@@ -147,7 +147,7 @@
147
147
  },
148
148
  {
149
149
  "description": "105 万上下文 | 12.8 万输出 | 思考强度至 max | 计算机操作 / 编码 / 科学基准接近饱和",
150
- "group": "grp_mb5v069lpnze",
150
+ "group": "grp_6co8aqwefsoh",
151
151
  "group_name": "",
152
152
  "hidden": false,
153
153
  "id": "gpt-6-astra",
@@ -165,7 +165,7 @@
165
165
  },
166
166
  {
167
167
  "description": "105 万上下文 | 12.8 万输出 | 复杂编程与 Agent 工作流",
168
- "group": "grp_mb5v069lpnze",
168
+ "group": "grp_irydsgijuckh",
169
169
  "group_name": "",
170
170
  "hidden": false,
171
171
  "id": "gpt-6-sol",
@@ -203,7 +203,7 @@
203
203
  },
204
204
  {
205
205
  "description": "约 100 万上下文 | 深度推理 | 长文档一致性",
206
- "group": "grp_3pi5kyqkp51b",
206
+ "group": "grp_z5khwusxuh2j",
207
207
  "group_name": "",
208
208
  "hidden": false,
209
209
  "id": "gemini-3-pro",
@@ -266,7 +266,7 @@
266
266
  },
267
267
  {
268
268
  "description": "推理与编码 | HLE-Verified 54.9% | 长文档工作流",
269
- "group": "grp_3pi5kyqkp51b",
269
+ "group": "grp_z5khwusxuh2j",
270
270
  "group_name": "",
271
271
  "hidden": false,
272
272
  "id": "gemini-3.8-flash",
@@ -295,7 +295,7 @@
295
295
  "grok": [
296
296
  {
297
297
  "description": "50 万上下文 | 1.5 万亿参数 MoE | 编码与 Agent",
298
- "group": "grp_irydsgijuckh",
298
+ "group": "grp_l34dwliv4yas",
299
299
  "group_name": "",
300
300
  "hidden": false,
301
301
  "id": "grok-4.5",
@@ -1 +1 @@
1
- import{execFileSync as e}from"child_process";import{createHash as t}from"crypto";import{createReadStream as r,createWriteStream as s,existsSync as o,readdirSync as i,readFileSync as n}from"fs";import{copyFile as a,mkdir as l,readFile as c,rename as u,rm as f,writeFile as p}from"fs/promises";import{isAbsolute as d,join as h,normalize as m,sep as w}from"path";import{Readable as g,Writable as b}from"stream";import{pipeline as D}from"stream/promises";import*as y from"zlib";import{logger as v}from"../../utils/logger.js";import{brandEnv as k}from"../brand.js";import{downloadNativeBinary as $,nativeLayout as C,nativePlatformKey as N}from"./claude-native-mirror.js";import{WINDOWS_PACKAGE_FAMILIES as x}from"./desktop-process.js";import{toolHome as A}from"./types.js";export function readDesktopCliPin(e,t,r=!1){const s=e.indexOf('claude-code-releases","sdkWrapperVersion"');if(s<0)return null;const o=e.lastIndexOf("JSON.parse('",s),i=e.indexOf("')",s);if(o<0||i<0)return null;try{const s=JSON.parse(e.subarray(o+12,i).toString("utf-8")),n="string"==typeof s.version?s.version:"",a=s.manifest?.platforms?.[t],l=r?a?.bundle?.checksum:a?.checksum;return/^\d+\.\d+\.\d+$/.test(n)&&"string"==typeof l&&/^[0-9a-f]{64}$/.test(l)?{version:n,checksum:l}:null}catch{return null}}class L extends b{dest;buffer=Buffer.alloc(0);remaining=0;padding=0;file=null;longName=null;collectingLongName=null;constructor(e){super(),this.dest=e}_write(e,t,r){this.buffer=this.buffer.length?Buffer.concat([this.buffer,e]):e,this.drain().then(()=>r()).catch(r)}_final(e){this.remaining>0?e(new Error("archive ends inside an entry")):e()}target(e){const t=m(e);if(!t||d(t)||".."===t||t.startsWith(`..${w}`))throw new Error(`unsafe path in archive: ${e}`);return h(this.dest,t)}async closeFile(){const e=this.file;this.file=null,e&&await new Promise((t,r)=>e.end(e=>e?r(e):t()))}async drain(){for(;;){if(this.remaining>0){if(0===this.buffer.length)return;const e=this.buffer.subarray(0,Math.min(this.remaining,this.buffer.length));this.buffer=this.buffer.subarray(e.length),this.remaining-=e.length,this.collectingLongName?this.collectingLongName.push(e):this.file&&!this.file.write(e)&&await new Promise(e=>this.file.once("drain",()=>e())),0===this.remaining&&(this.collectingLongName&&(this.longName=Buffer.concat(this.collectingLongName).toString("utf-8").replace(/\0.*$/s,""),this.collectingLongName=null),await this.closeFile());continue}if(this.padding>0){if(this.buffer.length<this.padding)return;this.buffer=this.buffer.subarray(this.padding),this.padding=0}if(this.buffer.length<512)return;const e=this.buffer.subarray(0,512);if(this.buffer=this.buffer.subarray(512),e.every(e=>0===e))continue;const t=(t,r)=>e.subarray(t,t+r).toString("utf-8").replace(/\0.*$/s,""),r=t(345,155);let o=r?`${r}/${t(0,100)}`:t(0,100);null!==this.longName&&(o=this.longName,this.longName=null);const i=parseInt(t(124,12).trim()||"0",8),n=511&parseInt(t(100,8).trim()||"644",8),a=t(156,1)||"0";if(this.remaining=i,this.padding=(512-i%512)%512,"L"===a)this.collectingLongName=[];else if("x"===a||"g"===a);else if("5"===a)await l(this.target(o),{recursive:!0});else{if("0"!==a)throw new Error(`unexpected entry type ${a} in archive: ${o}`);{const e=this.target(o);await l(h(e,".."),{recursive:!0}),this.file=s(e,{mode:n||420}),0===i&&await this.closeFile()}}}}}export async function installDesktopCli(e){const s=readDesktopCliPin(e.asar,e.platformKey,e.bundle);if(!s)return{status:"skipped",reason:"unknown app layout"};if(e.bundle&&!e.download)return{status:"skipped",reason:"no bundle mirror"};const i=e.platformKey.startsWith("win32")?"claude.exe":"claude",n=h(e.userDataDir,"claude-code",s.version),d=h(n,s.checksum.slice(0,12)),m=e.bundle?h(d,"claude.app","Contents","MacOS","claude"):h(d,i),w=h(d,".verified");try{if(o(m)&&(await c(w,"utf-8")).trim()===s.checksum)return{status:"present",version:s.version}}catch{}await l(n,{recursive:!0});const g=h(n,`.partial-${s.checksum.slice(0,12)}`),v=`${g}.download`;try{await f(w,{force:!0}),await f(g,{recursive:!0,force:!0});let i="mirror";if(e.bundle){if(e.onDownload?.(s.version),await e.download(s.version,v),await async function(e,s,o){const i=t("sha256");if(await D(r(e),new b({write(e,t,r){i.update(e),r()}})),i.digest("hex")!==s)throw new Error("downloaded bundle does not match the app's checksum");const n=y.createZstdDecompress;if(!n)throw new Error(`Node ${process.version} cannot decompress zstd (needs 22.15 or newer)`);await D(r(e),n(),new L(o))}(v,s.checksum,g),!o(h(g,"claude.app","Contents","MacOS","claude")))throw new Error("bundle has no claude.app");await f(d,{recursive:!0,force:!0}),await u(g,d)}else{const t=e.localVersionsDir?h(e.localVersionsDir,s.version):null;if(t&&o(t))await a(t,g),i="local";else{e.onDownload?.(s.version);const t=e.download??((t,r)=>$(e.platformKey,t,r));await t(s.version,g)}await l(d,{recursive:!0}),await u(g,m)}return await p(w,s.checksum),{status:"installed",version:s.version,source:i}}finally{await f(g,{recursive:!0,force:!0}),await f(v,{force:!0}),await f(`${g}.download`,{force:!0})}}let P=(...e)=>fetch(...e);export function setDesktopCliFetchForTests(e){P=e}export async function ensureDesktopCli(t){const r=N();if(!r)return{status:"skipped",reason:"unsupported architecture"};if("win32"===process.platform){const s=function(){const t=h(process.env.LOCALAPPDATA||"","AnthropicClaude");if(process.env.LOCALAPPDATA&&o(t)){const e=i(t).filter(e=>/^app-\d+\.\d+\.\d+$/.test(e)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}));for(const r of e){const e=h(t,r,"resources","app.asar");if(o(e))return e}}try{const t=e("powershell.exe",["-NoProfile","-Command",`Get-AppxPackage | Where-Object { @(${x.map(e=>`'${e}'`).join(",")}) -contains $_.PackageFamilyName } | ForEach-Object { $_.InstallLocation }`],{encoding:"utf-8",timeout:15e3,windowsHide:!0,stdio:["ignore","pipe","ignore"]});for(const e of t.split(/\r?\n/).map(e=>e.trim()).filter(Boolean)){const t=h(e,"app","resources","app.asar");if(o(t))return t}}catch(e){v.logError("claude-desktop-cli.windowsAsarPath",e)}return null}();return s?installDesktopCli({userDataDir:t.userDataDir,asar:n(s),platformKey:r,localVersionsDir:C().versionsDir,onDownload:t.onDownload}):{status:"skipped",reason:"app.asar not found"}}if("darwin"===process.platform){const e=function(){for(const e of["/Applications/Claude.app",h(A(),"Applications","Claude.app")]){const t=h(e,"Contents","Resources","app.asar");if(o(t))return t}return null}();if(!e)return{status:"skipped",reason:"app.asar not found"};const{mirrorRepo:i,desktopVersion:a}=t;return installDesktopCli({userDataDir:t.userDataDir,asar:n(e),platformKey:r,bundle:!0,onDownload:t.onDownload,download:i&&a?(e,t)=>async function(e,t){const r=await P(e,{signal:AbortSignal.timeout(9e5)});if(!r.ok||!r.body)throw new Error(`${e}: HTTP ${r.status}`);await D(g.fromWeb(r.body),s(t))}(`${i}/-/releases/download/v${a}/claude-code-${e}-${r}.app.tar.zst`,t):void 0})}if("linux"===process.platform){const e=function(){if(k("TEST_HOME")?.trim())return null;for(const e of["/usr/lib/claude-desktop","/opt/Claude"]){const t=h(e,"resources","app.asar");if(o(t))return t}return null}();return e?installDesktopCli({userDataDir:t.userDataDir,asar:n(e),platformKey:r.replace(/-musl$/,""),localVersionsDir:r.endsWith("-musl")?void 0:C().versionsDir,onDownload:t.onDownload}):{status:"skipped",reason:"app.asar not found"}}return{status:"skipped",reason:"unsupported platform"}}
1
+ import{execFileSync as e}from"child_process";import{createHash as t}from"crypto";import{createReadStream as r,createWriteStream as s,existsSync as o,readdirSync as n,readFileSync as i}from"fs";import{copyFile as a,mkdir as l,readFile as c,rename as u,rm as f,writeFile as p}from"fs/promises";import{isAbsolute as d,join as m,normalize as h,sep as w}from"path";import{Readable as g,Writable as b}from"stream";import{pipeline as D}from"stream/promises";import*as y from"zlib";import{logger as v}from"../../utils/logger.js";import{brandEnv as k}from"../brand.js";import{downloadNativeBinary as $,nativeLayout as C,nativePlatformKey as x}from"./claude-native-mirror.js";import{WINDOWS_PACKAGE_FAMILIES as N}from"./desktop-process.js";import{toolHome as A}from"./types.js";export function readDesktopCliPin(e,t,r=!1){const s=e.indexOf('claude-code-releases","sdkWrapperVersion"');if(s<0)return null;const o=e.lastIndexOf("JSON.parse('",s),n=e.indexOf("')",s);if(o<0||n<0)return null;try{const s=JSON.parse(e.subarray(o+12,n).toString("utf-8")),i="string"==typeof s.version?s.version:"",a=s.manifest?.platforms?.[t],l=r?a?.bundle?.checksum:a?.checksum;return/^\d+\.\d+\.\d+$/.test(i)&&"string"==typeof l&&/^[0-9a-f]{64}$/.test(l)?{version:i,checksum:l}:null}catch{return null}}function P(){const t=m(process.env.LOCALAPPDATA||"","AnthropicClaude");if(process.env.LOCALAPPDATA&&o(t)){const e=n(t).filter(e=>/^app-\d+\.\d+\.\d+$/.test(e)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}));for(const r of e){const e=m(t,r,"resources","app.asar");if(o(e))return e}}try{const t=e("powershell.exe",["-NoProfile","-Command",`Get-AppxPackage | Where-Object { @(${N.map(e=>`'${e}'`).join(",")}) -contains $_.PackageFamilyName } | ForEach-Object { $_.InstallLocation }`],{encoding:"utf-8",timeout:15e3,windowsHide:!0,stdio:["ignore","pipe","ignore"]});for(const e of t.split(/\r?\n/).map(e=>e.trim()).filter(Boolean)){const t=m(e,"app","resources","app.asar");if(o(t))return t}}catch(e){v.logError("claude-desktop-cli.windowsAsarPath",e)}return null}function L(){if(k("TEST_HOME")?.trim())return null;for(const e of["/usr/lib/claude-desktop","/opt/Claude"]){const t=m(e,"resources","app.asar");if(o(t))return t}return null}function O(){for(const e of["/Applications/Claude.app",m(A(),"Applications","Claude.app")]){const t=m(e,"Contents","Resources","app.asar");if(o(t))return t}return null}export function installedDesktopAsarPath(){return"win32"===process.platform?P():"darwin"===process.platform?O():"linux"===process.platform?L():null}class E extends b{dest;buffer=Buffer.alloc(0);remaining=0;padding=0;file=null;longName=null;collectingLongName=null;constructor(e){super(),this.dest=e}_write(e,t,r){this.buffer=this.buffer.length?Buffer.concat([this.buffer,e]):e,this.drain().then(()=>r()).catch(r)}_final(e){this.remaining>0?e(new Error("archive ends inside an entry")):e()}target(e){const t=h(e);if(!t||d(t)||".."===t||t.startsWith(`..${w}`))throw new Error(`unsafe path in archive: ${e}`);return m(this.dest,t)}async closeFile(){const e=this.file;this.file=null,e&&await new Promise((t,r)=>e.end(e=>e?r(e):t()))}async drain(){for(;;){if(this.remaining>0){if(0===this.buffer.length)return;const e=this.buffer.subarray(0,Math.min(this.remaining,this.buffer.length));this.buffer=this.buffer.subarray(e.length),this.remaining-=e.length,this.collectingLongName?this.collectingLongName.push(e):this.file&&!this.file.write(e)&&await new Promise(e=>this.file.once("drain",()=>e())),0===this.remaining&&(this.collectingLongName&&(this.longName=Buffer.concat(this.collectingLongName).toString("utf-8").replace(/\0.*$/s,""),this.collectingLongName=null),await this.closeFile());continue}if(this.padding>0){if(this.buffer.length<this.padding)return;this.buffer=this.buffer.subarray(this.padding),this.padding=0}if(this.buffer.length<512)return;const e=this.buffer.subarray(0,512);if(this.buffer=this.buffer.subarray(512),e.every(e=>0===e))continue;const t=(t,r)=>e.subarray(t,t+r).toString("utf-8").replace(/\0.*$/s,""),r=t(345,155);let o=r?`${r}/${t(0,100)}`:t(0,100);null!==this.longName&&(o=this.longName,this.longName=null);const n=parseInt(t(124,12).trim()||"0",8),i=511&parseInt(t(100,8).trim()||"644",8),a=t(156,1)||"0";if(this.remaining=n,this.padding=(512-n%512)%512,"L"===a)this.collectingLongName=[];else if("x"===a||"g"===a);else if("5"===a)await l(this.target(o),{recursive:!0});else{if("0"!==a)throw new Error(`unexpected entry type ${a} in archive: ${o}`);{const e=this.target(o);await l(m(e,".."),{recursive:!0}),this.file=s(e,{mode:i||420}),0===n&&await this.closeFile()}}}}}export async function installDesktopCli(e){const s=readDesktopCliPin(e.asar,e.platformKey,e.bundle);if(!s)return{status:"skipped",reason:"unknown app layout"};if(e.bundle&&!e.download)return{status:"skipped",reason:"no bundle mirror"};const n=e.platformKey.startsWith("win32")?"claude.exe":"claude",i=m(e.userDataDir,"claude-code",s.version),d=m(i,s.checksum.slice(0,12)),h=e.bundle?m(d,"claude.app","Contents","MacOS","claude"):m(d,n),w=m(d,".verified");try{if(o(h)&&(await c(w,"utf-8")).trim()===s.checksum)return{status:"present",version:s.version}}catch{}await l(i,{recursive:!0});const g=m(i,`.partial-${s.checksum.slice(0,12)}`),v=`${g}.download`;try{await f(w,{force:!0}),await f(g,{recursive:!0,force:!0});let n="mirror";if(e.bundle){if(e.onDownload?.(s.version),await e.download(s.version,v),await async function(e,s,o){const n=t("sha256");if(await D(r(e),new b({write(e,t,r){n.update(e),r()}})),n.digest("hex")!==s)throw new Error("downloaded bundle does not match the app's checksum");const i=y.createZstdDecompress;if(!i)throw new Error(`Node ${process.version} cannot decompress zstd (needs 22.15 or newer)`);await D(r(e),i(),new E(o))}(v,s.checksum,g),!o(m(g,"claude.app","Contents","MacOS","claude")))throw new Error("bundle has no claude.app");await f(d,{recursive:!0,force:!0}),await u(g,d)}else{const t=e.localVersionsDir?m(e.localVersionsDir,s.version):null;if(t&&o(t))await a(t,g),n="local";else{e.onDownload?.(s.version);const t=e.download??((t,r)=>$(e.platformKey,t,r));await t(s.version,g)}await l(d,{recursive:!0}),await u(g,h)}return await p(w,s.checksum),{status:"installed",version:s.version,source:n}}finally{await f(g,{recursive:!0,force:!0}),await f(v,{force:!0}),await f(`${g}.download`,{force:!0})}}let S=(...e)=>fetch(...e);export function setDesktopCliFetchForTests(e){S=e}export async function ensureDesktopCli(e){const t=x();if(!t)return{status:"skipped",reason:"unsupported architecture"};if("win32"===process.platform){const r=P();return r?installDesktopCli({userDataDir:e.userDataDir,asar:i(r),platformKey:t,localVersionsDir:C().versionsDir,onDownload:e.onDownload}):{status:"skipped",reason:"app.asar not found"}}if("darwin"===process.platform){const r=O();if(!r)return{status:"skipped",reason:"app.asar not found"};const{mirrorRepo:o,desktopVersion:n}=e;return installDesktopCli({userDataDir:e.userDataDir,asar:i(r),platformKey:t,bundle:!0,onDownload:e.onDownload,download:o&&n?(e,r)=>async function(e,t){const r=await S(e,{signal:AbortSignal.timeout(9e5)});if(!r.ok||!r.body)throw new Error(`${e}: HTTP ${r.status}`);await D(g.fromWeb(r.body),s(t))}(`${o}/-/releases/download/v${n}/claude-code-${e}-${t}.app.tar.zst`,r):void 0})}if("linux"===process.platform){const r=L();return r?installDesktopCli({userDataDir:e.userDataDir,asar:i(r),platformKey:t.replace(/-musl$/,""),localVersionsDir:t.endsWith("-musl")?void 0:C().versionsDir,onDownload:e.onDownload}):{status:"skipped",reason:"app.asar not found"}}return{status:"skipped",reason:"unsupported platform"}}
@@ -1 +1 @@
1
- import{chmodSync as e,existsSync as t,mkdirSync as o,readdirSync as n,readFileSync as r,rmSync as s}from"fs";import{dirname as i}from"path";import{join as l}from"path";import{randomUUID as a}from"crypto";import{execFileSync as c}from"child_process";import{userInfo as d}from"os";import p from"chalk";import{logger as u}from"../../utils/logger.js";import{track as f}from"../telemetry.js";import{ensureDesktopCli as m}from"./claude-desktop-cli.js";import{i18n as g}from"../i18n.js";import{BRAND_NAME as y,brand as h,brandEnv as k,CLI_NAME as _}from"../brand.js";import{backupBeforeWrite as b,atomicWriteFile as D}from"./backup.js";import{toolHome as A}from"./types.js";import{canRestartDesktop as C,isDesktopRunning as w,restartDesktop as E,WINDOWS_PACKAGE_FAMILIES as v}from"./desktop-process.js";import{setUserRegistryElevated as M}from"./elevated-reg.js";import{UserActionNeeded as O}from"./types.js";import{baseModelId as x,isClaudeModel as S}from"../model-catalog.js";import{getDefaultModels as P}from"../model-registry.js";import{claudeFormat as j,nestedClaudeProjectFiles as L}from"../sessions/formats.js";const I=y;export const CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING="hide_official_login";export const CLAUDE_DESKTOP_FORCE_REGISTRY_SETTING="force_registry";const T=/^[a-f0-9-]{36}$/;function $(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}export function claudeDesktopUserDataDir(){const e=process.env.CLAUDE_USER_DATA_DIR?.trim();if(e)return e;const o=A(),n=Boolean(k("TEST_HOME")?.trim());switch(process.platform){case"darwin":return l(o,"Library","Application Support","Claude-3p");case"win32":{const e=!n&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:l(o,"AppData","Local");return v.map(t=>l(e,"Packages",t,"LocalCache","Local","Claude-3p")).find(e=>t(e))??l(e,"Claude-3p")}default:{const e=!n&&process.env.XDG_CONFIG_HOME?process.env.XDG_CONFIG_HOME:l(o,".config");return l(e,"Claude-3p")}}}const R=()=>l(claudeDesktopUserDataDir(),"configLibrary"),G=()=>l(R(),"_meta.json"),K=e=>l(R(),`${e}.json`),N=()=>l(claudeDesktopUserDataDir(),"claude_desktop_config.json");function U(e){if(!t(e))return null;const o=r(e,"utf-8");if(!o.trim())return null;try{const e=JSON.parse(o);return $(e)?e:null}catch(t){throw new Error(`Existing ${e} cannot be parsed; back it up and fix it first: ${t instanceof Error?t.message:String(t)}`)}}function F(n,r){const s=i(n);t(s)||o(s,{recursive:!0,mode:448}),b(n),D(n,JSON.stringify(r,null,2)+"\n");try{e(n,384)}catch(e){u.logError("claude-desktop.writeJson.chmod",e)}}function H(){const e=U(G());if(!e)return null;const t=Array.isArray(e.entries)?e.entries.filter(e=>$(e)&&"string"==typeof e.id&&"string"==typeof e.name):[];return{...e,appliedId:"string"==typeof e.appliedId?e.appliedId:"",entries:t}}function B(e){return e?.entries.find(e=>e.name===I&&T.test(e.id))}const V={opus:0,fable:1,sonnet:2,haiku:3};function W(e){let t=/^claude-(opus|sonnet|haiku|fable)-(\d+(?:-\d+)*)/i.exec(e);return t?{family:t[1].toLowerCase(),version:t[2].split("-").map(Number)}:(t=/^claude-(\d+(?:-\d+)*)-(opus|sonnet|haiku)/i.exec(e),t?{family:t[2].toLowerCase(),version:t[1].split("-").map(Number)}:null)}export function humanizeModelId(e){const t=W(e);return t?`${t.family[0].toUpperCase()+t.family.slice(1)} ${t.version.filter(e=>e<1e7).slice(0,2).join(".")}`:e}function J(e){return W(e)?.family}export function buildInferenceModels(e,t){const{primary:o,bySlot:n}=function(e){const t=["opus","sonnet","haiku","reasoning"].map(t=>x(e[t]||"")).filter(Boolean);return{primary:t[0]??"",bySlot:t}}(e),r=new Set,s=t?.labels??{};let i;if(t&&t.models.some(S)){i=[...new Set(t.models.filter(S).map(x))];for(const e of t.oneMillion)r.add(e)}else{i=[];for(const t of["opus","sonnet","haiku","reasoning"]){const o=(e[t]||"").trim(),n=x(o);n&&(i.includes(n)||i.push(n),/\[1m\]/i.test(o)&&r.add(n))}}const l=e=>V[J(e)??""]??9;i.sort((e,t)=>{if(e===o)return-1;if(t===o)return 1;const n=l(e)-l(t);if(0!==n)return n;const r=W(e),s=W(t);return r&&s?function(e,t){const o=Math.max(e.length,t.length);for(let n=0;n<o;n++){const o=(t[n]??0)-(e[n]??0);if(0!==o)return o}return 0}(r.version,s.version):e.localeCompare(t)});const a=new Set,c=new Map,d=new Set(Object.values(P()).map(e=>x(e||"")));for(const e of n){const t=J(e);t&&i.includes(e)&&!d.has(e)&&!c.has(t)&&c.set(t,e)}return i.map(e=>{const t=J(e),o={name:e,labelOverride:s[e]||humanizeModelId(e)};if(r.has(e)&&(o.supports1m=!0,o.prefer1m=!0),t){o.anthropicFamilyTier=t;const n=c.get(t);n&&n!==e||a.has(t)||(o.isFamilyDefault=!0,a.add(t))}return o})}let z=null,Z=null,q=null,X=null,Y=null;function Q(e){return{inferenceProvider:"gateway",inferenceCredentialKind:"static",inferenceGatewayBaseUrl:(e.baseUrl||"").trim().replace(/\/+$/,""),inferenceGatewayApiKey:e.apiKey,inferenceModels:buildInferenceModels(e.models,e.catalog),disableDeploymentModeChooser:!1!==e.settings?.hide_official_login,chatTabEnabled:!0,chatAdvancedFileAnalysisEnabled:!0,autoModeEnabled:!0,coworkEgressAllowedHosts:["*"],disableEssentialTelemetry:!0,disableNonessentialTelemetry:!0,disableNonessentialServices:!1}}const ee={defaultModelEffort:"medium",modelPrefer1mContext:!0,skipWebFetchPreflight:!0,toolSearchEnabled:!0,builtinBrowserEnabled:!0,isDesktopExtensionEnabled:!0,sshHostAllowlist:["*"],claudeAiImport:{enabled:!0,automatic3pImport:!0,exportEnabled:!0},coworkVmIpv6Enabled:!0,mcpToolTimeoutSec:3600,updateViaUpdatesHost:!0,banner:{enabled:!1}};function te(e){return Object.fromEntries(Object.entries(ee).filter(([t])=>!e(t)))}const oe="SOFTWARE\\Policies\\Claude",ne=`HKCU\\${oe}`,re="HKLM\\SOFTWARE\\Policies\\Claude",se=`${_}-claude-policy.reg`,ie=e=>c("reg",e,{stdio:["ignore","pipe","pipe"]}).toString();let le=ie;export function setRegRunnerForTests(e){le=e??ie}function ae(){return"win32"===process.platform}function ce(e){let t;try{t=le(["query",e])}catch{return null}const o=new Map;for(const e of t.split(/\r?\n/)){const t=/^\s{2,}(\S+)\s+(REG_[A-Z_]+)\s*(.*)$/.exec(e);t&&o.set(t[1],t[3])}return o}function de(){if(null===ce(ne))return;const e=l(claudeDesktopUserDataDir(),se);try{t(i(e))||o(i(e),{recursive:!0,mode:448}),b(e),le(["export",ne,e,"/y"])}catch(e){u.logError("claude-desktop.snapshotPolicy",e)}}function pe(e){de();for(const[t,o]of Object.entries(e)){const[e,n]="boolean"==typeof o?["REG_DWORD",o?"1":"0"]:"number"==typeof o?["REG_DWORD",String(o)]:"string"==typeof o?["REG_SZ",o]:["REG_SZ",JSON.stringify(o)];le(["add",ne,"/v",t,"/t",e,"/d",n,"/f"])}}function ue(e){const t=ce(ne);if(!t)return;de();let o=t.size;for(const n of e)t.has(n)&&(le(["delete",ne,"/v",n,"/f"]),o-=1);o<=0&&le(["delete",ne,"/f"])}function fe(){const e=!Boolean(k("TEST_HOME")?.trim())&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:l(A(),"AppData","Local");return!!t(l(e,"AnthropicClaude"))||v.some(o=>t(l(e,"Packages",o,"LocalCache","Local","Claude-3p")))}const me=[...Object.keys(Q({apiKey:"",baseUrl:"",models:{haiku:"",sonnet:"",opus:"",reasoning:""}})),...Object.keys(ee)];export function detectManagedConfig(){try{if("darwin"===process.platform){let e="";try{e=d().username}catch{}return[e?`/Library/Managed Preferences/${e}/com.anthropic.claudefordesktop.plist`:"","/Library/Managed Preferences/com.anthropic.claudefordesktop.plist"].filter(Boolean).find(e=>t(e))??null}if("win32"===process.platform)return ce(re)?re:null;const e="/etc/claude-desktop/managed-settings.json";return t(e)?e:null}catch(e){return u.logError("claude-desktop.detectManagedConfig",e),null}}function ge(){const e=A();let o;switch(process.platform){case"darwin":o=["/Applications/Claude.app",l(e,"Applications","Claude.app")];break;case"win32":{const t=process.env.LOCALAPPDATA||l(e,"AppData","Local");o=[l(t,"AnthropicClaude"),l(t,"Programs","Claude"),...v.map(e=>l(t,"Packages",e))];break}default:o=["/usr/lib/claude-desktop","/opt/Claude","/usr/bin/claude-desktop",l(e,".local","bin","claude-desktop")]}return o.push(claudeDesktopUserDataDir(),l(claudeDesktopUserDataDir(),"..","Claude")),o.some(e=>t(e))}const ye=/\d+\.\d+\.\d+/;function he(e){const t=e=>e.split(".").map(Number);return e.sort((e,o)=>{const[n,r]=[t(e),t(o)];for(let e=0;e<3;e++)if(n[e]!==r[e])return r[e]-n[e];return 0})[0]??null}function ke(){if("darwin"===process.platform){for(const e of["/Applications/Claude.app",l(A(),"Applications","Claude.app")]){const o=l(e,"Contents","Info.plist");if(!t(o))continue;const n=/<key>CFBundleShortVersionString<\/key>\s*<string>([^<]+)<\/string>/.exec(r(o,"utf-8")),s=n?ye.exec(n[1])?.[0]:void 0;if(s)return s}return null}if("win32"===process.platform){const e=l(process.env.LOCALAPPDATA||l(A(),"AppData","Local"),"AnthropicClaude");if(t(e)){const t=n(e).map(e=>/^app-(\d+\.\d+\.\d+)$/.exec(e)?.[1]).filter(e=>!!e);if(t.length>0)return he(t)}const o=v.map(e=>`'${e}'`).join(",");return he(c("powershell.exe",["-NoProfile","-Command",`Get-AppxPackage | Where-Object { @(${o}) -contains $_.PackageFamilyName } | ForEach-Object { $_.Version.ToString() }`],{encoding:"utf-8",timeout:15e3,windowsHide:!0,stdio:["ignore","pipe","ignore"]}).split(/\r?\n/).flatMap(e=>ye.exec(e)?.[0]??[]))}if("linux"===process.platform)try{const e=c("dpkg-query",["-W","-f=${Version}","claude-desktop"],{encoding:"utf-8",timeout:5e3,stdio:["ignore","pipe","ignore"]});return ye.exec(e)?.[0]??null}catch{return null}return null}const _e="darwin"===process.platform?"open -a Claude":"win32"===process.platform?"Claude":"claude-desktop",be="darwin"!==process.platform&&"win32"!==process.platform||!h().installMirror?.claudeDesktop?"https://claude.ai/download":h().installMirror.claudeDesktop,De="darwin"===process.platform?`open ${be}`:"win32"===process.platform?`start ${be}`:`xdg-open ${be}`;export const claudeDesktopAdapter={name:"claude-desktop",displayName:"Claude Desktop",command:_e,installCommand:De,configPath:G(),sessions:{format:j,files:()=>L(l(claudeDesktopUserDataDir(),"local-agent-mode-sessions"))},isInstalled:ge,installedVersion:ke,prepareRuntime:async function(){if(!["win32","darwin","linux"].includes(process.platform)||!ge())return[];const e=Date.now();try{const t=await m({userDataDir:claudeDesktopUserDataDir(),onDownload:e=>console.log(p.gray(" "+g.t("tools.claude_desktop.code_cli_downloading",{version:e}))),desktopVersion:"darwin"===process.platform?ke():null,mirrorRepo:h().installMirror?.claudeDesktop?.replace(/\/-\/releases\/latest\/?$/,"")??null});return f("desktop-code-cli","skipped"===t.status?"skip":"ok",{duration_ms:Date.now()-e,detail:{...t}}),"installed"!==t.status?[]:[{kind:"summary",text:g.t("tools.claude_desktop.code_cli_installed",{version:t.version})}]}catch(t){return u.logError("claude-desktop.prepareCodeTabCli",t),f("desktop-code-cli","fail",{duration_ms:Date.now()-e,error:t}),[{kind:"action",text:g.t("tools.claude_desktop.code_cli_failed",{reason:t instanceof Error?t.message:String(t)})}]}},runningApp:C()?{isRunning:w,restart:E}:void 0,wantsModelCatalog:!0,loadPrivateConfig(e){const t=H()??{appliedId:"",entries:[]};let o=B(t);o||(o={id:a(),name:I},t.entries.push(o));const n=Q(e);Z=!0===n.disableDeploymentModeChooser,z={models:n.inferenceModels,source:e.catalog?e.catalog.oneMillionSource:"slots",groups:e.catalog?.matchedGroups??[]};const r=U(K(o.id))??{};F(K(o.id),{...te(e=>e in r),...r,...n}),t.appliedId=o.id,F(G(),t);const s=U(N())??{};if("3p"!==s.deploymentMode&&F(N(),{...s,deploymentMode:"3p"}),X=null,Y=null,q=null,ae()){const t=ce(ne),o=me.filter(e=>t?.has(e)),r={...te(e=>t?.has(e)??!1),...n},s=!0===e.settings?.force_registry,i=!s&&fe();try{i?ue(me):pe(r),q=i?"removed":"written"}catch(e){u.logError("claude-desktop.policy",e),X=e instanceof Error?e.message.trim():String(e),(o.length>0||s)&&(Y=i?{action:"remove",values:Object.fromEntries(o.map(e=>[e,null])),deleteKey:o.length===t.size}:{action:"write",values:r,deleteKey:!1})}}},pendingElevation(){const e=Y;return e?{prompt:g.t(`tools.claude_desktop.elevate_${e.action}`),run:()=>{if(!M(oe,e.values,e.deleteKey))return!1;const t=ce(ne),o="remove"===e.action?Object.keys(e.values).every(e=>!t?.has(e)):Object.keys(e.values).every(e=>t?.has(e));return o&&(Y=null,X=null),o}}:null},unloadPrivateConfig(){if(ae())try{ue(me)}catch(e){u.logError("claude-desktop.removePolicy",e)}const e=H(),t=B(e);if(!e||!t)return;b(K(t.id)),s(K(t.id),{force:!0});const o=e.entries.filter(e=>e.id!==t.id);0===o.length?(b(G()),s(G(),{force:!0})):F(G(),{...e,entries:o,appliedId:e.appliedId===t.id?o[0].id:e.appliedId})},listedModels(){const e=H(),t=B(e);if(!t||e?.appliedId!==t.id)return null;const o=U(K(t.id))?.inferenceModels;return Array.isArray(o)?o.map(e=>String(e.name)):null},refreshModelMenu(e){const t=H(),o=B(t);if(!o||t?.appliedId!==o.id)return;const n=U(K(o.id));if(!n)return;const r=buildInferenceModels(e.models,e.catalog),s=JSON.stringify(n.inferenceModels)!==JSON.stringify(r);Y=null;const i=ae()?ce(ne):null;if(!i?.has("inferenceModels"))return void(s&&F(K(o.id),{...n,inferenceModels:r}));const l=me.filter(e=>i.has(e)),a=!0!==e.settings?.force_registry&&fe();if(a||s){s&&F(K(o.id),{...n,inferenceModels:r});try{a?ue(me):pe({inferenceModels:r})}catch(e){throw u.logError("claude-desktop.refreshModelMenu registry",e),Y=a?{action:"remove",values:Object.fromEntries(l.map(e=>[e,null])),deleteKey:l.length===i.size}:{action:"write",values:{inferenceModels:r},deleteKey:!1},new O(g.t("tools.claude_desktop.refresh_needs_admin"))}}},detectCurrentConfig(){try{if(ae()){const e=ce(ne)?.get("inferenceGatewayApiKey");if(e)return{apiKey:e}}const e=B(H());if(!e)return{apiKey:null};const t=U(K(e.id)),o=t?.inferenceGatewayApiKey;return{apiKey:"string"==typeof o&&o?o:null}}catch(e){return u.logError("claude-desktop.detectCurrentConfig",e),{apiKey:null}}},getConfig(){try{const e=H(),t=B(e);return{meta:e,applied:t?U(K(t.id)):null,desktop:U(N()),...ae()?{policy:Object.fromEntries(ce(ne)??[])}:{}}}catch(e){return u.logError("claude-desktop.getConfig",e),null}},clearPinnedModels(){let e=!1;ae()&&ce(ne)?.has("inferenceModels")&&(de(),le(["delete",ne,"/v","inferenceModels","/f"]),e=!0);const t=B(H()),o=t?U(K(t.id)):null;if(t&&o&&void 0!==o.inferenceModels){const{inferenceModels:n,...r}=o;F(K(t.id),r),e=!0}return e?["inferenceModels"]:[]},applyNotes(){const e=[];if(z&&z.models.length>0){const{models:t,source:o,groups:n}=z;e.push({kind:"summary",text:g.t("tools.claude_desktop.models_summary",{count:String(t.length),default:t[0].labelOverride??t[0].name})}),e.push({kind:"detail",text:g.t(`tools.claude_desktop.models_written_${o}`,{count:String(t.length),list:t.map(e=>`${e.labelOverride}${e.supports1m?" (1M)":""}`).join(", "),groups:n.join(" / ")})})}null!==Z&&e.push({kind:"detail",text:g.t(Z?"tools.claude_desktop.official_login_hidden":"tools.claude_desktop.official_login_shown")}),C()&&!w()||e.push({kind:"action",text:g.t("tools.claude_desktop.restart_hint")}),Y?(e.push({kind:"action",text:g.t(`tools.claude_desktop.policy_stale_${Y.action}`)}),e.push({kind:"detail",text:X??""})):X?(e.push({kind:"detail",text:g.t("tools.claude_desktop.registry_denied")}),e.push({kind:"detail",text:X})):ae()&&q&&e.push({kind:"detail",text:g.t(`tools.claude_desktop.registry_${q}`,{key:ne})});const t=detectManagedConfig();return t&&e.push({kind:"action",text:g.t("tools.claude_desktop.managed_conflict",{path:t})}),e},forceResetPaths(){const e=[G(),N()];try{const t=B(H());t&&e.push(K(t.id))}catch{}return e},backupPaths(){const e=[G(),N()];ae()&&e.push(l(claudeDesktopUserDataDir(),se));try{const t=B(H());t&&e.push(K(t.id))}catch{}return e}};
1
+ import{chmodSync as e,existsSync as t,mkdirSync as o,readdirSync as n,readFileSync as r,rmSync as s}from"fs";import{dirname as i}from"path";import{join as l}from"path";import{randomUUID as a}from"crypto";import{execFileSync as c}from"child_process";import{userInfo as d}from"os";import p from"chalk";import{logger as u}from"../../utils/logger.js";import{track as f}from"../telemetry.js";import{ensureDesktopCli as m,installedDesktopAsarPath as g}from"./claude-desktop-cli.js";import{i18n as y}from"../i18n.js";import{BRAND_NAME as h,brand as k,brandEnv as _,CLI_NAME as D}from"../brand.js";import{backupBeforeWrite as b,atomicWriteFile as A}from"./backup.js";import{toolHome as C}from"./types.js";import{canRestartDesktop as w,isDesktopRunning as E,restartDesktop as v,WINDOWS_PACKAGE_FAMILIES as M}from"./desktop-process.js";import{setUserRegistryElevated as O}from"./elevated-reg.js";import{UserActionNeeded as S}from"./types.js";import{baseModelId as x,isClaudeModel as j}from"../model-catalog.js";import{getDefaultModels as P}from"../model-registry.js";import{claudeFormat as L,nestedClaudeProjectFiles as T}from"../sessions/formats.js";const I=h;export const CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING="hide_official_login";export const CLAUDE_DESKTOP_FORCE_REGISTRY_SETTING="force_registry";const $=/^[a-f0-9-]{36}$/;function N(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}export function claudeDesktopUserDataDir(){const e=process.env.CLAUDE_USER_DATA_DIR?.trim();if(e)return e;const o=C(),n=Boolean(_("TEST_HOME")?.trim());switch(process.platform){case"darwin":return l(o,"Library","Application Support","Claude-3p");case"win32":{const e=!n&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:l(o,"AppData","Local");return M.map(t=>l(e,"Packages",t,"LocalCache","Local","Claude-3p")).find(e=>t(e))??l(e,"Claude-3p")}default:{const e=!n&&process.env.XDG_CONFIG_HOME?process.env.XDG_CONFIG_HOME:l(o,".config");return l(e,"Claude-3p")}}}const R=()=>l(claudeDesktopUserDataDir(),"configLibrary"),G=()=>l(R(),"_meta.json"),K=e=>l(R(),`${e}.json`),U=()=>l(claudeDesktopUserDataDir(),"claude_desktop_config.json");function F(e){if(!t(e))return null;const o=r(e,"utf-8");if(!o.trim())return null;try{const e=JSON.parse(o);return N(e)?e:null}catch(t){throw new Error(`Existing ${e} cannot be parsed; back it up and fix it first: ${t instanceof Error?t.message:String(t)}`)}}function H(n,r){const s=i(n);t(s)||o(s,{recursive:!0,mode:448}),b(n),A(n,JSON.stringify(r,null,2)+"\n");try{e(n,384)}catch(e){u.logError("claude-desktop.writeJson.chmod",e)}}function J(){const e=F(G());if(!e)return null;const t=Array.isArray(e.entries)?e.entries.filter(e=>N(e)&&"string"==typeof e.id&&"string"==typeof e.name):[];return{...e,appliedId:"string"==typeof e.appliedId?e.appliedId:"",entries:t}}function B(e){return e?.entries.find(e=>e.name===I&&$.test(e.id))}const V={opus:0,fable:1,sonnet:2,haiku:3};function W(e){let t=/^claude-(opus|sonnet|haiku|fable)-(\d+(?:-\d+)*)/i.exec(e);return t?{family:t[1].toLowerCase(),version:t[2].split("-").map(Number)}:(t=/^claude-(\d+(?:-\d+)*)-(opus|sonnet|haiku)/i.exec(e),t?{family:t[2].toLowerCase(),version:t[1].split("-").map(Number)}:null)}export function humanizeModelId(e){const t=W(e);return t?`${t.family[0].toUpperCase()+t.family.slice(1)} ${t.version.filter(e=>e<1e7).slice(0,2).join(".")}`:e}function z(e){return W(e)?.family}export function buildInferenceModels(e,t){const{primary:o,bySlot:n}=function(e){const t=["opus","sonnet","haiku","reasoning"].map(t=>x(e[t]||"")).filter(Boolean);return{primary:t[0]??"",bySlot:t}}(e),r=new Set,s=t?.labels??{};let i;if(t&&t.models.some(j)){i=[...new Set(t.models.filter(j).map(x))];for(const e of t.oneMillion)r.add(e)}else{i=[];for(const t of["opus","sonnet","haiku","reasoning"]){const o=(e[t]||"").trim(),n=x(o);n&&(i.includes(n)||i.push(n),/\[1m\]/i.test(o)&&r.add(n))}}const l=e=>V[z(e)??""]??9;i.sort((e,t)=>{if(e===o)return-1;if(t===o)return 1;const n=l(e)-l(t);if(0!==n)return n;const r=W(e),s=W(t);return r&&s?function(e,t){const o=Math.max(e.length,t.length);for(let n=0;n<o;n++){const o=(t[n]??0)-(e[n]??0);if(0!==o)return o}return 0}(r.version,s.version):e.localeCompare(t)});const a=new Set,c=new Map,d=new Set(Object.values(P()).map(e=>x(e||"")));for(const e of n){const t=z(e);t&&i.includes(e)&&!d.has(e)&&!c.has(t)&&c.set(t,e)}return i.map(e=>{const t=z(e),o={name:e,labelOverride:s[e]||humanizeModelId(e)};if(r.has(e)&&(o.supports1m=!0,o.prefer1m=!0),t){o.anthropicFamilyTier=t;const n=c.get(t);n&&n!==e||a.has(t)||(o.isFamilyDefault=!0,a.add(t))}return o})}let Z=null,q=null,X=null,Y=null,Q=null;function ee(e){return{inferenceProvider:"gateway",inferenceCredentialKind:"static",inferenceGatewayBaseUrl:(e.baseUrl||"").trim().replace(/\/+$/,""),inferenceGatewayApiKey:e.apiKey,inferenceModels:buildInferenceModels(e.models,e.catalog),disableDeploymentModeChooser:!1!==e.settings?.hide_official_login,chatTabEnabled:!0,chatAdvancedFileAnalysisEnabled:!0,autoModeEnabled:!0,coworkEgressAllowedHosts:["*"],disableEssentialTelemetry:!0,disableNonessentialTelemetry:!0,disableNonessentialServices:!1}}const te={defaultModelEffort:"medium",modelPrefer1mContext:!0,skipWebFetchPreflight:!0,toolSearchEnabled:!0,builtinBrowserEnabled:!0,isDesktopExtensionEnabled:!0,sshHostAllowlist:["*"],claudeAiImport:{enabled:!0,automatic3pImport:!0,exportEnabled:!0},coworkVmIpv6Enabled:!0,mcpToolTimeoutSec:3600,updateViaUpdatesHost:!0,banner:{enabled:!1}},oe=()=>{if(_("TEST_HOME")?.trim())return null;const e=g();return e?r(e):null};let ne=oe,re=null;export function setDesktopAsarForTests(e){ne=void 0===e?oe:()=>e,re=null}function se(){if(re)return re;let e=null;try{e=ne()}catch(e){u.logError("claude-desktop.unsupportedDefaults",e)}return re=new Set(e?Object.keys(te).filter(t=>!e.includes(t)):[]),re}function ie(e){const t=se();return Object.fromEntries(Object.entries(te).filter(([o])=>!e(o)&&!t.has(o)))}function le(e){const t={...ie(t=>t in e),...e};for(const e of se())e in t&&JSON.stringify(t[e])===JSON.stringify(te[e])&&delete t[e];return t}const ae="SOFTWARE\\Policies\\Claude",ce=`HKCU\\${ae}`,de="HKLM\\SOFTWARE\\Policies\\Claude",pe=`${D}-claude-policy.reg`,ue=e=>c("reg",e,{stdio:["ignore","pipe","pipe"]}).toString();let fe=ue;export function setRegRunnerForTests(e){fe=e??ue}function me(){return"win32"===process.platform}function ge(e){let t;try{t=fe(["query",e])}catch{return null}const o=new Map;for(const e of t.split(/\r?\n/)){const t=/^\s{2,}(\S+)\s+(REG_[A-Z_]+)\s*(.*)$/.exec(e);t&&o.set(t[1],t[3])}return o}function ye(){if(null===ge(ce))return;const e=l(claudeDesktopUserDataDir(),pe);try{t(i(e))||o(i(e),{recursive:!0,mode:448}),b(e),fe(["export",ce,e,"/y"])}catch(e){u.logError("claude-desktop.snapshotPolicy",e)}}function he(e){ye();for(const[t,o]of Object.entries(e)){const[e,n]="boolean"==typeof o?["REG_DWORD",o?"1":"0"]:"number"==typeof o?["REG_DWORD",String(o)]:"string"==typeof o?["REG_SZ",o]:["REG_SZ",JSON.stringify(o)];fe(["add",ce,"/v",t,"/t",e,"/d",n,"/f"])}}function ke(e){const t=ge(ce);if(!t)return;ye();let o=t.size;for(const n of e)t.has(n)&&(fe(["delete",ce,"/v",n,"/f"]),o-=1);o<=0&&fe(["delete",ce,"/f"])}function _e(){const e=!Boolean(_("TEST_HOME")?.trim())&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:l(C(),"AppData","Local");return!!t(l(e,"AnthropicClaude"))||M.some(o=>t(l(e,"Packages",o,"LocalCache","Local","Claude-3p")))}const De=[...Object.keys(ee({apiKey:"",baseUrl:"",models:{haiku:"",sonnet:"",opus:"",reasoning:""}})),...Object.keys(te)];export function detectManagedConfig(){try{if("darwin"===process.platform){let e="";try{e=d().username}catch{}return[e?`/Library/Managed Preferences/${e}/com.anthropic.claudefordesktop.plist`:"","/Library/Managed Preferences/com.anthropic.claudefordesktop.plist"].filter(Boolean).find(e=>t(e))??null}if("win32"===process.platform)return ge(de)?de:null;const e="/etc/claude-desktop/managed-settings.json";return t(e)?e:null}catch(e){return u.logError("claude-desktop.detectManagedConfig",e),null}}function be(){const e=C();let o;switch(process.platform){case"darwin":o=["/Applications/Claude.app",l(e,"Applications","Claude.app")];break;case"win32":{const t=process.env.LOCALAPPDATA||l(e,"AppData","Local");o=[l(t,"AnthropicClaude"),l(t,"Programs","Claude"),...M.map(e=>l(t,"Packages",e))];break}default:o=["/usr/lib/claude-desktop","/opt/Claude","/usr/bin/claude-desktop",l(e,".local","bin","claude-desktop")]}return o.push(claudeDesktopUserDataDir(),l(claudeDesktopUserDataDir(),"..","Claude")),o.some(e=>t(e))}const Ae=/\d+\.\d+\.\d+/;function Ce(e){const t=e=>e.split(".").map(Number);return e.sort((e,o)=>{const[n,r]=[t(e),t(o)];for(let e=0;e<3;e++)if(n[e]!==r[e])return r[e]-n[e];return 0})[0]??null}function we(){if("darwin"===process.platform){for(const e of["/Applications/Claude.app",l(C(),"Applications","Claude.app")]){const o=l(e,"Contents","Info.plist");if(!t(o))continue;const n=/<key>CFBundleShortVersionString<\/key>\s*<string>([^<]+)<\/string>/.exec(r(o,"utf-8")),s=n?Ae.exec(n[1])?.[0]:void 0;if(s)return s}return null}if("win32"===process.platform){const e=l(process.env.LOCALAPPDATA||l(C(),"AppData","Local"),"AnthropicClaude");if(t(e)){const t=n(e).map(e=>/^app-(\d+\.\d+\.\d+)$/.exec(e)?.[1]).filter(e=>!!e);if(t.length>0)return Ce(t)}const o=M.map(e=>`'${e}'`).join(",");return Ce(c("powershell.exe",["-NoProfile","-Command",`Get-AppxPackage | Where-Object { @(${o}) -contains $_.PackageFamilyName } | ForEach-Object { $_.Version.ToString() }`],{encoding:"utf-8",timeout:15e3,windowsHide:!0,stdio:["ignore","pipe","ignore"]}).split(/\r?\n/).flatMap(e=>Ae.exec(e)?.[0]??[]))}if("linux"===process.platform)try{const e=c("dpkg-query",["-W","-f=${Version}","claude-desktop"],{encoding:"utf-8",timeout:5e3,stdio:["ignore","pipe","ignore"]});return Ae.exec(e)?.[0]??null}catch{return null}return null}const Ee="darwin"===process.platform?"open -a Claude":"win32"===process.platform?"Claude":"claude-desktop",ve="darwin"!==process.platform&&"win32"!==process.platform||!k().installMirror?.claudeDesktop?"https://claude.ai/download":k().installMirror.claudeDesktop,Me="darwin"===process.platform?`open ${ve}`:"win32"===process.platform?`start ${ve}`:`xdg-open ${ve}`;export const claudeDesktopAdapter={name:"claude-desktop",displayName:"Claude Desktop",command:Ee,installCommand:Me,configPath:G(),sessions:{format:L,files:()=>T(l(claudeDesktopUserDataDir(),"local-agent-mode-sessions"))},isInstalled:be,installedVersion:we,prepareRuntime:async function(){if(!["win32","darwin","linux"].includes(process.platform)||!be())return[];const e=Date.now();try{const t=await m({userDataDir:claudeDesktopUserDataDir(),onDownload:e=>console.log(p.gray(" "+y.t("tools.claude_desktop.code_cli_downloading",{version:e}))),desktopVersion:"darwin"===process.platform?we():null,mirrorRepo:k().installMirror?.claudeDesktop?.replace(/\/-\/releases\/latest\/?$/,"")??null});return f("desktop-code-cli","skipped"===t.status?"skip":"ok",{duration_ms:Date.now()-e,detail:{...t}}),"installed"!==t.status?[]:[{kind:"summary",text:y.t("tools.claude_desktop.code_cli_installed",{version:t.version})}]}catch(t){return u.logError("claude-desktop.prepareCodeTabCli",t),f("desktop-code-cli","fail",{duration_ms:Date.now()-e,error:t}),[{kind:"action",text:y.t("tools.claude_desktop.code_cli_failed",{reason:t instanceof Error?t.message:String(t)})}]}},runningApp:w()?{isRunning:E,restart:v}:void 0,wantsModelCatalog:!0,loadPrivateConfig(e){const t=J()??{appliedId:"",entries:[]};let o=B(t);o||(o={id:a(),name:I},t.entries.push(o));const n=ee(e);q=!0===n.disableDeploymentModeChooser,Z={models:n.inferenceModels,source:e.catalog?e.catalog.oneMillionSource:"slots",groups:e.catalog?.matchedGroups??[]};const r=F(K(o.id))??{};H(K(o.id),{...le(r),...n}),t.appliedId=o.id,H(G(),t);const s=F(U())??{};if("3p"!==s.deploymentMode&&H(U(),{...s,deploymentMode:"3p"}),Y=null,Q=null,X=null,me()){const t=ge(ce),o=De.filter(e=>t?.has(e)),r={...ie(e=>t?.has(e)??!1),...n},s=!0===e.settings?.force_registry,i=!s&&_e();try{i?ke(De):he(r),X=i?"removed":"written"}catch(e){u.logError("claude-desktop.policy",e),Y=e instanceof Error?e.message.trim():String(e),(o.length>0||s)&&(Q=i?{action:"remove",values:Object.fromEntries(o.map(e=>[e,null])),deleteKey:o.length===t.size}:{action:"write",values:r,deleteKey:!1})}}},pendingElevation(){const e=Q;return e?{prompt:y.t(`tools.claude_desktop.elevate_${e.action}`),run:()=>{if(!O(ae,e.values,e.deleteKey))return!1;const t=ge(ce),o="remove"===e.action?Object.keys(e.values).every(e=>!t?.has(e)):Object.keys(e.values).every(e=>t?.has(e));return o&&(Q=null,Y=null),o}}:null},unloadPrivateConfig(){if(me())try{ke(De)}catch(e){u.logError("claude-desktop.removePolicy",e)}const e=J(),t=B(e);if(!e||!t)return;b(K(t.id)),s(K(t.id),{force:!0});const o=e.entries.filter(e=>e.id!==t.id);0===o.length?(b(G()),s(G(),{force:!0})):H(G(),{...e,entries:o,appliedId:e.appliedId===t.id?o[0].id:e.appliedId})},listedModels(){const e=J(),t=B(e);if(!t||e?.appliedId!==t.id)return null;const o=F(K(t.id))?.inferenceModels;return Array.isArray(o)?o.map(e=>String(e.name)):null},refreshModelMenu(e){const t=J(),o=B(t);if(!o||t?.appliedId!==o.id)return;const n=F(K(o.id));if(!n)return;const r=buildInferenceModels(e.models,e.catalog),s=JSON.stringify(n.inferenceModels)!==JSON.stringify(r),i={...le(n),inferenceModels:r},l=JSON.stringify(i)!==JSON.stringify(n);Q=null;const a=me()?ge(ce):null;if(!a?.has("inferenceModels"))return void(l&&H(K(o.id),i));const c=De.filter(e=>a.has(e)),d=!0!==e.settings?.force_registry&&_e();if(l&&H(K(o.id),i),d||s)try{d?ke(De):he({inferenceModels:r})}catch(e){throw u.logError("claude-desktop.refreshModelMenu registry",e),Q=d?{action:"remove",values:Object.fromEntries(c.map(e=>[e,null])),deleteKey:c.length===a.size}:{action:"write",values:{inferenceModels:r},deleteKey:!1},new S(y.t("tools.claude_desktop.refresh_needs_admin"))}},detectCurrentConfig(){try{if(me()){const e=ge(ce)?.get("inferenceGatewayApiKey");if(e)return{apiKey:e}}const e=B(J());if(!e)return{apiKey:null};const t=F(K(e.id)),o=t?.inferenceGatewayApiKey;return{apiKey:"string"==typeof o&&o?o:null}}catch(e){return u.logError("claude-desktop.detectCurrentConfig",e),{apiKey:null}}},getConfig(){try{const e=J(),t=B(e);return{meta:e,applied:t?F(K(t.id)):null,desktop:F(U()),...me()?{policy:Object.fromEntries(ge(ce)??[])}:{}}}catch(e){return u.logError("claude-desktop.getConfig",e),null}},clearPinnedModels(){let e=!1;me()&&ge(ce)?.has("inferenceModels")&&(ye(),fe(["delete",ce,"/v","inferenceModels","/f"]),e=!0);const t=B(J()),o=t?F(K(t.id)):null;if(t&&o&&void 0!==o.inferenceModels){const{inferenceModels:n,...r}=o;H(K(t.id),r),e=!0}return e?["inferenceModels"]:[]},applyNotes(){const e=[];if(Z&&Z.models.length>0){const{models:t,source:o,groups:n}=Z;e.push({kind:"summary",text:y.t("tools.claude_desktop.models_summary",{count:String(t.length),default:t[0].labelOverride??t[0].name})}),e.push({kind:"detail",text:y.t(`tools.claude_desktop.models_written_${o}`,{count:String(t.length),list:t.map(e=>`${e.labelOverride}${e.supports1m?" (1M)":""}`).join(", "),groups:n.join(" / ")})})}null!==q&&e.push({kind:"detail",text:y.t(q?"tools.claude_desktop.official_login_hidden":"tools.claude_desktop.official_login_shown")}),w()&&!E()||e.push({kind:"action",text:y.t("tools.claude_desktop.restart_hint")}),Q?(e.push({kind:"action",text:y.t(`tools.claude_desktop.policy_stale_${Q.action}`)}),e.push({kind:"detail",text:Y??""})):Y?(e.push({kind:"detail",text:y.t("tools.claude_desktop.registry_denied")}),e.push({kind:"detail",text:Y})):me()&&X&&e.push({kind:"detail",text:y.t(`tools.claude_desktop.registry_${X}`,{key:ce})});const t=detectManagedConfig();return t&&e.push({kind:"action",text:y.t("tools.claude_desktop.managed_conflict",{path:t})}),e},forceResetPaths(){const e=[G(),U()];try{const t=B(J());t&&e.push(K(t.id))}catch{}return e},backupPaths(){const e=[G(),U()];me()&&e.push(l(claudeDesktopUserDataDir(),pe));try{const t=B(J());t&&e.push(K(t.id))}catch{}return e}};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xship/cli",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "description": "Configure Claude Code, Codex, Grok Build and other coding tools for Xship AI with one command",
5
5
  "main": "dist/index.js",
6
6
  "bin": {