@manan_joshi/atelier 0.1.3 → 0.1.5

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.
Files changed (3) hide show
  1. package/README.md +3 -0
  2. package/dist/index.js +16 -11
  3. package/package.json +2 -1
package/README.md CHANGED
@@ -30,6 +30,9 @@ atl login
30
30
  atl whoami
31
31
  atl scan
32
32
  atl save <id-or-path>
33
+ atl apply <id-or-path> --preview
34
+ atl apply <id-or-path> --backup
35
+ atl profile switch <name> --preview
33
36
  atl saved list
34
37
  atl saved show <stable-id>
35
38
  atl logout
package/dist/index.js CHANGED
@@ -1,13 +1,18 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
- import{stdin as $,stdout as G}from"process";import{existsSync as Ct,readFileSync as St}from"fs";import{homedir as rn,platform as nn}from"os";import{join as q,resolve as on}from"path";import{Command as an}from"commander";import{execFileSync as j}from"child_process";import{chmodSync as $e,existsSync as ee,mkdirSync as Ae,readFileSync as me,rmSync as Mt,writeFileSync as ve}from"fs";import{homedir as _t,platform as Xt}from"os";import{dirname as xe,join as te}from"path";var Ce=te(_t(),".config","atelier"),w=te(Ce,"session.json"),C=te(Ce,"config.json"),re="dev.atelier.session",Yt="https://atelier.mananjoshi.me/api",Jt="Ov23liiscZlMXcJ2RLnd";function J(){return process.env.ATELIER_API_URL??Yt}function Wt(){return process.env.ATELIER_GITHUB_CLIENT_ID??Jt}async function Se(e){let t=e.apiUrl??J(),r=e.clientId??Wt(),n=await Qt(r);await e.onPrompt({verificationUri:n.verification_uri,userCode:n.user_code,expiresIn:n.expires_in});let i=await Ot(r,n,e.onPoll),a=await fetch(`${t}/auth/github/exchange`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({githubAccessToken:i})});if(!a.ok)throw new Error(`Atelier API rejected GitHub login (${a.status})`);let c=await a.json();return It({apiUrl:t,user:c.user,token:c.token}),{apiUrl:t,user:c.user}}async function Re(){let e=S();if(!e)return;let t=await fetch(`${e.apiUrl}/me`,{headers:{authorization:`Bearer ${e.token}`}});if(!t.ok)return;return{user:(await t.json()).user,apiUrl:e.apiUrl}}function S(){let e=W();if(!e)return;let t=Nt(e);if(!t)return;return{apiUrl:e.apiUrl,user:e.user,token:t}}function y(){return ke().activeProfile??"personal"}function ne(e){Lt({...ke(),activeProfile:e})}function Ue(){let e=W();if(e?.tokenStorage==="keychain")Ht(e.user.id);if(ee(w))Mt(w)}function W(){if(!ee(w))return;return JSON.parse(me(w,"utf-8"))}function ke(){if(!ee(C))return{};return JSON.parse(me(C,"utf-8"))}function Lt(e){Ae(xe(C),{recursive:!0}),ve(C,JSON.stringify(e,null,2)+`
4
- `,"utf-8"),$e(C,384)}function It(e){Ae(xe(w),{recursive:!0});let t=Xt()==="darwin",r={apiUrl:e.apiUrl,user:e.user,tokenStorage:t?"keychain":"file",createdAt:new Date().toISOString()};if(t)Gt(e.user.id,e.token);else r.token=e.token;ve(w,JSON.stringify(r,null,2)+`
5
- `,"utf-8"),$e(w,384)}function Nt(e){if(e.tokenStorage==="file")return e.token;return qt(e.user.id)}async function Qt(e){let t=await fetch("https://github.com/login/device/code",{method:"POST",headers:{accept:"application/json","content-type":"application/json"},body:JSON.stringify({client_id:e,scope:"read:user user:email"})});if(!t.ok)throw new Error(`GitHub device-code request failed (${t.status})`);return t.json()}async function Ot(e,t,r){let n=t.interval,i=Date.now()+t.expires_in*1000;while(Date.now()<i){await Ft(n*1000),await r?.("Waiting for GitHub authorization\u2026");let a=await fetch("https://github.com/login/oauth/access_token",{method:"POST",headers:{accept:"application/json","content-type":"application/json"},body:JSON.stringify({client_id:e,device_code:t.device_code,grant_type:"urn:ietf:params:oauth:grant-type:device_code"})});if(!a.ok)throw new Error(`GitHub token polling failed (${a.status})`);let c=await a.json();if(c.access_token)return c.access_token;if(c.error==="authorization_pending")continue;if(c.error==="slow_down"){n+=5;continue}if(c.error==="access_denied")throw new Error("GitHub login was denied");if(c.error==="expired_token")throw new Error("GitHub login code expired");throw new Error(c.error_description??"GitHub login failed")}throw new Error("GitHub login timed out")}function Gt(e,t){j("security",["add-generic-password","-a",e,"-s",re,"-w",t,"-U"],{stdio:"ignore"})}function qt(e){try{return j("security",["find-generic-password","-a",e,"-s",re,"-w"],{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim()}catch{return}}function Ht(e){try{j("security",["delete-generic-password","-a",e,"-s",re],{stdio:"ignore"})}catch{}}function Ft(e){return new Promise((t)=>setTimeout(t,e))}async function Ze(){return(await(await p("/profiles")).json()).profiles}async function Me(e){return(await(await p("/profiles",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({name:e})})).json()).profile}async function R(e){let t=await p(`/profiles/${encodeURIComponent(e)}`);if(t.status===404)return;return(await t.json()).profile}async function U(){return await(await p("/vault")).json()}async function _e(e){await p("/vault",{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}async function Xe(e){let t=await p(`/profiles/${encodeURIComponent(e)}/key`);if(t.status===404)return;return(await t.json()).profileKey}async function oe(e,t){return(await(await p(`/profiles/${encodeURIComponent(e)}/key`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify(t)})).json()).profileKey}async function Ye(e){return(await(await p(`/profiles/${encodeURIComponent(e)}/configs`)).json()).configs}async function Je(e,t){let r=await p(`/profiles/${encodeURIComponent(e)}/configs/${encodeURIComponent(t)}`);if(r.status===404)return;return(await r.json()).config}async function We(e,t,r){return await(await p(`/profiles/${encodeURIComponent(e)}/configs/${encodeURIComponent(t)}/versions`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(r)})).json()}async function p(e,t={}){let r=S();if(!r)throw new Error("Not logged in. Run `atl login`.");let n=await fetch(`${r.apiUrl}${e}`,{...t,headers:{...t.headers,authorization:`Bearer ${r.token}`}});if(!n.ok&&n.status!==404){let i=await n.json().catch(()=>{return});throw new Error(i?.error??`Atelier API request failed (${n.status})`)}return n}import{createCipheriv as yr,createHash as br,randomBytes as pr}from"crypto";import{readFile as wr}from"fs/promises";import{execFileSync as le}from"child_process";import{createCipheriv as Pt,createDecipheriv as Vt,randomBytes as k,scryptSync as Dt}from"crypto";import{chmodSync as Et,existsSync as Ie,mkdirSync as jt,readFileSync as er,rmSync as tr,writeFileSync as rr}from"fs";import{homedir as nr,platform as se}from"os";import{dirname as or,join as Ne}from"path";var fe="dev.atelier.vault",ir=Ne(nr(),".config","atelier"),h=Ne(ir,"vault-key.json"),Le={N:32768,r:8,p:1},ar=67108864,ie="aes-256-gcm";async function ge(){let e=A();return{initialized:(await U()).initialized,unlocked:Boolean(ce(e.user.id)),activeProfile:y()}}async function ue(e,t=y()){lr(e);let r=A();if((await U()).initialized)throw new Error("Atelier vault already exists. Run `atl vault unlock` if this machine is locked.");let i=await R(t);if(!i)throw new Error(`Profile not found: ${t}`);let a=k(32),c=k(32),d=k(16),D=He(e,d,Le),E=ae(a,D),x=ae(c,a);return await _e({kdf:{algorithm:"scrypt",salt:L(d),params:Le},encryptedVaultKey:E}),await oe(t,{version:1,algorithm:x.algorithm,nonce:x.nonce,encryptedKey:x.ciphertext}),de(r.user.id,a),{profileName:i.name}}async function Qe(e){let t=A(),r=await U();if(!r.initialized)throw new Error("Atelier vault is not initialized. Run `atl save <id>` or `atl vault init`.");let n=qe(r,e);return de(t.user.id,n),{activeProfile:y()}}function Oe(){let e=A();sr(e.user.id)}async function cr(e,t=y()){let r=A(),n=ce(r.user.id);if(n)return n;if(!e)throw new Error("Vault passphrase is required");let i=await U();if(!i.initialized){await ue(e,t);let a=ce(r.user.id);if(!a)throw new Error("Vault initialized but local key was not stored");return a}return qe(i,e)}async function Ge(e,t=y()){let r=await cr(e,t),n=await Xe(t);if(n)return Fe(n.encryptedKey,n.nonce,r);let i=k(32),a=ae(i,r);return await oe(t,{version:1,algorithm:a.algorithm,nonce:a.nonce,encryptedKey:a.ciphertext}),i}function qe(e,t){if(!e.kdf||!e.encryptedVaultKey)throw new Error("Vault payload is incomplete");if(e.kdf.algorithm!=="scrypt")throw new Error(`Unsupported vault KDF: ${e.kdf.algorithm}`);let r=I(e.kdf.salt),n=He(t,r,e.kdf.params),i=Fe(e.encryptedVaultKey.ciphertext,e.encryptedVaultKey.nonce,n);return de(A().user.id,i),i}function He(e,t,r){return Dt(e,t,32,{N:r.N,r:r.r,p:r.p,maxmem:ar})}function ae(e,t){let r=k(12),n=Pt(ie,t,r),i=Buffer.concat([n.update(e),n.final()]),a=n.getAuthTag();return{algorithm:ie,nonce:L(r),ciphertext:L(Buffer.concat([i,a]))}}function Fe(e,t,r){let n=Buffer.from(I(e)),i=Buffer.from(I(t)),a=n.subarray(0,-16),c=n.subarray(-16),d=Vt(ie,r,i);return d.setAuthTag(c),Buffer.concat([d.update(a),d.final()])}function lr(e){if(e.length<12)throw new Error("Vault passphrase must be at least 12 characters.")}function A(){let e=S();if(!e)throw new Error("Not logged in. Run `atl login`.");return e}function de(e,t){let r=L(t);if(se()==="darwin"){le("security",["add-generic-password","-a",e,"-s",fe,"-w",r,"-U"],{stdio:"ignore"});return}jt(or(h),{recursive:!0}),rr(h,JSON.stringify({userId:e,key:r},null,2)+`
6
- `,"utf-8"),Et(h,384)}function ce(e){let t=se()==="darwin"?fr(e):gr(e);return t?Buffer.from(I(t)):void 0}function sr(e){if(se()==="darwin"){try{le("security",["delete-generic-password","-a",e,"-s",fe],{stdio:"ignore"})}catch{}return}if(Ie(h))tr(h)}function fr(e){try{return le("security",["find-generic-password","-a",e,"-s",fe,"-w"],{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim()}catch{return}}function gr(e){if(!Ie(h))return;let t=JSON.parse(er(h,"utf-8"));return t.userId===e?t.key:void 0}function L(e){return Buffer.from(e).toString("base64url")}function I(e){return new Uint8Array(Buffer.from(e,"base64url"))}function Pe(e){let t=[];if(!e.exists)t.push("file does not exist");if(e.isDirectory||e.kind==="directory"||e.format==="directory")t.push("directory saving is not supported yet");if(e.kind==="generated")t.push("generated/cache files are not saved");if(e.kind==="private"||e.shareability==="private")t.push("private/auth files are blocked");if(e.secretFindings.length>0)t.push("detected secret material");if(e.size!==void 0&&e.size>1048576)t.push(`file is larger than ${dr(1048576)}`);if(ur(e))t.push("binary files are not supported yet");return{ok:t.length===0,reasons:t}}function ye(e){let t=Pe(e);if(!t.ok)throw new Error(`Cannot save ${e.id}: ${t.reasons.join("; ")}`)}function ur(e){if(e.previewSuppressedReason?.toLowerCase().includes("binary"))return!0;return["binary","sqlite","db"].includes(e.format.toLowerCase())}function dr(e){if(e<1024)return`${e} B`;let t=e/1024;if(t<1024)return`${Math.round(t)} KiB`;return`${Math.round(t/1024)} MiB`}var Ve="aes-256-gcm";async function je(e,t={}){ye(e);let r=y(),n=await Ge(t.passphrase,r),i=await wr(e.path),a=hr(i,n),c=await We(r,e.id,{kind:"file",pathHint:e.displayPath,contentSha256:De(i),ciphertextSha256:De(a.ciphertextBytes),sizeBytes:i.byteLength,algorithm:a.algorithm,profileKeyVersion:1,nonce:a.nonce,ciphertext:a.ciphertext});return{profileName:r,stableId:e.id,version:c.version,reused:c.reused}}function hr(e,t){let r=pr(12),n=yr(Ve,t,r),i=Buffer.concat([n.update(e),n.final()]),a=n.getAuthTag(),c=Buffer.concat([i,a]);return{algorithm:Ve,nonce:Ee(r),ciphertext:Ee(c),ciphertextBytes:c}}function De(e){return br("sha256").update(e).digest("hex")}function Ee(e){return Buffer.from(e).toString("base64url")}import{execFileSync as ct}from"child_process";import{existsSync as z,lstatSync as Tr,mkdirSync as $r,readdirSync as we,readFileSync as Z,statSync as m,writeFileSync as Ar}from"fs";import{homedir as mr,userInfo as vr}from"os";import{dirname as lt,join as B,relative as st,resolve as xr}from"path";var et=[{domain:"AI Tools",app:"Pi",items:[{id:"pi.dir",path:"~/.pi",kind:"directory",format:"directory",shareability:"machine-specific"}]},{domain:"Shell",app:"Starship",items:[{id:"starship.config",path:"~/.config/starship.toml",kind:"config",format:"toml",shareability:"shareable"}]},{domain:"Editors",app:"Zed",items:[{id:"zed.dir",path:"~/.config/zed",kind:"directory",format:"directory",shareability:"shareable"},{id:"zed.settings",path:"~/.config/zed/settings.json",kind:"config",format:"jsonc",shareability:"shareable"},{id:"zed.themes",path:"~/.config/zed/themes",kind:"config",format:"directory",shareability:"shareable"},{id:"zed.prompts",path:"~/.config/zed/prompts",kind:"generated",format:"directory",shareability:"machine-specific"}]},{domain:"Git",app:"Git",items:[{id:"git.config",path:"~/.gitconfig",kind:"config",format:"gitconfig",shareability:"machine-specific"},{id:"git.config-dir",path:"~/.config/git",kind:"directory",format:"directory",shareability:"machine-specific"},{id:"git.ignore",path:"~/.gitignore",kind:"config",format:"gitignore",shareability:"machine-specific"}]},{domain:"Private/Auth",app:"Credentials",privateByDefault:!0,items:[{id:"auth.ssh",path:"~/.ssh",kind:"private",format:"directory",shareability:"private"},{id:"auth.aws",path:"~/.aws",kind:"private",format:"directory",shareability:"private"},{id:"auth.gh",path:"~/.config/gh",kind:"private",format:"directory",shareability:"private"},{id:"auth.gcloud-adc",path:"~/.config/gcloud/application_default_credentials.json",kind:"private",format:"json",shareability:"private"},{id:"auth.docker",path:"~/.docker/config.json",kind:"private",format:"json",shareability:"private"},{id:"auth.pi",path:"~/.config/pi/auth.json",kind:"private",format:"json",shareability:"private"}]},{domain:"Shell",app:"Zsh",items:[{id:"zsh.home-rc",path:"~/.zshrc",kind:"config",format:"shell",shareability:"shareable"},{id:"zsh.home-env",path:"~/.zshenv",kind:"config",format:"shell",shareability:"private"},{id:"zsh.dir",path:"~/.config/zsh",kind:"directory",format:"directory",shareability:"machine-specific"},{id:"zsh.env",path:"~/.config/zsh/.zshenv",kind:"config",format:"shell",shareability:"private"},{id:"zsh.rc",path:"~/.config/zsh/.zshrc",kind:"config",format:"shell",shareability:"shareable"},{id:"zsh.conf",path:"~/.config/zsh/conf.d",kind:"directory",format:"directory",shareability:"shareable"},{id:"zsh.zcompdump",path:"~/.config/zsh/.zcompdump",kind:"generated",format:"text",shareability:"machine-specific"},{id:"zsh.sessions",path:"~/.config/zsh/.zsh_sessions",kind:"generated",format:"directory",shareability:"machine-specific"}]},{domain:"Terminals",app:"cmux",items:[{id:"cmux.dir",path:"~/.config/cmux",kind:"directory",format:"directory",shareability:"shareable"},{id:"cmux.config",path:"~/.config/cmux/cmux.json",kind:"config",format:"jsonc",shareability:"shareable"},{id:"cmux.ghostty",path:"~/Library/Application Support/com.cmuxterm.app/config.ghostty",kind:"config",format:"ghostty",shareability:"shareable"},{id:"cmux.browser-history",path:"~/Library/Application Support/com.cmuxterm.app/browser_history.json",kind:"generated",format:"json",shareability:"machine-specific"}]}];var be=[["GitHub token",/gh[pousr]_[A-Za-z0-9_]{20,}/g],["Slack token",/xox[baprs]-[A-Za-z0-9-]{20,}/g],["AWS access key",/AKIA[0-9A-Z]{16}/g],["Private key",/-----BEGIN (?:RSA |OPENSSH |EC |DSA )?PRIVATE KEY-----/g],["Generic token assignment",/(?:token|api[_-]?key|secret|webhook|password)\s*[=:]\s*["']?[^"'\s]{12,}/gi]];function tt(e){let t=[],r=e.split(/\r?\n/);for(let[n,i]of be)for(let a of e.matchAll(i)){let c=a.index??0,d=e.slice(0,c).split(/\r?\n/).length;t.push({type:n,line:d,preview:N(a[0])})}return r.forEach((n,i)=>{for(let a of n.matchAll(/[A-Za-z0-9_+\/=.-]{32,}/g)){let c=a[0];if(!Br(c,n)&&nt(c,n))t.push({type:"High-entropy string",line:i+1,preview:N(c)})}}),Kr(t)}function N(e){if(e.length<=8)return"[redacted]";return`${e.slice(0,4)}\u2026${e.slice(-4)}`}function rt(e){let t=e;for(let[,r]of be)t=t.replace(r,(n)=>N(n));return t=t.replace(/[A-Za-z0-9_+\/=.-]{32,}/g,(r)=>{if(nt(r,e))return N(r);return r}),t}function Br(e,t){return be.some(([,r])=>{return r.lastIndex=0,Array.from(t.matchAll(r)).some((n)=>n[0].includes(e)||e.includes(n[0]))})}function nt(e,t){if(e.startsWith("amazon."))return!1;if(e.includes("anthropic.claude"))return!1;if(/^[A-Za-z0-9.-]+@[A-Za-z0-9.-]+$/.test(e))return!1;if(/model/i.test(t)&&/^[A-Za-z0-9_.-]+$/.test(e))return!1;return zr(e)>4.2&&/[A-Za-z]/.test(e)&&/[0-9]/.test(e)}function zr(e){let t=new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);let r=0;for(let n of t.values()){let i=n/e.length;r-=i*Math.log2(i)}return r}function Kr(e){let t=new Set;return e.filter((r)=>{let n=`${r.type}:${r.line}:${r.preview}`;if(t.has(n))return!1;return t.add(n),!0})}function ot(e){let n=e.replace(/\/\*[\s\S]*?\*\//g,"").replace(/(^|[^:])\/\/.*$/gm,"$1").replace(/,\s*([}\]])/g,"$1");return JSON.parse(n)}var K=mr(),Cr=new Set([".zsh",".zshrc",".zshenv",".sh",".json",".jsonc",".toml",".md",".yml",".yaml",".gitconfig",".gitignore",".ghostty",""]),Sr=[/cache/i,/history/i,/session/i,/state/i,/\.mdb$/i,/\.sqlite/i,/\.db$/i,/zcompdump/i,/logs?/i],Rr=[/credential/i,/secret/i,/token/i,/auth\.json$/i,/hosts\.yml$/i,/config\.json$/i],O;async function ft(e){O=e.includeLegacyManagers?Nr():void 0;let r=Ur(e.repoRoot).flatMap((a)=>a.items.map((c)=>({definition:a,item:c}))),n=new Set,i=[];for(let{definition:a,item:c}of r){let d=pe(c.path);n.add(d),i.push(kr(a,c,d))}for(let a of Zr()){if(n.has(a.path))continue;n.add(a.path),i.push(it(a))}for(let a of e.manualPaths??[]){let c=pe(a);if(n.has(c))continue;n.add(c),i.push(it({path:c,reason:"manual path"}))}return i.sort((a,c)=>`${a.domain}:${a.app}:${a.path}`.localeCompare(`${c.domain}:${c.app}:${c.path}`)),{version:1,generatedAt:new Date().toISOString(),repoRoot:e.repoRoot,home:K,items:i,summary:{total:i.length,existing:i.filter((a)=>a.exists).length,secrets:i.filter((a)=>a.secretFindings.length>0).length,drift:i.filter((a)=>a.mirrors.some((c)=>c.exists&&c.identical===!1)).length,generated:i.filter((a)=>a.kind==="generated").length,private:i.filter((a)=>a.shareability==="private").length}}}function gt(e,t={}){let r=t.path??B(e.repoRoot,".atelier","state","inventory.json");return $r(lt(r),{recursive:!0}),Ar(r,JSON.stringify(e,null,2)+`
7
- `,"utf-8"),r}function Ur(e){let t=B(e,"packages","registry","definitions");if(!z(t))return et;return we(t).filter((r)=>r.endsWith(".jsonc")).map((r)=>ot(Z(B(t,r),"utf-8")))}function kr(e,t,r){return ut({path:r,domain:e.domain,app:e.app,kind:t.kind,format:t.format,shareability:t.shareability,reason:"registry match",mirrors:t.mirrors??[],privateByDefault:e.privateByDefault,id:t.id})}function it(e){let t=Or(e.path),r=qr(e.path),n=Hr(e.path,r);return ut({path:e.path,domain:Gr(e.path),app:t,kind:r,format:Fr(e.path),shareability:n,reason:e.reason,mirrors:[],privateByDefault:n==="private"})}function ut(e){let t=z(e.path),r=t?Tr(e.path):void 0,n=t?m(e.path):void 0,i=!!n?.isDirectory(),a=!!r?.isSymbolicLink(),c=t&&!i&&dt(e.path)?tt(Z(e.path,"utf-8")):[],d=e.mirrors.map((x)=>_r(e.path,pe(x))),D=Jr(e.kind,e.shareability,c.length,d),E=Yr(e.path,t,i,e.shareability,e.privateByDefault,e.kind);return{id:e.id??Qr(e.path),domain:e.domain,app:e.app,path:e.path,displayPath:M(e.path),kind:e.kind,format:e.format,shareability:e.shareability,exists:t,isDirectory:i,isSymlink:a,mode:n?`0${(n.mode&511).toString(8)}`:void 0,owner:t?vr().username:void 0,size:n?.size,git:t?Wr(e.path):void 0,legacyManagers:t?Lr(e.path):{},mirrors:d,secretFindings:c,...E,recommendation:D,reason:e.reason}}function Zr(){let e=[],t=B(K,".config");if(!z(t))return e;for(let r of we(t,{withFileTypes:!0})){if(r.name.startsWith("."))continue;let n=B(t,r.name);if(e.push({path:n,reason:"~/.config app directory"}),!r.isDirectory())continue;for(let i of Mr(n).slice(0,80)){let a=B(n,i.name);if(he(a)){e.push({path:a,reason:"generated/app-state candidate"});continue}if(i.isFile()&&Be(i.name))e.push({path:a,reason:"shallow ~/.config config candidate"});if(i.isDirectory()&&["conf.d","themes","snippets","plugins"].includes(i.name))e.push({path:a,reason:"shallow ~/.config config directory"})}}return e}function Mr(e){try{return we(e,{withFileTypes:!0})}catch{return[]}}function _r(e,t){let r=z(t);if(!r||!z(e)||m(e).isDirectory()||m(t).isDirectory())return{path:t,displayPath:M(t),exists:r};let n=Z(e,"utf-8"),i=Z(t,"utf-8");return{path:t,displayPath:M(t),exists:r,identical:n===i,diff:n===i?void 0:Xr(i,n)}}function Xr(e,t){let r=e.split(/\r?\n/),n=t.split(/\r?\n/),i=Math.max(r.length,n.length),a=[];for(let c=0;c<i;c++){if(r[c]===n[c])continue;if(r[c]!==void 0)a.push(`-${r[c]}`);if(n[c]!==void 0)a.push(`+${n[c]}`)}return a.slice(0,200).join(`
8
- `)}function Yr(e,t,r,n,i,a){if(!t)return{previewSuppressedReason:"missing"};if(r)return{previewSuppressedReason:"directory"};if(n==="private"||i||a==="private")return{previewSuppressedReason:"private/auth metadata-only"};if(!dt(e))return{previewSuppressedReason:"binary or unsupported file type"};let c=Z(e,"utf-8");return{preview:rt(c).slice(0,20000)}}function Jr(e,t,r,n){if(r>0)return"rotate-secret";if(e==="generated")return"ignore-generated";if(t==="private")return"mark-private";if(n.some((i)=>i.exists&&i.identical===!1))return"resolve-drift";if(t==="machine-specific")return"review-machine-specific";if(e==="config"||e==="directory")return"adopt-candidate";return"none"}function Wr(e){let t=m(e).isDirectory()?e:lt(e),r=Q(["rev-parse","--show-toplevel"],t);if(!r)return;let n=st(r,e),i=!!Q(["check-ignore","-q",n],r,!0),a=!!Q(["ls-files","--error-unmatch",n],r,!0),c=a&&!!Q(["status","--porcelain","--",n],r);return{root:r,tracked:a,modified:c,ignored:i}}function Lr(e){if(!O)return{};return{yadm:Ir(e)}}function Ir(e){let t=M(e).replace(/^~\//,"");if(O?.modified.has(t))return"modified";if(O?.tracked.has(t))return"tracked";return"unknown"}function Nr(){let e=new Set((at("yadm",["ls-files"])??"").split(`
9
- `).filter(Boolean)),t=new Set((at("yadm",["status","--porcelain"])??"").split(`
10
- `).map((r)=>r.slice(3).trim()).filter(Boolean));return{tracked:e,modified:t}}function Q(e,t,r=!1){try{return ct("git",e,{cwd:t,encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim()||(r?"ok":void 0)}catch{return}}function at(e,t){try{return ct(e,t,{cwd:K,encoding:"utf-8",stdio:["ignore","pipe","ignore"]})}catch{return}}function pe(e){return xr(e.replace(/^~(?=\/|$)/,K))}function M(e){return e.startsWith(K)?`~${e.slice(K.length)}`:e}function Qr(e){return M(e).replace(/[^A-Za-z0-9_.-]+/g,":")}function Or(e){let t=st(B(K,".config"),e);if(!t.startsWith(".."))return t.split(/[\\/]/)[0]||"Unknown";return"Unknown"}function Gr(e){if(e.includes("/.config/"))return"~/.config";if(e.includes("/.ssh")||e.includes("/.aws"))return"Private/Auth";return"Unknown"}function qr(e){if(he(e))return"generated";if(Rr.some((t)=>t.test(e)))return"private";if(z(e)&&m(e).isDirectory())return"directory";if(Be(e))return"config";return"unknown"}function Hr(e,t){if(t==="private")return"private";if(t==="generated")return"machine-specific";if(e.includes("/credentials")||e.includes("/.ssh")||e.includes("/.aws"))return"private";return"machine-specific"}function Fr(e){if(z(e)&&m(e).isDirectory())return"directory";if(e.endsWith(".jsonc"))return"jsonc";if(e.endsWith(".json"))return"json";if(e.endsWith(".toml"))return"toml";if(e.endsWith(".zsh"))return"shell";if(e.endsWith(".md"))return"markdown";return"text"}function he(e){return Sr.some((t)=>t.test(e))}function Be(e){return/(^config\.|settings\.|rc$|\.rc$|\.zshrc$|\.zshenv$|\.jsonc?$|\.toml$|\.ya?ml$|\.zsh$|\.conf$|\.ini$)/i.test(e)}function dt(e){let t=e.split("/").pop()??"";if(he(e))return!1;if(t.includes("lock")||t.endsWith(".mdb")||t.endsWith(".sqlite")||t.endsWith(".db"))return!1;let r=t.includes(".")?t.slice(t.lastIndexOf(".")):"";return Cr.has(r)||Be(t)}import{Box as s,Text as l,render as Pr}from"ink";import{jsxDEV as o,Fragment as tn}from"react/jsx-dev-runtime";function f(e){return Pr(o(tn,{children:e},void 0,!1,void 0,this)).waitUntilExit()}function ze({inventory:e,path:t}){return o(s,{flexDirection:"column",gap:1,children:[o(b,{title:"Scan complete",subtitle:t},void 0,!1,void 0,this),o(s,{gap:2,children:[o(v,{label:"total",value:e.summary.total,color:"cyan"},void 0,!1,void 0,this),o(v,{label:"existing",value:e.summary.existing,color:"green"},void 0,!1,void 0,this),o(v,{label:"private",value:e.summary.private,color:"red"},void 0,!1,void 0,this),o(v,{label:"generated",value:e.summary.generated,color:"magenta"},void 0,!1,void 0,this),o(v,{label:"secrets",value:e.summary.secrets,color:"red"},void 0,!1,void 0,this),o(v,{label:"drift",value:e.summary.drift,color:"blue"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function yt({items:e,title:t}){return o(s,{flexDirection:"column",children:[o(b,{title:t,subtitle:`${e.length} item${e.length===1?"":"s"}`},void 0,!1,void 0,this),o(s,{flexDirection:"column",marginTop:1,children:e.map((r)=>o(s,{gap:1,children:[o(l,{color:r.exists?"white":"gray",children:r.exists?"\u25CF":"\u25CB"},void 0,!1,void 0,this),o(l,{color:mt(r),children:r.domain},void 0,!1,void 0,this),o(l,{color:"gray",children:"/"},void 0,!1,void 0,this),o(l,{color:"cyan",children:r.app},void 0,!1,void 0,this),o(l,{children:r.displayPath},void 0,!1,void 0,this),o(T,{label:r.shareability,color:vt(r.shareability)},void 0,!1,void 0,this),r.secretFindings.length>0?o(T,{label:"secret",color:"red"},void 0,!1,void 0,this):null,r.mirrors.some((n)=>n.exists&&n.identical===!1)?o(T,{label:"drift",color:"blue"},void 0,!1,void 0,this):null]},r.id,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function bt({item:e}){return o(s,{flexDirection:"column",gap:1,children:[o(b,{title:e.app,subtitle:e.displayPath},void 0,!1,void 0,this),o(s,{gap:1,children:[o(T,{label:e.domain,color:"cyan"},void 0,!1,void 0,this),o(T,{label:e.kind,color:mt(e)},void 0,!1,void 0,this),o(T,{label:e.shareability,color:vt(e.shareability)},void 0,!1,void 0,this),o(T,{label:e.recommendation,color:"yellow"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),o(Vr,{rows:[["reason",e.reason],["exists",String(e.exists)],["mode",e.mode??"\u2014"],["symlink",String(e.isSymlink)],["git",en(e)],["legacy",jr(e)]]},void 0,!1,void 0,this),e.secretFindings.length>0?o(s,{flexDirection:"column",children:[o(l,{color:"red",bold:!0,children:"Secret warnings"},void 0,!1,void 0,this),e.secretFindings.map((t,r)=>o(l,{color:"red",children:[" ",t.type,t.line?` line ${t.line}`:"",": ",t.preview]},`${t.type}-${r}`,!0,void 0,this))]},void 0,!0,void 0,this):null,e.mirrors.length>0?o(s,{flexDirection:"column",children:[o(l,{color:"blue",bold:!0,children:"Mirrors"},void 0,!1,void 0,this),e.mirrors.map((t)=>o(l,{children:[" ",t.displayPath," \u2014 ",t.exists?t.identical===!1?"differs":"identical":"missing"]},t.path,!0,void 0,this))]},void 0,!0,void 0,this):null,o(s,{flexDirection:"column",children:[o(l,{bold:!0,children:e.preview?"Safe preview":"Preview"},void 0,!1,void 0,this),o(l,{color:e.preview?"white":"gray",children:e.preview?e.preview.slice(0,3000):`Suppressed: ${e.previewSuppressedReason??"not available"}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function pt({verificationUri:e,userCode:t,expiresIn:r}){return o(s,{flexDirection:"column",gap:1,children:[o(b,{title:"Login with GitHub",subtitle:`code expires in ${Math.round(r/60)} minutes`},void 0,!1,void 0,this),o(s,{flexDirection:"column",children:[o(l,{children:"Open:"},void 0,!1,void 0,this),o(l,{color:"blue",underline:!0,children:e},void 0,!1,void 0,this)]},void 0,!0,void 0,this),o(s,{gap:1,children:[o(l,{children:"Enter code:"},void 0,!1,void 0,this),o(l,{color:"green",bold:!0,children:t},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function wt({login:e,apiUrl:t}){return o(s,{flexDirection:"column",children:[o(b,{title:"Logged in",subtitle:t},void 0,!1,void 0,this),o(l,{color:"green",children:["\u2713 ",e]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function ht({login:e,apiUrl:t}){if(!e)return o(l,{color:"yellow",children:"Not logged in. Run `atl login`."},void 0,!1,void 0,this);return o(s,{flexDirection:"column",children:[o(b,{title:"Current account",subtitle:t},void 0,!1,void 0,this),o(l,{color:"green",children:e},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Bt(){return o(l,{color:"green",children:"\u2713 Logged out"},void 0,!1,void 0,this)}function zt({profiles:e,activeProfile:t}){return o(s,{flexDirection:"column",children:[o(b,{title:"Profiles",subtitle:`active: ${t}`},void 0,!1,void 0,this),o(s,{flexDirection:"column",marginTop:1,children:e.map((r)=>o(s,{gap:1,children:[o(l,{color:r.name===t?"green":"gray",children:r.name===t?"\u25CF":"\u25CB"},void 0,!1,void 0,this),o(l,{bold:r.name===t,children:r.name},void 0,!1,void 0,this),o(l,{color:"gray",children:r.createdAt},void 0,!1,void 0,this)]},r.id,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function _({title:e,name:t}){return o(s,{flexDirection:"column",children:[o(b,{title:e},void 0,!1,void 0,this),o(l,{color:"green",children:["\u2713 ",t]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Kt({configs:e,profileName:t}){return o(s,{flexDirection:"column",children:[o(b,{title:"Saved configs",subtitle:t},void 0,!1,void 0,this),e.length===0?o(l,{color:"gray",children:"No saved configs yet."},void 0,!1,void 0,this):e.map((r)=>o(s,{flexDirection:"column",marginTop:1,children:[o(l,{bold:!0,children:r.stableId},void 0,!1,void 0,this),o(l,{color:"gray",children:r.pathHint??"no path hint"},void 0,!1,void 0,this),r.latestVersion?o(l,{color:"green",children:[r.latestVersion.contentSha256.slice(0,12)," \xB7 ",r.latestVersion.sizeBytes," bytes \xB7 ",r.latestVersion.createdAt]},void 0,!0,void 0,this):null]},r.id,!0,void 0,this))]},void 0,!0,void 0,this)}function Tt({config:e,profileName:t}){return o(s,{flexDirection:"column",children:[o(b,{title:e.stableId,subtitle:t},void 0,!1,void 0,this),o(l,{color:"gray",children:e.pathHint??"no path hint"},void 0,!1,void 0,this),o(s,{flexDirection:"column",marginTop:1,children:(e.versions??[]).map((r)=>o(l,{children:[r.contentSha256.slice(0,12)," \xB7 ",r.sizeBytes," bytes \xB7 ",r.createdAt]},r.id,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function $t({stableId:e,profileName:t,versionHash:r,sizeBytes:n,reused:i}){return o(s,{flexDirection:"column",children:[o(b,{title:i?"Config already saved":"Config saved",subtitle:t},void 0,!1,void 0,this),o(l,{color:"green",children:["\u2713 ",e]},void 0,!0,void 0,this),o(l,{color:"gray",children:["Version ",r.slice(0,12)," \xB7 ",n," bytes \xB7 encrypted"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function At({checks:e}){let t=e.filter((n)=>n.status==="fail").length,r=e.filter((n)=>n.status==="warn").length;return o(s,{flexDirection:"column",gap:1,children:[o(b,{title:"Doctor",subtitle:t?`${t} failing`:r?`${r} warning${r===1?"":"s"}`:"all checks passed"},void 0,!1,void 0,this),o(s,{flexDirection:"column",children:e.map((n)=>o(s,{gap:1,children:[o(l,{color:Er(n.status),children:Dr(n.status)},void 0,!1,void 0,this),o(l,{bold:!0,children:n.label},void 0,!1,void 0,this),o(l,{color:"gray",children:n.detail},void 0,!1,void 0,this)]},n.label,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Ke({query:e}){return o(l,{color:"red",children:["No inventory item matched: ",e]},void 0,!0,void 0,this)}function b({title:e,subtitle:t}){return o(s,{flexDirection:"column",children:[o(l,{bold:!0,color:"cyan",children:"\u25C6 Atelier"},void 0,!1,void 0,this),o(s,{gap:1,children:[o(l,{bold:!0,children:e},void 0,!1,void 0,this),t?o(l,{color:"gray",children:t},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function v({label:e,value:t,color:r}){return o(s,{flexDirection:"column",borderStyle:"round",borderColor:r,paddingX:1,children:[o(l,{color:r,bold:!0,children:t},void 0,!1,void 0,this),o(l,{color:"gray",children:e},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function T({label:e,color:t}){return o(l,{color:t,children:["[",e,"]"]},void 0,!0,void 0,this)}function Vr({rows:e}){return o(s,{flexDirection:"column",children:e.map(([t,r])=>o(s,{gap:1,children:[o(l,{color:"gray",children:t.padEnd(10)},void 0,!1,void 0,this),o(l,{children:r},void 0,!1,void 0,this)]},t,!0,void 0,this))},void 0,!1,void 0,this)}function mt(e){let t=typeof e==="string"?e:e.kind;if(t==="private")return"red";if(t==="generated")return"magenta";if(t==="config")return"green";return"yellow"}function vt(e){if(e==="private")return"red";if(e==="shareable")return"green";return"yellow"}function Dr(e){if(e==="pass")return"\u2713";if(e==="warn")return"!";return"\u2717"}function Er(e){if(e==="pass")return"green";if(e==="warn")return"yellow";return"red"}function jr(e){let t=Object.entries(e.legacyManagers??{});if(t.length===0)return"not scanned";return t.map(([r,n])=>`${r}: ${n}`).join(", ")}function en(e){if(!e.git)return"not in repo";return`${e.git.tracked?"tracked":"untracked"}${e.git.modified?", modified":""} @ ${e.git.root}`}import{jsxDEV as g}from"react/jsx-dev-runtime";var cn=on(import.meta.dir,"../../.."),Rt=ln(),X=q(Rt,"inventory.json"),xt,u=new an;u.name("atl").description("Atelier config management CLI").version("0.1.3");u.command("login").description("Login to Atelier with GitHub device auth").option("--api-url <url>","Atelier API URL",J()).action(async(e)=>{let t=await Se({apiUrl:e.apiUrl,onPrompt:async(r)=>{await f(g(pt,{verificationUri:r.verificationUri,userCode:r.userCode,expiresIn:r.expiresIn},void 0,!1,void 0,this))}});await f(g(wt,{login:t.user.login,apiUrl:t.apiUrl},void 0,!1,void 0,this))});u.command("whoami").description("Show the current Atelier account").action(async()=>{let e=await Re();if(await f(g(ht,{login:e?.user.login,apiUrl:e?.apiUrl},void 0,!1,void 0,this)),!e)process.exitCode=1});u.command("logout").description("Remove the local Atelier session").action(async()=>{Ue(),await f(g(Bt,{},void 0,!1,void 0,this))});var F=u.command("profile").description("Manage account-backed config profiles");F.command("list").description("List remote profiles").action(async()=>{await f(g(zt,{profiles:await Ze(),activeProfile:y()},void 0,!1,void 0,this))});F.command("create").description("Create a remote profile").argument("<name>").action(async(e)=>{let t=await Me(e);await f(g(_,{title:"Profile created",name:t.name},void 0,!1,void 0,this))});F.command("switch").description("Set the active local profile after verifying it exists remotely").argument("<name>").action(async(e)=>{let t=await R(e);if(!t)throw new Error(`Profile not found: ${e}`);ne(t.name),await f(g(_,{title:"Active profile",name:t.name},void 0,!1,void 0,this))});F.command("current").description("Show the active local profile").action(async()=>{await f(g(_,{title:"Active profile",name:y()},void 0,!1,void 0,this))});u.command("checkout").description("Alias for `atl profile switch`").argument("<name>").action(async(e)=>{let t=await R(e);if(!t)throw new Error(`Profile not found: ${e}`);ne(t.name),await f(g(_,{title:"Active profile",name:t.name},void 0,!1,void 0,this))});var P=u.command("vault").description("Advanced vault controls");P.command("status").description("Show vault initialization and local unlock state").action(async()=>{let e=await ge();console.log(`Vault: ${e.initialized?"initialized":"not initialized"}`),console.log(`Local state: ${e.unlocked?"unlocked":"locked"}`),console.log(`Active profile: ${e.activeProfile}`)});P.command("init").description("Initialize the encrypted vault now instead of waiting for first save").action(async()=>{let e=await kt("Create an Atelier vault passphrase: "),t=await ue(e);console.log(`Vault initialized for profile ${t.profileName}`)});P.command("unlock").description("Unlock this machine with the vault passphrase").action(async()=>{let e=await H("Vault passphrase: "),t=await Qe(e);console.log(`Vault unlocked for profile ${t.activeProfile}`)});P.command("lock").description("Remove local unlocked vault material from this machine").action(async()=>{Oe(),console.log("Vault locked")});u.command("save").description("Save a config snapshot to the active encrypted profile").argument("<id-or-path>").action(async(e)=>{await sn(e)});var Ut=u.command("saved").description("Inspect encrypted configs saved remotely");Ut.command("list").description("List saved configs for the active profile").action(async()=>{let e=y();await f(g(Kt,{configs:await Ye(e),profileName:e},void 0,!1,void 0,this))});Ut.command("show").description("Show saved metadata and version history").argument("<stable-id>").action(async(e)=>{let t=y(),r=await Je(t,e);if(!r)throw new Error(`Saved config not found: ${e}`);await f(g(Tt,{config:r,profileName:t},void 0,!1,void 0,this))});u.command("scan").description("Scan this machine and write local inventory").option("--path <path...>","additional manual path(s) to scan").option("--legacy","include legacy manager signals like yadm").action(async(e)=>{let t=await ft({repoRoot:cn,manualPaths:e.path??[],includeLegacyManagers:e.legacy}),r=gt(t,{path:X});await f(g(ze,{inventory:t,path:r},void 0,!1,void 0,this))});u.command("list").description("List inventory items with polished terminal output").option("--domain <domain>","filter by domain").option("--app <app>","filter by app").option("--secrets","only items with secret warnings").option("--drift","only items with mirror drift").option("--generated","only generated/app-state items").option("--private","only private items").option("--missing","only missing registry items").option("--json","print JSON instead of Ink output").action(async(e)=>{let t=Y(),r=fn(t.items,e);if(e.json)return V(r);await f(g(yt,{items:r,title:"Inventory"},void 0,!1,void 0,this))});u.command("inspect").description("Inspect one inventory item by id or path").argument("<id-or-path>").option("--json","print JSON instead of Ink output").action(async(e,t)=>{let r=Y(),n=Zt(r,e);if(t.json)return V(n??null);await f(n?g(bt,{item:n},void 0,!1,void 0,this):g(Ke,{query:e},void 0,!1,void 0,this))});u.command("summary").description("Print the last scan summary").option("--json","print JSON instead of Ink output").action(async(e)=>{let t=Y();if(e.json)return V(t.summary);await f(g(ze,{inventory:t,path:X},void 0,!1,void 0,this))});u.command("doctor").description("Check Atelier CLI, account, inventory, and local environment health").option("--json","print JSON instead of Ink output").action(async(e)=>{let t=gn();if(e.json)V(t);else await f(g(At,{checks:t},void 0,!1,void 0,this));if(t.some((r)=>r.status==="fail"))process.exitCode=1});u.parseAsync(process.argv).catch((e)=>{console.error(e instanceof Error?e.message:e),process.exit(1)});function V(e){console.log(JSON.stringify(e,null,2))}function Y(){if(!Ct(X))throw new Error("No inventory found. Run `atl scan` first.");return JSON.parse(St(X,"utf-8"))}function ln(){if(process.env.ATELIER_STATE_DIR)return process.env.ATELIER_STATE_DIR;if(process.env.XDG_STATE_HOME)return q(process.env.XDG_STATE_HOME,"atelier");if(nn()==="win32"&&process.env.LOCALAPPDATA)return q(process.env.LOCALAPPDATA,"Atelier");return q(rn(),".local","state","atelier")}async function sn(e){let t=Y(),r=Zt(t,e);if(!r){await f(g(Ke,{query:e},void 0,!1,void 0,this)),process.exitCode=1;return}let n=await ge(),i;if(!n.initialized)i=await kt("Create an Atelier vault passphrase: ");else if(!n.unlocked)i=await H("Vault passphrase: ");let a=await je(r,{passphrase:i});await f(g($t,{stableId:a.stableId,profileName:a.profileName,versionHash:a.version.contentSha256,sizeBytes:a.version.sizeBytes,reused:a.reused},void 0,!1,void 0,this))}async function kt(e){let t=await H(e),r=await H("Confirm vault passphrase: ");if(t!==r)throw new Error("Vault passphrases do not match");return t}async function H(e){if(!$.isTTY)return G.write(e),xt??=St(0,"utf-8").split(/\r?\n/),xt.shift()??"";G.write(e),$.setRawMode(!0),$.resume(),$.setEncoding("utf-8");let t="";try{for await(let r of $){let n=String(r);for(let i of n){if(i==="\x03")G.write(`
11
- `),process.exit(130);if(i==="\r"||i===`
12
- `)return G.write(`
13
- `),t;if(i==="\x7F"){t=t.slice(0,-1);continue}t+=i}}}finally{$.setRawMode(!1),$.pause()}return t}function fn(e,t){return e.filter((r)=>{if(t.domain&&r.domain.toLowerCase()!==t.domain.toLowerCase())return!1;if(t.app&&r.app.toLowerCase()!==t.app.toLowerCase())return!1;if(t.secrets&&r.secretFindings.length===0)return!1;if(t.drift&&!r.mirrors.some((n)=>n.exists&&n.identical===!1))return!1;if(t.generated&&r.kind!=="generated")return!1;if(t.private&&r.shareability!=="private")return!1;if(t.missing&&r.exists)return!1;return!0})}function Zt(e,t){let r=Te(t);return e.items.find((n)=>n.id===t||Te(n.path)===r||Te(n.displayPath)===r)??e.items.find((n)=>n.displayPath.includes(t)||n.path.includes(t))}function Te(e){return e.replace(/^~(?=\/|$)/,process.env.HOME??"").toLowerCase()}function gn(){let e=[],t=Ct(X)?Y():void 0,r=W();return e.push({label:"runtime",status:process.versions.bun?"pass":"fail",detail:process.versions.bun?`Bun ${process.versions.bun}`:"Bun is required"}),e.push({label:"api",status:"pass",detail:J()}),e.push({label:"session",status:r?"pass":"warn",detail:r?`logged in as ${r.user.login}`:"not logged in; run `atl login`"}),e.push({label:"state directory",status:"pass",detail:Rt}),e.push({label:"inventory",status:t?"pass":"warn",detail:t?`${t.summary.existing}/${t.summary.total} existing, generated ${t.generatedAt}`:"missing; run `atl scan`"}),e.push({label:"secret warnings",status:t&&t.summary.secrets>0?"warn":"pass",detail:t?`${t.summary.secrets} item${t.summary.secrets===1?"":"s"} flagged`:"no inventory"}),e}
3
+ import{stdin as B,stdout as E}from"process";import{existsSync as Et,readFileSync as jt}from"fs";import{homedir as Gn,platform as Fn}from"os";import{join as j,resolve as qn}from"path";import{Command as Vn}from"commander";import{createDecipheriv as Or,createHash as Jr}from"crypto";import{existsSync as Xr,mkdirSync as it}from"fs";import{copyFile as Wr,readFile as Yr,writeFile as Qr}from"fs/promises";import{homedir as we,platform as Hr}from"os";import{basename as Nr,dirname as ct,join as S,resolve as Gr}from"path";import{createPatch as Fr}from"diff";import{execFileSync as ne}from"child_process";import{chmodSync as ze,existsSync as oe,mkdirSync as Ke,readFileSync as Re,rmSync as cr,writeFileSync as Ue}from"fs";import{homedir as lr,platform as sr}from"os";import{dirname as _e,join as ae}from"path";var Ie=ae(lr(),".config","atelier"),T=ae(Ie,"session.json"),R=ae(Ie,"config.json"),ie="dev.atelier.session",fr="https://atelier.mananjoshi.me/api",ur="Ov23liiscZlMXcJ2RLnd";function W(){return process.env.ATELIER_API_URL??fr}function gr(){return process.env.ATELIER_GITHUB_CLIENT_ID??ur}async function Pe(e){let t=e.apiUrl??W(),r=e.clientId??gr(),n=await br(r);await e.onPrompt({verificationUri:n.verification_uri,userCode:n.user_code,expiresIn:n.expires_in});let a=await wr(r,n,e.onPoll),i=await fetch(`${t}/auth/github/exchange`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({githubAccessToken:a})});if(!i.ok)throw new Error(`Atelier API rejected GitHub login (${i.status})`);let c=await i.json();return pr({apiUrl:t,user:c.user,token:c.token}),{apiUrl:t,user:c.user}}async function Ze(){let e=U();if(!e)return;let t=await fetch(`${e.apiUrl}/me`,{headers:{authorization:`Bearer ${e.token}`}});if(!t.ok)return;return{user:(await t.json()).user,apiUrl:e.apiUrl}}function U(){let e=Y();if(!e)return;let t=yr(e);if(!t)return;return{apiUrl:e.apiUrl,user:e.user,token:t}}function y(){return Oe().activeProfile??"personal"}function Me(e){dr({...Oe(),activeProfile:e})}function Le(){let e=Y();if(e?.tokenStorage==="keychain")Ar(e.user.id);if(oe(T))cr(T)}function Y(){if(!oe(T))return;return JSON.parse(Re(T,"utf-8"))}function Oe(){if(!oe(R))return{};return JSON.parse(Re(R,"utf-8"))}function dr(e){Ke(_e(R),{recursive:!0}),Ue(R,JSON.stringify(e,null,2)+`
4
+ `,"utf-8"),ze(R,384)}function pr(e){Ke(_e(T),{recursive:!0});let t=sr()==="darwin",r={apiUrl:e.apiUrl,user:e.user,tokenStorage:t?"keychain":"file",createdAt:new Date().toISOString()};if(t)hr(e.user.id,e.token);else r.token=e.token;Ue(T,JSON.stringify(r,null,2)+`
5
+ `,"utf-8"),ze(T,384)}function yr(e){if(e.tokenStorage==="file")return e.token;return vr(e.user.id)}async function br(e){let t=await fetch("https://github.com/login/device/code",{method:"POST",headers:{accept:"application/json","content-type":"application/json"},body:JSON.stringify({client_id:e,scope:"read:user user:email"})});if(!t.ok)throw new Error(`GitHub device-code request failed (${t.status})`);return t.json()}async function wr(e,t,r){let n=t.interval,a=Date.now()+t.expires_in*1000;while(Date.now()<a){await Br(n*1000),await r?.("Waiting for GitHub authorization\u2026");let i=await fetch("https://github.com/login/oauth/access_token",{method:"POST",headers:{accept:"application/json","content-type":"application/json"},body:JSON.stringify({client_id:e,device_code:t.device_code,grant_type:"urn:ietf:params:oauth:grant-type:device_code"})});if(!i.ok)throw new Error(`GitHub token polling failed (${i.status})`);let c=await i.json();if(c.access_token)return c.access_token;if(c.error==="authorization_pending")continue;if(c.error==="slow_down"){n+=5;continue}if(c.error==="access_denied")throw new Error("GitHub login was denied");if(c.error==="expired_token")throw new Error("GitHub login code expired");throw new Error(c.error_description??"GitHub login failed")}throw new Error("GitHub login timed out")}function hr(e,t){ne("security",["add-generic-password","-a",e,"-s",ie,"-w",t,"-U"],{stdio:"ignore"})}function vr(e){try{return ne("security",["find-generic-password","-a",e,"-s",ie,"-w"],{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim()}catch{return}}function Ar(e){try{ne("security",["delete-generic-password","-a",e,"-s",ie],{stdio:"ignore"})}catch{}}function Br(e){return new Promise((t)=>setTimeout(t,e))}async function Je(){return(await(await h("/profiles")).json()).profiles}async function Xe(e){return(await(await h("/profiles",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({name:e})})).json()).profile}async function Q(e){let t=await h(`/profiles/${encodeURIComponent(e)}`);if(t.status===404)return;return(await t.json()).profile}async function _(){return await(await h("/vault")).json()}async function We(e){await h("/vault",{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}async function Ye(e){let t=await h(`/profiles/${encodeURIComponent(e)}/key`);if(t.status===404)return;return(await t.json()).profileKey}async function ce(e,t){return(await(await h(`/profiles/${encodeURIComponent(e)}/key`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify(t)})).json()).profileKey}async function I(e){return(await(await h(`/profiles/${encodeURIComponent(e)}/configs`)).json()).configs}async function H(e,t){let r=await h(`/profiles/${encodeURIComponent(e)}/configs/${encodeURIComponent(t)}`);if(r.status===404)return;return(await r.json()).config}async function Qe(e,t,r){return await(await h(`/profiles/${encodeURIComponent(e)}/configs/${encodeURIComponent(t)}/versions`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(r)})).json()}async function He(e,t,r){let n=await h(`/profiles/${encodeURIComponent(e)}/configs/${encodeURIComponent(t)}/versions/${encodeURIComponent(r)}/blob`);if(n.status===404)return;return await n.json()}async function h(e,t={}){let r=U();if(!r)throw new Error("Not logged in. Run `atl login`.");let n=await fetch(`${r.apiUrl}${e}`,{...t,headers:{...t.headers,authorization:`Bearer ${r.token}`}});if(!n.ok&&n.status!==404){let a=await n.json().catch(()=>{return});throw new Error(a?.error??`Atelier API request failed (${n.status})`)}return n}import{execFileSync as ue}from"child_process";import{createCipheriv as Tr,createDecipheriv as mr,randomBytes as P,scryptSync as kr}from"crypto";import{chmodSync as Cr,existsSync as Ge,mkdirSync as xr,readFileSync as $r,rmSync as Sr,writeFileSync as zr}from"fs";import{homedir as Kr,platform as ge}from"os";import{dirname as Rr,join as Fe}from"path";var de="dev.atelier.vault",Ur=Fe(Kr(),".config","atelier"),m=Fe(Ur,"vault-key.json"),Ne={N:32768,r:8,p:1},_r=67108864,le="aes-256-gcm";async function F(){let e=$();return{initialized:(await _()).initialized,unlocked:Boolean(fe(e.user.id)),activeProfile:y()}}async function pe(e,t=y()){Pr(e);let r=$();if((await _()).initialized)throw new Error("Atelier vault already exists. Run `atl vault unlock` if this machine is locked.");let a=await Q(t);if(!a)throw new Error(`Profile not found: ${t}`);let i=P(32),c=P(32),f=P(16),w=Ee(e,f,Ne),u=se(i,w),v=se(c,i);return await We({kdf:{algorithm:"scrypt",salt:N(f),params:Ne},encryptedVaultKey:u}),await ce(t,{version:1,algorithm:v.algorithm,nonce:v.nonce,encryptedKey:v.ciphertext}),ye(r.user.id,i),{profileName:a.name}}async function qe(e){let t=$(),r=await _();if(!r.initialized)throw new Error("Atelier vault is not initialized. Run `atl save <id>` or `atl vault init`.");let n=De(r,e);return ye(t.user.id,n),{activeProfile:y()}}function Ve(){let e=$();Zr(e.user.id)}async function Ir(e,t=y()){let r=$(),n=fe(r.user.id);if(n)return n;if(!e)throw new Error("Vault passphrase is required");let a=await _();if(!a.initialized){await pe(e,t);let i=fe(r.user.id);if(!i)throw new Error("Vault initialized but local key was not stored");return i}return De(a,e)}async function Z(e,t=y()){let r=await Ir(e,t),n=await Ye(t);if(n)return je(n.encryptedKey,n.nonce,r);let a=P(32),i=se(a,r);return await ce(t,{version:1,algorithm:i.algorithm,nonce:i.nonce,encryptedKey:i.ciphertext}),a}function De(e,t){if(!e.kdf||!e.encryptedVaultKey)throw new Error("Vault payload is incomplete");if(e.kdf.algorithm!=="scrypt")throw new Error(`Unsupported vault KDF: ${e.kdf.algorithm}`);let r=G(e.kdf.salt),n=Ee(t,r,e.kdf.params),a=je(e.encryptedVaultKey.ciphertext,e.encryptedVaultKey.nonce,n);return ye($().user.id,a),a}function Ee(e,t,r){return kr(e,t,32,{N:r.N,r:r.r,p:r.p,maxmem:_r})}function se(e,t){let r=P(12),n=Tr(le,t,r),a=Buffer.concat([n.update(e),n.final()]),i=n.getAuthTag();return{algorithm:le,nonce:N(r),ciphertext:N(Buffer.concat([a,i]))}}function je(e,t,r){let n=Buffer.from(G(e)),a=Buffer.from(G(t)),i=n.subarray(0,-16),c=n.subarray(-16),f=mr(le,r,a);return f.setAuthTag(c),Buffer.concat([f.update(i),f.final()])}function Pr(e){if(e.length<12)throw new Error("Vault passphrase must be at least 12 characters.")}function $(){let e=U();if(!e)throw new Error("Not logged in. Run `atl login`.");return e}function ye(e,t){let r=N(t);if(ge()==="darwin"){ue("security",["add-generic-password","-a",e,"-s",de,"-w",r,"-U"],{stdio:"ignore"});return}xr(Rr(m),{recursive:!0}),zr(m,JSON.stringify({userId:e,key:r},null,2)+`
6
+ `,"utf-8"),Cr(m,384)}function fe(e){let t=ge()==="darwin"?Mr(e):Lr(e);return t?Buffer.from(G(t)):void 0}function Zr(e){if(ge()==="darwin"){try{ue("security",["delete-generic-password","-a",e,"-s",de],{stdio:"ignore"})}catch{}return}if(Ge(m))Sr(m)}function Mr(e){try{return ue("security",["find-generic-password","-a",e,"-s",de,"-w"],{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim()}catch{return}}function Lr(e){if(!Ge(m))return;let t=JSON.parse($r(m,"utf-8"));return t.userId===e?t.key:void 0}function N(e){return Buffer.from(e).toString("base64url")}function G(e){return new Uint8Array(Buffer.from(e,"base64url"))}var qr="aes-256-gcm",Vr=new TextDecoder("utf-8",{fatal:!0});async function lt(e,t={}){let r=t.profileName??y(),n=await Dr(r,e);if(!n)throw new Error(`Saved config not found: ${e}`);let a=await Z(t.passphrase,r),i=await ut(r,n,a,{preview:t.preview});return await ft(i,t)}async function st(e,t={}){let n=(await I(e)).filter((u)=>u.kind==="file"&&u.pathHint&&gt(u));if(n.length===0)return{profileName:e,results:[],blocked:!1,preview:Boolean(t.preview),backup:Boolean(t.backup)};let a=await Z(t.passphrase,e),i=await Promise.all(n.map((u)=>ut(e,u,a,{preview:t.preview})));if(t.preview)return{profileName:e,results:i.map((u)=>u.result),blocked:!1,preview:!0,backup:Boolean(t.backup)};if(i.some((u)=>u.result.status==="update")&&!t.backup)return{profileName:e,results:i.map((u)=>u.result.status==="update"?{...u.result,status:"blocked",reason:"local file differs; rerun with --preview to inspect or --backup to replace safely"}:u.result),blocked:!0,preview:!1,backup:!1};let f=pt(),w=[];for(let u of i)w.push(await ft(u,{...t,backupRunId:f}));return{profileName:e,results:w,blocked:!1,preview:!1,backup:Boolean(t.backup)}}async function ft(e,t){let{result:r,savedBytes:n}=e;if(r.status==="unchanged")return r;if(r.status==="create"){if(!t.preview)await et(r.targetPath,n);return{...r,reason:t.preview?"would create missing local file":"created missing local file"}}if(t.preview)return r;if(!t.backup)return{...r,status:"blocked",reason:"local file differs; rerun with --preview to inspect or --backup to replace safely"};let a=await jr(r.stableId,r.targetPath,t.backupRunId??pt());return await et(r.targetPath,n),{...r,reason:"replaced differing local file after creating backup",backupPath:a}}async function ut(e,t,r,n){if(t.kind!=="file")throw new Error(`Cannot apply non-file config: ${t.stableId}`);if(!t.pathHint)throw new Error(`Saved config has no target path: ${t.stableId}`);let a=gt(t);if(!a)throw new Error(`Saved config has no versions: ${t.stableId}`);let i=await He(e,t.stableId,a.id);if(!i)throw new Error(`Saved config blob not found: ${t.stableId}`);let c=Er(i.ciphertext,i.version.nonce,r),f=dt(t.pathHint),w=t.pathHint,u=Xr(f),v=u?await Yr(f):void 0,Se=ot(c);if(Se!==a.contentSha256)throw new Error(`Saved content hash mismatch for ${t.stableId}`);if(!u)return{savedBytes:c,result:{profileName:e,stableId:t.stableId,targetPath:f,displayPath:w,status:"create",reason:n.preview?"would create missing local file":"created missing local file",diff:tt("",c,w),version:be(a)}};if(ot(v)===Se)return{savedBytes:c,result:{profileName:e,stableId:t.stableId,targetPath:f,displayPath:w,status:"unchanged",reason:"local file already matches saved version",version:be(a)}};return{savedBytes:c,result:{profileName:e,stableId:t.stableId,targetPath:f,displayPath:w,status:"update",reason:n.preview?"would replace differing local file":"local file differs",diff:tt(v,c,w),version:be(a)}}}async function Dr(e,t){let r=await H(e,t);if(r)return r;let n=nt(t);return(await I(e)).find((i)=>i.pathHint&&nt(i.pathHint)===n)}function gt(e){return e.latestVersion??e.versions?.[0]}function Er(e,t,r){let n=Buffer.from(e,"base64url"),a=Buffer.from(t,"base64url"),i=n.subarray(0,-16),c=n.subarray(-16),f=Or(qr,r,a);return f.setAuthTag(c),Buffer.concat([f.update(i),f.final()])}async function et(e,t){it(ct(e),{recursive:!0}),await Qr(e,t)}async function jr(e,t,r){let n=S(en(),r,at(e),at(t));return it(ct(n),{recursive:!0}),await Wr(t,n),n}function en(){if(process.env.ATELIER_STATE_DIR)return S(process.env.ATELIER_STATE_DIR,"backups");if(process.env.XDG_STATE_HOME)return S(process.env.XDG_STATE_HOME,"atelier","backups");if(Hr()==="win32"&&process.env.LOCALAPPDATA)return S(process.env.LOCALAPPDATA,"Atelier","backups");return S(we(),".local","state","atelier","backups")}function tt(e,t,r){let n=typeof e==="string"?e:rt(e),a=rt(t);if(n===void 0||a===void 0)return;return Fr(`local ${r}`,n,a,"local","saved").split(`
7
+ `).slice(2).join(`
8
+ `)}function rt(e){if(e.includes(0))return;try{return Vr.decode(e)}catch{return}}function dt(e){if(e==="~")return we();if(e.startsWith("~/"))return S(we(),e.slice(2));return Gr(e)}function nt(e){return dt(e).toLowerCase()}function ot(e){return Jr("sha256").update(e).digest("hex")}function be(e){return{id:e.id,contentSha256:e.contentSha256,sizeBytes:e.sizeBytes,createdAt:e.createdAt}}function pt(){return new Date().toISOString().replaceAll(":","-").replaceAll(".","-")}function at(e){return e.replace(/[^a-zA-Z0-9._-]+/g,"_").replace(/^_+|_+$/g,"")||Nr(e)||"item"}import{createCipheriv as nn,createHash as on,randomBytes as an}from"crypto";import{readFile as cn}from"fs/promises";function yt(e){let t=[];if(!e.exists)t.push("file does not exist");if(e.isDirectory||e.kind==="directory"||e.format==="directory")t.push("directory saving is not supported yet");if(e.kind==="generated")t.push("generated/cache files are not saved");if(e.kind==="private"||e.shareability==="private")t.push("private/auth files are blocked");if(e.secretFindings.length>0)t.push("detected secret material");if(e.size!==void 0&&e.size>1048576)t.push(`file is larger than ${rn(1048576)}`);if(tn(e))t.push("binary files are not supported yet");return{ok:t.length===0,reasons:t}}function he(e){let t=yt(e);if(!t.ok)throw new Error(`Cannot save ${e.id}: ${t.reasons.join("; ")}`)}function tn(e){if(e.previewSuppressedReason?.toLowerCase().includes("binary"))return!0;return["binary","sqlite","db"].includes(e.format.toLowerCase())}function rn(e){if(e<1024)return`${e} B`;let t=e/1024;if(t<1024)return`${Math.round(t)} KiB`;return`${Math.round(t/1024)} MiB`}var bt="aes-256-gcm";async function vt(e,t={}){he(e);let r=y(),n=await Z(t.passphrase,r),a=await cn(e.path),i=ln(a,n),c=await Qe(r,e.id,{kind:"file",pathHint:e.displayPath,contentSha256:wt(a),ciphertextSha256:wt(i.ciphertextBytes),sizeBytes:a.byteLength,algorithm:i.algorithm,profileKeyVersion:1,nonce:i.nonce,ciphertext:i.ciphertext});return{profileName:r,stableId:e.id,version:c.version,reused:c.reused}}function ln(e,t){let r=an(12),n=nn(bt,t,r),a=Buffer.concat([n.update(e),n.final()]),i=n.getAuthTag(),c=Buffer.concat([a,i]);return{algorithm:bt,nonce:ht(r),ciphertext:ht(c),ciphertextBytes:c}}function wt(e){return on("sha256").update(e).digest("hex")}function ht(e){return Buffer.from(e).toString("base64url")}import{execFileSync as $t}from"child_process";import{existsSync as C,lstatSync as gn,mkdirSync as dn,readdirSync as Be,readFileSync as M,statSync as z,writeFileSync as pn}from"fs";import{homedir as yn,userInfo as bn}from"os";import{dirname as St,join as k,relative as zt,resolve as wn}from"path";var At=[{domain:"AI Tools",app:"Pi",items:[{id:"pi.dir",path:"~/.pi",kind:"directory",format:"directory",shareability:"machine-specific"}]},{domain:"Shell",app:"Starship",items:[{id:"starship.config",path:"~/.config/starship.toml",kind:"config",format:"toml",shareability:"shareable"}]},{domain:"Editors",app:"Zed",items:[{id:"zed.dir",path:"~/.config/zed",kind:"directory",format:"directory",shareability:"shareable"},{id:"zed.settings",path:"~/.config/zed/settings.json",kind:"config",format:"jsonc",shareability:"shareable"},{id:"zed.themes",path:"~/.config/zed/themes",kind:"config",format:"directory",shareability:"shareable"},{id:"zed.prompts",path:"~/.config/zed/prompts",kind:"generated",format:"directory",shareability:"machine-specific"}]},{domain:"Git",app:"Git",items:[{id:"git.config",path:"~/.gitconfig",kind:"config",format:"gitconfig",shareability:"machine-specific"},{id:"git.config-dir",path:"~/.config/git",kind:"directory",format:"directory",shareability:"machine-specific"},{id:"git.ignore",path:"~/.gitignore",kind:"config",format:"gitignore",shareability:"machine-specific"}]},{domain:"Private/Auth",app:"Credentials",privateByDefault:!0,items:[{id:"auth.ssh",path:"~/.ssh",kind:"private",format:"directory",shareability:"private"},{id:"auth.aws",path:"~/.aws",kind:"private",format:"directory",shareability:"private"},{id:"auth.gh",path:"~/.config/gh",kind:"private",format:"directory",shareability:"private"},{id:"auth.gcloud-adc",path:"~/.config/gcloud/application_default_credentials.json",kind:"private",format:"json",shareability:"private"},{id:"auth.docker",path:"~/.docker/config.json",kind:"private",format:"json",shareability:"private"},{id:"auth.pi",path:"~/.config/pi/auth.json",kind:"private",format:"json",shareability:"private"}]},{domain:"Shell",app:"Zsh",items:[{id:"zsh.home-rc",path:"~/.zshrc",kind:"config",format:"shell",shareability:"shareable"},{id:"zsh.home-env",path:"~/.zshenv",kind:"config",format:"shell",shareability:"private"},{id:"zsh.dir",path:"~/.config/zsh",kind:"directory",format:"directory",shareability:"machine-specific"},{id:"zsh.env",path:"~/.config/zsh/.zshenv",kind:"config",format:"shell",shareability:"private"},{id:"zsh.rc",path:"~/.config/zsh/.zshrc",kind:"config",format:"shell",shareability:"shareable"},{id:"zsh.conf",path:"~/.config/zsh/conf.d",kind:"directory",format:"directory",shareability:"shareable"},{id:"zsh.zcompdump",path:"~/.config/zsh/.zcompdump",kind:"generated",format:"text",shareability:"machine-specific"},{id:"zsh.sessions",path:"~/.config/zsh/.zsh_sessions",kind:"generated",format:"directory",shareability:"machine-specific"}]},{domain:"Terminals",app:"cmux",items:[{id:"cmux.dir",path:"~/.config/cmux",kind:"directory",format:"directory",shareability:"shareable"},{id:"cmux.config",path:"~/.config/cmux/cmux.json",kind:"config",format:"jsonc",shareability:"shareable"},{id:"cmux.ghostty",path:"~/Library/Application Support/com.cmuxterm.app/config.ghostty",kind:"config",format:"ghostty",shareability:"shareable"},{id:"cmux.browser-history",path:"~/Library/Application Support/com.cmuxterm.app/browser_history.json",kind:"generated",format:"json",shareability:"machine-specific"}]}];var ve=[["GitHub token",/gh[pousr]_[A-Za-z0-9_]{20,}/g],["Slack token",/xox[baprs]-[A-Za-z0-9-]{20,}/g],["AWS access key",/AKIA[0-9A-Z]{16}/g],["Private key",/-----BEGIN (?:RSA |OPENSSH |EC |DSA )?PRIVATE KEY-----/g],["Generic token assignment",/(?:token|api[_-]?key|secret|webhook|password)\s*[=:]\s*["']?[^"'\s]{12,}/gi]];function Bt(e){let t=[],r=e.split(/\r?\n/);for(let[n,a]of ve)for(let i of e.matchAll(a)){let c=i.index??0,f=e.slice(0,c).split(/\r?\n/).length;t.push({type:n,line:f,preview:q(i[0])})}return r.forEach((n,a)=>{for(let i of n.matchAll(/[A-Za-z0-9_+\/=.-]{32,}/g)){let c=i[0];if(!sn(c,n)&&mt(c,n))t.push({type:"High-entropy string",line:a+1,preview:q(c)})}}),un(t)}function q(e){if(e.length<=8)return"[redacted]";return`${e.slice(0,4)}\u2026${e.slice(-4)}`}function Tt(e){let t=e;for(let[,r]of ve)t=t.replace(r,(n)=>q(n));return t=t.replace(/[A-Za-z0-9_+\/=.-]{32,}/g,(r)=>{if(mt(r,e))return q(r);return r}),t}function sn(e,t){return ve.some(([,r])=>{return r.lastIndex=0,Array.from(t.matchAll(r)).some((n)=>n[0].includes(e)||e.includes(n[0]))})}function mt(e,t){if(e.startsWith("amazon."))return!1;if(e.includes("anthropic.claude"))return!1;if(/^[A-Za-z0-9.-]+@[A-Za-z0-9.-]+$/.test(e))return!1;if(/model/i.test(t)&&/^[A-Za-z0-9_.-]+$/.test(e))return!1;return fn(e)>4.2&&/[A-Za-z]/.test(e)&&/[0-9]/.test(e)}function fn(e){let t=new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);let r=0;for(let n of t.values()){let a=n/e.length;r-=a*Math.log2(a)}return r}function un(e){let t=new Set;return e.filter((r)=>{let n=`${r.type}:${r.line}:${r.preview}`;if(t.has(n))return!1;return t.add(n),!0})}function kt(e){let n=e.replace(/\/\*[\s\S]*?\*\//g,"").replace(/(^|[^:])\/\/.*$/gm,"$1").replace(/,\s*([}\]])/g,"$1");return JSON.parse(n)}var x=yn(),hn=new Set([".zsh",".zshrc",".zshenv",".sh",".json",".jsonc",".toml",".md",".yml",".yaml",".gitconfig",".gitignore",".ghostty",""]),vn=[/cache/i,/history/i,/session/i,/state/i,/\.mdb$/i,/\.sqlite/i,/\.db$/i,/zcompdump/i,/logs?/i],An=[/credential/i,/secret/i,/token/i,/auth\.json$/i,/hosts\.yml$/i,/config\.json$/i],D;async function Kt(e){D=e.includeLegacyManagers?Un():void 0;let r=Bn(e.repoRoot).flatMap((i)=>i.items.map((c)=>({definition:i,item:c}))),n=new Set,a=[];for(let{definition:i,item:c}of r){let f=Ae(c.path);n.add(f),a.push(Tn(i,c,f))}for(let i of mn()){if(n.has(i.path))continue;n.add(i.path),a.push(Ct(i))}for(let i of e.manualPaths??[]){let c=Ae(i);if(n.has(c))continue;n.add(c),a.push(Ct({path:c,reason:"manual path"}))}return a.sort((i,c)=>`${i.domain}:${i.app}:${i.path}`.localeCompare(`${c.domain}:${c.app}:${c.path}`)),{version:1,generatedAt:new Date().toISOString(),repoRoot:e.repoRoot,home:x,items:a,summary:{total:a.length,existing:a.filter((i)=>i.exists).length,secrets:a.filter((i)=>i.secretFindings.length>0).length,drift:a.filter((i)=>i.mirrors.some((c)=>c.exists&&c.identical===!1)).length,generated:a.filter((i)=>i.kind==="generated").length,private:a.filter((i)=>i.shareability==="private").length}}}function Rt(e,t={}){let r=t.path??k(e.repoRoot,".atelier","state","inventory.json");return dn(St(r),{recursive:!0}),pn(r,JSON.stringify(e,null,2)+`
9
+ `,"utf-8"),r}function Bn(e){let t=k(e,"packages","registry","definitions");if(!C(t))return At;return Be(t).filter((r)=>r.endsWith(".jsonc")).map((r)=>kt(M(k(t,r),"utf-8")))}function Tn(e,t,r){return Ut({path:r,domain:e.domain,app:e.app,kind:t.kind,format:t.format,shareability:t.shareability,reason:"registry match",mirrors:t.mirrors??[],privateByDefault:e.privateByDefault,id:t.id})}function Ct(e){let t=In(e.path),r=Zn(e.path),n=Mn(e.path,r);return Ut({path:e.path,domain:Pn(e.path),app:t,kind:r,format:Ln(e.path),shareability:n,reason:e.reason,mirrors:[],privateByDefault:n==="private"})}function Ut(e){let t=C(e.path),r=t?gn(e.path):void 0,n=t?z(e.path):void 0,a=!!n?.isDirectory(),i=!!r?.isSymbolicLink(),c=t&&!a&&_t(e.path)?Bt(M(e.path,"utf-8")):[],f=e.mirrors.map((v)=>Cn(e.path,Ae(v))),w=Sn(e.kind,e.shareability,c.length,f),u=$n(e.path,t,a,e.shareability,e.privateByDefault,e.kind);return{id:e.id??_n(e.path),domain:e.domain,app:e.app,path:e.path,displayPath:L(e.path),kind:e.kind,format:e.format,shareability:e.shareability,exists:t,isDirectory:a,isSymlink:i,mode:n?`0${(n.mode&511).toString(8)}`:void 0,owner:t?bn().username:void 0,size:n?.size,git:t?zn(e.path):void 0,legacyManagers:t?Kn(e.path):{},mirrors:f,secretFindings:c,...u,recommendation:w,reason:e.reason}}function mn(){let e=[],t=k(x,".config");if(!C(t))return e;for(let r of Be(t,{withFileTypes:!0})){if(r.name.startsWith("."))continue;let n=k(t,r.name);if(e.push({path:n,reason:"~/.config app directory"}),!r.isDirectory())continue;for(let a of kn(n).slice(0,80)){let i=k(n,a.name);if(Te(i)){e.push({path:i,reason:"generated/app-state candidate"});continue}if(a.isFile()&&me(a.name))e.push({path:i,reason:"shallow ~/.config config candidate"});if(a.isDirectory()&&["conf.d","themes","snippets","plugins"].includes(a.name))e.push({path:i,reason:"shallow ~/.config config directory"})}}return e}function kn(e){try{return Be(e,{withFileTypes:!0})}catch{return[]}}function Cn(e,t){let r=C(t);if(!r||!C(e)||z(e).isDirectory()||z(t).isDirectory())return{path:t,displayPath:L(t),exists:r};let n=M(e,"utf-8"),a=M(t,"utf-8");return{path:t,displayPath:L(t),exists:r,identical:n===a,diff:n===a?void 0:xn(a,n)}}function xn(e,t){let r=e.split(/\r?\n/),n=t.split(/\r?\n/),a=Math.max(r.length,n.length),i=[];for(let c=0;c<a;c++){if(r[c]===n[c])continue;if(r[c]!==void 0)i.push(`-${r[c]}`);if(n[c]!==void 0)i.push(`+${n[c]}`)}return i.slice(0,200).join(`
10
+ `)}function $n(e,t,r,n,a,i){if(!t)return{previewSuppressedReason:"missing"};if(r)return{previewSuppressedReason:"directory"};if(n==="private"||a||i==="private")return{previewSuppressedReason:"private/auth metadata-only"};if(!_t(e))return{previewSuppressedReason:"binary or unsupported file type"};let c=M(e,"utf-8");return{preview:Tt(c).slice(0,20000)}}function Sn(e,t,r,n){if(r>0)return"rotate-secret";if(e==="generated")return"ignore-generated";if(t==="private")return"mark-private";if(n.some((a)=>a.exists&&a.identical===!1))return"resolve-drift";if(t==="machine-specific")return"review-machine-specific";if(e==="config"||e==="directory")return"adopt-candidate";return"none"}function zn(e){let t=z(e).isDirectory()?e:St(e),r=V(["rev-parse","--show-toplevel"],t);if(!r)return;let n=zt(r,e),a=!!V(["check-ignore","-q",n],r,!0),i=!!V(["ls-files","--error-unmatch",n],r,!0),c=i&&!!V(["status","--porcelain","--",n],r);return{root:r,tracked:i,modified:c,ignored:a}}function Kn(e){if(!D)return{};return{yadm:Rn(e)}}function Rn(e){let t=L(e).replace(/^~\//,"");if(D?.modified.has(t))return"modified";if(D?.tracked.has(t))return"tracked";return"unknown"}function Un(){let e=new Set((xt("yadm",["ls-files"])??"").split(`
11
+ `).filter(Boolean)),t=new Set((xt("yadm",["status","--porcelain"])??"").split(`
12
+ `).map((r)=>r.slice(3).trim()).filter(Boolean));return{tracked:e,modified:t}}function V(e,t,r=!1){try{return $t("git",e,{cwd:t,encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim()||(r?"ok":void 0)}catch{return}}function xt(e,t){try{return $t(e,t,{cwd:x,encoding:"utf-8",stdio:["ignore","pipe","ignore"]})}catch{return}}function Ae(e){return wn(e.replace(/^~(?=\/|$)/,x))}function L(e){return e.startsWith(x)?`~${e.slice(x.length)}`:e}function _n(e){return L(e).replace(/[^A-Za-z0-9_.-]+/g,":")}function In(e){let t=zt(k(x,".config"),e);if(!t.startsWith(".."))return t.split(/[\\/]/)[0]||"Unknown";return"Unknown"}function Pn(e){if(e.includes("/.config/"))return"~/.config";if(e.includes("/.ssh")||e.includes("/.aws"))return"Private/Auth";return"Unknown"}function Zn(e){if(Te(e))return"generated";if(An.some((t)=>t.test(e)))return"private";if(C(e)&&z(e).isDirectory())return"directory";if(me(e))return"config";return"unknown"}function Mn(e,t){if(t==="private")return"private";if(t==="generated")return"machine-specific";if(e.includes("/credentials")||e.includes("/.ssh")||e.includes("/.aws"))return"private";return"machine-specific"}function Ln(e){if(C(e)&&z(e).isDirectory())return"directory";if(e.endsWith(".jsonc"))return"jsonc";if(e.endsWith(".json"))return"json";if(e.endsWith(".toml"))return"toml";if(e.endsWith(".zsh"))return"shell";if(e.endsWith(".md"))return"markdown";return"text"}function Te(e){return vn.some((t)=>t.test(e))}function me(e){return/(^config\.|settings\.|rc$|\.rc$|\.zshrc$|\.zshenv$|\.jsonc?$|\.toml$|\.ya?ml$|\.zsh$|\.conf$|\.ini$)/i.test(e)}function _t(e){let t=e.split("/").pop()??"";if(Te(e))return!1;if(t.includes("lock")||t.endsWith(".mdb")||t.endsWith(".sqlite")||t.endsWith(".db"))return!1;let r=t.includes(".")?t.slice(t.lastIndexOf(".")):"";return hn.has(r)||me(t)}import{Box as s,Text as l,render as On}from"ink";import{jsxDEV as o,Fragment as Nn}from"react/jsx-dev-runtime";function g(e){return On(o(Nn,{children:e},void 0,!1,void 0,this)).waitUntilExit()}function ke({inventory:e,path:t}){return o(s,{flexDirection:"column",gap:1,children:[o(b,{title:"Scan complete",subtitle:t},void 0,!1,void 0,this),o(s,{gap:2,children:[o(K,{label:"total",value:e.summary.total,color:"cyan"},void 0,!1,void 0,this),o(K,{label:"existing",value:e.summary.existing,color:"green"},void 0,!1,void 0,this),o(K,{label:"private",value:e.summary.private,color:"red"},void 0,!1,void 0,this),o(K,{label:"generated",value:e.summary.generated,color:"magenta"},void 0,!1,void 0,this),o(K,{label:"secrets",value:e.summary.secrets,color:"red"},void 0,!1,void 0,this),o(K,{label:"drift",value:e.summary.drift,color:"blue"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Pt({items:e,title:t}){return o(s,{flexDirection:"column",children:[o(b,{title:t,subtitle:`${e.length} item${e.length===1?"":"s"}`},void 0,!1,void 0,this),o(s,{flexDirection:"column",marginTop:1,children:e.map((r)=>o(s,{gap:1,children:[o(l,{color:r.exists?"white":"gray",children:r.exists?"\u25CF":"\u25CB"},void 0,!1,void 0,this),o(l,{color:qt(r),children:r.domain},void 0,!1,void 0,this),o(l,{color:"gray",children:"/"},void 0,!1,void 0,this),o(l,{color:"cyan",children:r.app},void 0,!1,void 0,this),o(l,{children:r.displayPath},void 0,!1,void 0,this),o(A,{label:r.shareability,color:Vt(r.shareability)},void 0,!1,void 0,this),r.secretFindings.length>0?o(A,{label:"secret",color:"red"},void 0,!1,void 0,this):null,r.mirrors.some((n)=>n.exists&&n.identical===!1)?o(A,{label:"drift",color:"blue"},void 0,!1,void 0,this):null]},r.id,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Zt({item:e}){return o(s,{flexDirection:"column",gap:1,children:[o(b,{title:e.app,subtitle:e.displayPath},void 0,!1,void 0,this),o(s,{gap:1,children:[o(A,{label:e.domain,color:"cyan"},void 0,!1,void 0,this),o(A,{label:e.kind,color:qt(e)},void 0,!1,void 0,this),o(A,{label:e.shareability,color:Vt(e.shareability)},void 0,!1,void 0,this),o(A,{label:e.recommendation,color:"yellow"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),o(Jn,{rows:[["reason",e.reason],["exists",String(e.exists)],["mode",e.mode??"\u2014"],["symlink",String(e.isSymlink)],["git",Hn(e)],["legacy",Qn(e)]]},void 0,!1,void 0,this),e.secretFindings.length>0?o(s,{flexDirection:"column",children:[o(l,{color:"red",bold:!0,children:"Secret warnings"},void 0,!1,void 0,this),e.secretFindings.map((t,r)=>o(l,{color:"red",children:[" ",t.type,t.line?` line ${t.line}`:"",": ",t.preview]},`${t.type}-${r}`,!0,void 0,this))]},void 0,!0,void 0,this):null,e.mirrors.length>0?o(s,{flexDirection:"column",children:[o(l,{color:"blue",bold:!0,children:"Mirrors"},void 0,!1,void 0,this),e.mirrors.map((t)=>o(l,{children:[" ",t.displayPath," \u2014 ",t.exists?t.identical===!1?"differs":"identical":"missing"]},t.path,!0,void 0,this))]},void 0,!0,void 0,this):null,o(s,{flexDirection:"column",children:[o(l,{bold:!0,children:e.preview?"Safe preview":"Preview"},void 0,!1,void 0,this),o(l,{color:e.preview?"white":"gray",children:e.preview?e.preview.slice(0,3000):`Suppressed: ${e.previewSuppressedReason??"not available"}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Mt({verificationUri:e,userCode:t,expiresIn:r}){return o(s,{flexDirection:"column",gap:1,children:[o(b,{title:"Login with GitHub",subtitle:`code expires in ${Math.round(r/60)} minutes`},void 0,!1,void 0,this),o(s,{flexDirection:"column",children:[o(l,{children:"Open:"},void 0,!1,void 0,this),o(l,{color:"blue",underline:!0,children:e},void 0,!1,void 0,this)]},void 0,!0,void 0,this),o(s,{gap:1,children:[o(l,{children:"Enter code:"},void 0,!1,void 0,this),o(l,{color:"green",bold:!0,children:t},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Lt({login:e,apiUrl:t}){return o(s,{flexDirection:"column",children:[o(b,{title:"Logged in",subtitle:t},void 0,!1,void 0,this),o(l,{color:"green",children:["\u2713 ",e]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Ot({login:e,apiUrl:t}){if(!e)return o(l,{color:"yellow",children:"Not logged in. Run `atl login`."},void 0,!1,void 0,this);return o(s,{flexDirection:"column",children:[o(b,{title:"Current account",subtitle:t},void 0,!1,void 0,this),o(l,{color:"green",children:e},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Jt(){return o(l,{color:"green",children:"\u2713 Logged out"},void 0,!1,void 0,this)}function Xt({profiles:e,activeProfile:t}){return o(s,{flexDirection:"column",children:[o(b,{title:"Profiles",subtitle:`active: ${t}`},void 0,!1,void 0,this),o(s,{flexDirection:"column",marginTop:1,children:e.map((r)=>o(s,{gap:1,children:[o(l,{color:r.name===t?"green":"gray",children:r.name===t?"\u25CF":"\u25CB"},void 0,!1,void 0,this),o(l,{bold:r.name===t,children:r.name},void 0,!1,void 0,this),o(l,{color:"gray",children:r.createdAt},void 0,!1,void 0,this)]},r.id,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Ce({title:e,name:t}){return o(s,{flexDirection:"column",children:[o(b,{title:e},void 0,!1,void 0,this),o(l,{color:"green",children:["\u2713 ",t]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Wt({configs:e,profileName:t}){return o(s,{flexDirection:"column",children:[o(b,{title:"Saved configs",subtitle:t},void 0,!1,void 0,this),e.length===0?o(l,{color:"gray",children:"No saved configs yet."},void 0,!1,void 0,this):e.map((r)=>o(s,{flexDirection:"column",marginTop:1,children:[o(l,{bold:!0,children:r.stableId},void 0,!1,void 0,this),o(l,{color:"gray",children:r.pathHint??"no path hint"},void 0,!1,void 0,this),r.latestVersion?o(l,{color:"green",children:[r.latestVersion.contentSha256.slice(0,12)," \xB7 ",r.latestVersion.sizeBytes," bytes \xB7 ",r.latestVersion.createdAt]},void 0,!0,void 0,this):null]},r.id,!0,void 0,this))]},void 0,!0,void 0,this)}function Yt({config:e,profileName:t}){return o(s,{flexDirection:"column",children:[o(b,{title:e.stableId,subtitle:t},void 0,!1,void 0,this),o(l,{color:"gray",children:e.pathHint??"no path hint"},void 0,!1,void 0,this),o(s,{flexDirection:"column",marginTop:1,children:(e.versions??[]).map((r)=>o(l,{children:[r.contentSha256.slice(0,12)," \xB7 ",r.sizeBytes," bytes \xB7 ",r.createdAt]},r.id,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Qt({stableId:e,profileName:t,versionHash:r,sizeBytes:n,reused:a}){return o(s,{flexDirection:"column",children:[o(b,{title:a?"Config already saved":"Config saved",subtitle:t},void 0,!1,void 0,this),o(l,{color:"green",children:["\u2713 ",e]},void 0,!0,void 0,this),o(l,{color:"gray",children:["Version ",r.slice(0,12)," \xB7 ",n," bytes \xB7 encrypted"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Ht({result:e,preview:t}){let r=t?"Apply preview":e.status==="blocked"?"Apply blocked":"Config applied";return o(s,{flexDirection:"column",children:[o(b,{title:r,subtitle:e.profileName},void 0,!1,void 0,this),o(Ft,{result:e},void 0,!1,void 0,this),o(l,{children:e.displayPath},void 0,!1,void 0,this),o(l,{color:"gray",children:e.reason},void 0,!1,void 0,this),e.backupPath?o(l,{color:"yellow",children:["Backup: ",e.backupPath]},void 0,!0,void 0,this):null,o(l,{color:"gray",children:["Version ",e.version.contentSha256.slice(0,12)," \xB7 ",e.version.sizeBytes," bytes \xB7 encrypted"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Nt({result:e}){let t=e.preview?"Profile switch preview":e.blocked?"Profile switch blocked":"Profile switched",r=e.results.filter((a)=>a.status==="create"||a.status==="update").length,n=e.results.filter((a)=>a.status==="blocked").length;return o(s,{flexDirection:"column",children:[o(b,{title:t,subtitle:e.profileName},void 0,!1,void 0,this),e.results.length===0?o(l,{color:"gray",children:"No saved configs in this profile."},void 0,!1,void 0,this):null,e.results.length>0?o(l,{color:"gray",children:[r," change",r===1?"":"s"," \xB7 ",n," blocked \xB7 ",e.results.length," total"]},void 0,!0,void 0,this):null,o(s,{flexDirection:"column",marginTop:1,children:e.results.map((a)=>o(s,{flexDirection:"column",children:[o(Ft,{result:a},void 0,!1,void 0,this),o(l,{color:"gray",children:[" ",a.displayPath]},void 0,!0,void 0,this),o(l,{color:"gray",children:[" ",a.reason]},void 0,!0,void 0,this),a.backupPath?o(l,{color:"yellow",children:[" Backup: ",a.backupPath]},void 0,!0,void 0,this):null]},a.stableId,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Gt({checks:e}){let t=e.filter((n)=>n.status==="fail").length,r=e.filter((n)=>n.status==="warn").length;return o(s,{flexDirection:"column",gap:1,children:[o(b,{title:"Doctor",subtitle:t?`${t} failing`:r?`${r} warning${r===1?"":"s"}`:"all checks passed"},void 0,!1,void 0,this),o(s,{flexDirection:"column",children:e.map((n)=>o(s,{gap:1,children:[o(l,{color:Wn(n.status),children:Xn(n.status)},void 0,!1,void 0,this),o(l,{bold:!0,children:n.label},void 0,!1,void 0,this),o(l,{color:"gray",children:n.detail},void 0,!1,void 0,this)]},n.label,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function xe({query:e}){return o(l,{color:"red",children:["No inventory item matched: ",e]},void 0,!0,void 0,this)}function b({title:e,subtitle:t}){return o(s,{flexDirection:"column",children:[o(l,{bold:!0,color:"cyan",children:"\u25C6 Atelier"},void 0,!1,void 0,this),o(s,{gap:1,children:[o(l,{bold:!0,children:e},void 0,!1,void 0,this),t?o(l,{color:"gray",children:t},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function K({label:e,value:t,color:r}){return o(s,{flexDirection:"column",borderStyle:"round",borderColor:r,paddingX:1,children:[o(l,{color:r,bold:!0,children:t},void 0,!1,void 0,this),o(l,{color:"gray",children:e},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function A({label:e,color:t}){return o(l,{color:t,children:["[",e,"]"]},void 0,!0,void 0,this)}function Ft({result:e}){return o(s,{gap:1,children:[o(l,{color:It(e.status),children:Yn(e.status)},void 0,!1,void 0,this),o(l,{bold:!0,children:e.stableId},void 0,!1,void 0,this),o(A,{label:e.status,color:It(e.status)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Jn({rows:e}){return o(s,{flexDirection:"column",children:e.map(([t,r])=>o(s,{gap:1,children:[o(l,{color:"gray",children:t.padEnd(10)},void 0,!1,void 0,this),o(l,{children:r},void 0,!1,void 0,this)]},t,!0,void 0,this))},void 0,!1,void 0,this)}function qt(e){let t=typeof e==="string"?e:e.kind;if(t==="private")return"red";if(t==="generated")return"magenta";if(t==="config")return"green";return"yellow"}function Vt(e){if(e==="private")return"red";if(e==="shareable")return"green";return"yellow"}function Xn(e){if(e==="pass")return"\u2713";if(e==="warn")return"!";return"\u2717"}function Wn(e){if(e==="pass")return"green";if(e==="warn")return"yellow";return"red"}function It(e){if(e==="unchanged")return"green";if(e==="create")return"cyan";if(e==="update")return"yellow";return"red"}function Yn(e){if(e==="unchanged")return"\u2713";if(e==="create")return"+";if(e==="update")return"\xB1";return"\u2717"}function Qn(e){let t=Object.entries(e.legacyManagers??{});if(t.length===0)return"not scanned";return t.map(([r,n])=>`${r}: ${n}`).join(", ")}function Hn(e){if(!e.git)return"not in repo";return`${e.git.tracked?"tracked":"untracked"}${e.git.modified?", modified":""} @ ${e.git.root}`}import{jsxDEV as d}from"react/jsx-dev-runtime";var Dn=qn(import.meta.dir,"../../.."),er=En(),O=j(er,"inventory.json"),Dt,p=new Vn;p.name("atl").description("Atelier config management CLI").version("0.1.5");p.command("login").description("Login to Atelier with GitHub device auth").option("--api-url <url>","Atelier API URL",W()).action(async(e)=>{let t=await Pe({apiUrl:e.apiUrl,onPrompt:async(r)=>{await g(d(Mt,{verificationUri:r.verificationUri,userCode:r.userCode,expiresIn:r.expiresIn},void 0,!1,void 0,this))}});await g(d(Lt,{login:t.user.login,apiUrl:t.apiUrl},void 0,!1,void 0,this))});p.command("whoami").description("Show the current Atelier account").action(async()=>{let e=await Ze();if(await g(d(Ot,{login:e?.user.login,apiUrl:e?.apiUrl},void 0,!1,void 0,this)),!e)process.exitCode=1});p.command("logout").description("Remove the local Atelier session").action(async()=>{Le(),await g(d(Jt,{},void 0,!1,void 0,this))});var ee=p.command("profile").description("Manage account-backed config profiles");ee.command("list").description("List remote profiles").action(async()=>{await g(d(Xt,{profiles:await Je(),activeProfile:y()},void 0,!1,void 0,this))});ee.command("create").description("Create a remote profile").argument("<name>").action(async(e)=>{let t=await Xe(e);await g(d(Ce,{title:"Profile created",name:t.name},void 0,!1,void 0,this))});ee.command("switch").description("Apply a remote profile to this machine and make it active").argument("<name>").option("--preview","show profile changes without writing files or switching").option("--backup","back up differing local files before replacing them").action(async(e,t)=>{await nr(e,t)});ee.command("current").description("Show the active local profile").action(async()=>{await g(d(Ce,{title:"Active profile",name:y()},void 0,!1,void 0,this))});p.command("checkout").description("Alias for `atl profile switch`").argument("<name>").option("--preview","show profile changes without writing files or switching").option("--backup","back up differing local files before replacing them").action(async(e,t)=>{await nr(e,t)});var te=p.command("vault").description("Advanced vault controls");te.command("status").description("Show vault initialization and local unlock state").action(async()=>{let e=await F();console.log(`Vault: ${e.initialized?"initialized":"not initialized"}`),console.log(`Local state: ${e.unlocked?"unlocked":"locked"}`),console.log(`Active profile: ${e.activeProfile}`)});te.command("init").description("Initialize the encrypted vault now instead of waiting for first save").action(async()=>{let e=await ar("Create an Atelier vault passphrase: "),t=await pe(e);console.log(`Vault initialized for profile ${t.profileName}`)});te.command("unlock").description("Unlock this machine with the vault passphrase").action(async()=>{let e=await J("Vault passphrase: "),t=await qe(e);console.log(`Vault unlocked for profile ${t.activeProfile}`)});te.command("lock").description("Remove local unlocked vault material from this machine").action(async()=>{Ve(),console.log("Vault locked")});p.command("save").description("Save a config snapshot to the active encrypted profile").argument("<id-or-path>").action(async(e)=>{await jn(e)});p.command("apply").description("Apply a saved config to this machine").argument("<id-or-path>").option("--preview","show the local changes without writing files").option("--backup","back up a differing local file before replacing it").action(async(e,t)=>{await eo(e,t)});var tr=p.command("saved").description("Inspect encrypted configs saved remotely");tr.command("list").description("List saved configs for the active profile").action(async()=>{let e=y();await g(d(Wt,{configs:await I(e),profileName:e},void 0,!1,void 0,this))});tr.command("show").description("Show saved metadata and version history").argument("<stable-id>").action(async(e)=>{let t=y(),r=await H(t,e);if(!r)throw new Error(`Saved config not found: ${e}`);await g(d(Yt,{config:r,profileName:t},void 0,!1,void 0,this))});p.command("scan").description("Scan this machine and write local inventory").option("--path <path...>","additional manual path(s) to scan").option("--legacy","include legacy manager signals like yadm").action(async(e)=>{let t=await Kt({repoRoot:Dn,manualPaths:e.path??[],includeLegacyManagers:e.legacy}),r=Rt(t,{path:O});await g(d(ke,{inventory:t,path:r},void 0,!1,void 0,this))});p.command("list").description("List inventory items with polished terminal output").option("--domain <domain>","filter by domain").option("--app <app>","filter by app").option("--secrets","only items with secret warnings").option("--drift","only items with mirror drift").option("--generated","only generated/app-state items").option("--private","only private items").option("--missing","only missing registry items").option("--json","print JSON instead of Ink output").action(async(e)=>{let t=X(),r=ro(t.items,e);if(e.json)return re(r);await g(d(Pt,{items:r,title:"Inventory"},void 0,!1,void 0,this))});p.command("inspect").description("Inspect one inventory item by id or path").argument("<id-or-path>").option("--json","print JSON instead of Ink output").action(async(e,t)=>{let r=X(),n=ir(r,e);if(t.json)return re(n??null);await g(n?d(Zt,{item:n},void 0,!1,void 0,this):d(xe,{query:e},void 0,!1,void 0,this))});p.command("summary").description("Print the last scan summary").option("--json","print JSON instead of Ink output").action(async(e)=>{let t=X();if(e.json)return re(t.summary);await g(d(ke,{inventory:t,path:O},void 0,!1,void 0,this))});p.command("doctor").description("Check Atelier CLI, account, inventory, and local environment health").option("--json","print JSON instead of Ink output").action(async(e)=>{let t=no();if(e.json)re(t);else await g(d(Gt,{checks:t},void 0,!1,void 0,this));if(t.some((r)=>r.status==="fail"))process.exitCode=1});p.parseAsync(process.argv).catch((e)=>{console.error(e instanceof Error?e.message:e),process.exit(1)});function re(e){console.log(JSON.stringify(e,null,2))}function rr(e){return e.split(`
13
+ `).map((t)=>{if(t.startsWith("+")&&!t.startsWith("+++"))return`\x1B[32m${t}\x1B[0m`;if(t.startsWith("-")&&!t.startsWith("---"))return`\x1B[31m${t}\x1B[0m`;if(t.startsWith("@@"))return`\x1B[36m${t}\x1B[0m`;return t}).join(`
14
+ `)}function X(){if(!Et(O))throw new Error("No inventory found. Run `atl scan` first.");return JSON.parse(jt(O,"utf-8"))}function En(){if(process.env.ATELIER_STATE_DIR)return process.env.ATELIER_STATE_DIR;if(process.env.XDG_STATE_HOME)return j(process.env.XDG_STATE_HOME,"atelier");if(Fn()==="win32"&&process.env.LOCALAPPDATA)return j(process.env.LOCALAPPDATA,"Atelier");return j(Gn(),".local","state","atelier")}async function jn(e){let t=X(),r=ir(t,e);if(!r){await g(d(xe,{query:e},void 0,!1,void 0,this)),process.exitCode=1;return}let n=await or({initialize:!0}),a=await vt(r,{passphrase:n});await g(d(Qt,{stableId:a.stableId,profileName:a.profileName,versionHash:a.version.contentSha256,sizeBytes:a.version.sizeBytes,reused:a.reused},void 0,!1,void 0,this))}async function eo(e,t){let r=await or({initialize:!1}),n=await lt(e,{passphrase:r,preview:t.preview,backup:t.backup});if(await g(d(Ht,{result:n,preview:t.preview},void 0,!1,void 0,this)),n.diff&&(t.preview||n.status==="blocked"))console.log(rr(n.diff));if(n.status==="blocked")process.exitCode=1}async function nr(e,t){let r=await Q(e);if(!r)throw new Error(`Profile not found: ${e}`);let n=await to(),a=await st(r.name,{passphrase:n,preview:t.preview,backup:t.backup});if(!t.preview&&!a.blocked)Me(r.name);if(await g(d(Nt,{result:a},void 0,!1,void 0,this)),t.preview||a.blocked){for(let i of a.results)if(i.diff&&(i.status==="update"||i.status==="blocked"))console.log(`
15
+ ${i.stableId}`),console.log(rr(i.diff))}if(a.blocked)process.exitCode=1}async function to(){let e=await F();if(e.initialized&&!e.unlocked)return await J("Vault passphrase: ");return}async function or({initialize:e}){let t=await F();if(!t.initialized){if(!e)throw new Error("Atelier vault is not initialized. Run `atl save <id>` first.");return await ar("Create an Atelier vault passphrase: ")}if(!t.unlocked)return await J("Vault passphrase: ");return}async function ar(e){let t=await J(e),r=await J("Confirm vault passphrase: ");if(t!==r)throw new Error("Vault passphrases do not match");return t}async function J(e){if(!B.isTTY)return E.write(e),Dt??=jt(0,"utf-8").split(/\r?\n/),Dt.shift()??"";return E.write(e),B.setEncoding("utf-8"),B.resume(),B.setRawMode(!0),await new Promise((t)=>{let r="",n=()=>{B.off("data",i),B.setRawMode(!1),B.pause()},a=()=>{n(),E.write(`
16
+ `),t(r)},i=(c)=>{for(let f of String(c)){if(f==="\x03")n(),E.write(`
17
+ `),process.exit(130);if(f==="\r"||f===`
18
+ `){a();return}if(f==="\x7F"){r=r.slice(0,-1);continue}r+=f}};B.on("data",i)})}function ro(e,t){return e.filter((r)=>{if(t.domain&&r.domain.toLowerCase()!==t.domain.toLowerCase())return!1;if(t.app&&r.app.toLowerCase()!==t.app.toLowerCase())return!1;if(t.secrets&&r.secretFindings.length===0)return!1;if(t.drift&&!r.mirrors.some((n)=>n.exists&&n.identical===!1))return!1;if(t.generated&&r.kind!=="generated")return!1;if(t.private&&r.shareability!=="private")return!1;if(t.missing&&r.exists)return!1;return!0})}function ir(e,t){let r=$e(t);return e.items.find((n)=>n.id===t||$e(n.path)===r||$e(n.displayPath)===r)??e.items.find((n)=>n.displayPath.includes(t)||n.path.includes(t))}function $e(e){return e.replace(/^~(?=\/|$)/,process.env.HOME??"").toLowerCase()}function no(){let e=[],t=Et(O)?X():void 0,r=Y();return e.push({label:"runtime",status:process.versions.bun?"pass":"fail",detail:process.versions.bun?`Bun ${process.versions.bun}`:"Bun is required"}),e.push({label:"api",status:"pass",detail:W()}),e.push({label:"session",status:r?"pass":"warn",detail:r?`logged in as ${r.user.login}`:"not logged in; run `atl login`"}),e.push({label:"state directory",status:"pass",detail:er}),e.push({label:"inventory",status:t?"pass":"warn",detail:t?`${t.summary.existing}/${t.summary.total} existing, generated ${t.generatedAt}`:"missing; run `atl scan`"}),e.push({label:"secret warnings",status:t&&t.summary.secrets>0?"warn":"pass",detail:t?`${t.summary.secrets} item${t.summary.secrets===1?"":"s"} flagged`:"no inventory"}),e}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@manan_joshi/atelier",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Atelier config management CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "dependencies": {
20
20
  "commander": "15.0.0",
21
+ "diff": "8.0.4",
21
22
  "ink": "7.0.5",
22
23
  "react": "19.2.7"
23
24
  },