inscope 0.7.0-canary.9 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -62,7 +62,7 @@ add-zsh-hook chpwd __inscope_resolve_identity
62
62
  __inscope_ws="__init__" # force the first resolve, clearing any inherited token
63
63
  __inscope_resolve_identity
64
64
  `},Le=e=>{let t=o();return e===t?`$HOME`:e.startsWith(t+n.sep)?`$HOME/${e.slice(t.length+1)}`:e},Re=()=>{let e=Le(p());return`[ -r "${e}" ] && source "${e}"`},ze=e=>{let t=Re();if(e.includes(t))return e;let n=e.replace(/\n*$/,``),r=`# inscope: load each workspace's tokens (GitHub, Slack) from \$PWD on every cd\n${t}`;return n.length?`${n}\n\n${r}\n`:`${r}\n`},Be=()=>{let e=g(),n=``;try{n=t.readFileSync(e,`utf8`)}catch{}let r=ze(n);r!==n&&t.writeFileSync(e,r)},Ve=()=>{try{return t.readFileSync(g(),`utf8`).includes(Re())}catch{return!1}},X=e=>{let r=p();t.mkdirSync(n.dirname(r),{recursive:!0}),t.writeFileSync(r,Ie(e)),Me(e),Be();let i=[];for(let t of e.workspaces)fe(t),i.push(O(t));return{hook:r,gitconfig:e.workspaces.some(e=>e.git?.email||e.git?.name),mcp:i}},He=E,Ue=e=>`SLACK_MCP_XOXP_TOKEN_${e.toUpperCase().replace(/[^A-Z0-9]+/g,`_`)}`,We=e=>E.filter(t=>!!e[t]),Ge=(e,t)=>{let n={};for(let r of E)n[r]=r===`slack`?t?{keychain:t.keychain,addMessageTool:t.addMessageTool}:!1:e.includes(r);return n},Ke=e=>{let t=ie(v()?y():_(),e);b(t),X(t)},qe=async(e,t)=>{if(!e.servers.slack)return;let n=e.servers.slack.keychain;if(t){let e=await be(`Paste the Slack xoxp token for ${n}: `);e?(_e(n,e),console.log(`\n✓ stored ${n} in the macOS keychain`)):console.error(`
65
- No token entered; skipped keychain write.`)}else N(n)||console.log(`\nSlack token not in the keychain yet. Store it once with:\n${I(P(n))}\n\nSetup guide: ${I(ye(`https://github.com/korotovsky/slack-mcp-server/blob/HEAD/docs/01-authentication-setup.md#option-2-using-slack_mcp_xoxp_token-user-oauth`))}`)};var Z=`inscope`,Je=`0.7.0-canary.9`,Q={name:`Neeraj Dalal`,email:`admin@nrjdalal.com`,url:`https://nrjdalal.com`};const Ye=`Map a directory to a GitHub account, git email, and MCP servers.
65
+ No token entered; skipped keychain write.`)}else N(n)||console.log(`\nSlack token not in the keychain yet. Store it once with:\n${I(P(n))}\n\nSetup guide: ${I(ye(`https://github.com/korotovsky/slack-mcp-server/blob/HEAD/docs/01-authentication-setup.md#option-2-using-slack_mcp_xoxp_token-user-oauth`))}`)};var Z=`inscope`,Je=`0.7.0`,Q={name:`Neeraj Dalal`,email:`admin@nrjdalal.com`,url:`https://nrjdalal.com`};const Ye=`Map a directory to a GitHub account, git email, and MCP servers.
66
66
  Runs interactively in a terminal; pass flags or -y to skip the prompts. Re-running
67
67
  with the same path or label updates that workspace.
68
68
 
@@ -92,7 +92,7 @@ Usage:
92
92
  $ ${Z} apply
93
93
 
94
94
  Options:
95
- -h, --help Display help message`,$e=t=>{let{values:n}=e({allowPositionals:!0,options:{help:{type:`boolean`,short:`h`}},args:t});n.help&&(console.log(Qe),process.exit(0)),v()||(console.error(`No config found. Run \`${Z} init\` first.`),process.exit(1));let r=y(),i=X(r);console.log(`\n✓ hook ${i.hook}`),i.gitconfig&&console.log(`✓ gitconfig ~/.gitconfig (includeIf block)`);for(let e of i.mcp)console.log(`✓ mcp ${e}`);console.log(`\nApplied ${r.workspaces.length} workspace(s).`),process.exit(0)},et=e=>{try{return t.readFileSync(e,`utf8`)}catch{return null}},tt=e=>{let t=[],n=e?.mcpServers;if(!n||typeof n!=`object`)return t;for(let[e,r]of Object.entries(n)){let n=Array.isArray(r?.args)?r.args:[];if(n.some(e=>typeof e==`string`&&/@latest$/.test(e)))t.push(e);else if(r?.command===`npx`){let r=n.find(e=>typeof e==`string`&&!e.startsWith(`-`));r&&!r.includes(`@`)&&t.push(e)}}return t},nt=(e,t=process.cwd())=>{let r=n.resolve(t);return e.workspaces.find(e=>{let t=u(e.path);return r===t||r.startsWith(t+n.sep)})},rt=(e=k)=>{let t=e(`gh`,[`api`,`user`,`--jq`,`.login`]),n=e(`git`,[`config`,`user.email`]);return{pwd:process.cwd(),gh:t.status===0&&t.stdout.trim()?t.stdout.trim():`none`,gitEmail:n.status===0?n.stdout.trim():`none`,tokenSet:!!process.env.GITHUB_TOKEN}},it=(e,n=k)=>{let r=[];me()||r.push({status:`warn`,label:`platform`,detail:`inscope's secret resolution targets macOS (gh keyring + Keychain)`});let i=p(),a=et(i);a===null?r.push({status:`fail`,label:`hook`,detail:`missing ${i}; run \`inscope init\``}):a===Ie(e)?r.push({status:`ok`,label:`hook`,detail:i}):r.push({status:`warn`,label:`hook`,detail:"out of date; run `inscope apply`"}),r.push(Ve()?{status:`ok`,label:`zshrc`,detail:`sources the hook`}:{status:`warn`,label:`zshrc`,detail:"does not source the hook; run `inscope init`"}),e.workspaces.some(J)&&r.push(Oe(h(),q)===null?{status:`fail`,label:`gitconfig`,detail:"missing includeIf block; run `inscope apply`"}:{status:`ok`,label:`gitconfig`,detail:`includeIf block present`});for(let i of e.workspaces){let e=`[${i.name}]`;if(i.gh&&r.push(he(i.gh,n)?{status:`ok`,label:`${e} gh`,detail:`token for ${i.gh}`}:{status:`fail`,label:`${e} gh`,detail:`no token for ${i.gh}; run \`gh auth login\``}),i.servers.slack){let t=i.servers.slack.keychain;r.push(N(t,n)?{status:`ok`,label:`${e} slack`,detail:t}:{status:`fail`,label:`${e} slack`,detail:`${t} not in keychain; run \`${P(t)}\``})}if(J(i)){let a=Y(i.name);if(!t.existsSync(a))r.push({status:`fail`,label:`${e} git`,detail:`missing ${a}; run \`inscope apply\``});else if(i.git?.email){let t=ve(a,n);r.push(t===i.git.email?{status:`ok`,label:`${e} git`,detail:i.git.email}:{status:`fail`,label:`${e} git`,detail:`email is ${t??`unset`}, expected ${i.git.email}`})}}let a=de(i);if(a===null)r.push({status:`warn`,label:`${e} mcp`,detail:"no .mcp.json; run `inscope apply`"});else{let t=D(i.name).filter(e=>a.mcpServers?.[e]);r.push({status:`ok`,label:`${e} mcp`,detail:`${t.length} server(s)`});let n=tt(a);n.length&&r.push({status:`warn`,label:`${e} mcp`,detail:`unpinned: ${n.join(`, `)}`})}}return r},at=`Verify the setup: gh tokens resolve, keychain entries exist,
95
+ -h, --help Display help message`,$e=t=>{let{values:n}=e({allowPositionals:!0,options:{help:{type:`boolean`,short:`h`}},args:t});n.help&&(console.log(Qe),process.exit(0)),v()||(console.error(`No config found. Run \`${Z} init\` first.`),process.exit(1));let r=y(),i=X(r);console.log(`\n✓ hook ${i.hook}`),i.gitconfig&&console.log(`✓ gitconfig ~/.gitconfig (includeIf block)`);for(let e of i.mcp)console.log(`✓ mcp ${e}`);console.log(`\nApplied ${r.workspaces.length} workspace(s).`),process.exit(0)},et=e=>{try{return t.readFileSync(e,`utf8`)}catch{return null}},tt=e=>{let t=[],n=e?.mcpServers;if(!n||typeof n!=`object`)return t;for(let[e,r]of Object.entries(n)){let n=Array.isArray(r?.args)?r.args:[];if(n.some(e=>typeof e==`string`&&e.endsWith(`@latest`)))t.push(e);else if(r?.command===`npx`){let r=n.find(e=>typeof e==`string`&&!e.startsWith(`-`));r&&!r.includes(`@`)&&t.push(e)}}return t},nt=(e,t=process.cwd())=>{let r=n.resolve(t);return e.workspaces.find(e=>{let t=u(e.path);return r===t||r.startsWith(t+n.sep)})},rt=(e=k)=>{let t=e(`gh`,[`api`,`user`,`--jq`,`.login`]),n=e(`git`,[`config`,`user.email`]);return{pwd:process.cwd(),gh:t.status===0&&t.stdout.trim()?t.stdout.trim():`none`,gitEmail:n.status===0?n.stdout.trim():`none`,tokenSet:!!process.env.GITHUB_TOKEN}},it=(e,n=k)=>{let r=[];me()||r.push({status:`warn`,label:`platform`,detail:`inscope's secret resolution targets macOS (gh keyring + Keychain)`});let i=p(),a=et(i);a===null?r.push({status:`fail`,label:`hook`,detail:`missing ${i}; run \`inscope init\``}):a===Ie(e)?r.push({status:`ok`,label:`hook`,detail:i}):r.push({status:`warn`,label:`hook`,detail:"out of date; run `inscope apply`"}),r.push(Ve()?{status:`ok`,label:`zshrc`,detail:`sources the hook`}:{status:`warn`,label:`zshrc`,detail:"does not source the hook; run `inscope init`"}),e.workspaces.some(J)&&r.push(Oe(h(),q)===null?{status:`fail`,label:`gitconfig`,detail:"missing includeIf block; run `inscope apply`"}:{status:`ok`,label:`gitconfig`,detail:`includeIf block present`});for(let i of e.workspaces){let e=`[${i.name}]`;if(i.gh&&r.push(he(i.gh,n)?{status:`ok`,label:`${e} gh`,detail:`token for ${i.gh}`}:{status:`fail`,label:`${e} gh`,detail:`no token for ${i.gh}; run \`gh auth login\``}),i.servers.slack){let t=i.servers.slack.keychain;r.push(N(t,n)?{status:`ok`,label:`${e} slack`,detail:t}:{status:`fail`,label:`${e} slack`,detail:`${t} not in keychain; run \`${P(t)}\``})}if(J(i)){let a=Y(i.name);if(!t.existsSync(a))r.push({status:`fail`,label:`${e} git`,detail:`missing ${a}; run \`inscope apply\``});else if(i.git?.email){let t=ve(a,n);r.push(t===i.git.email?{status:`ok`,label:`${e} git`,detail:i.git.email}:{status:`fail`,label:`${e} git`,detail:`email is ${t??`unset`}, expected ${i.git.email}`})}}let a=de(i);if(a===null)r.push({status:`warn`,label:`${e} mcp`,detail:"no .mcp.json; run `inscope apply`"});else{let t=D(i.name).filter(e=>a.mcpServers?.[e]);r.push({status:`ok`,label:`${e} mcp`,detail:`${t.length} server(s)`});let n=tt(a);n.length&&r.push({status:`warn`,label:`${e} mcp`,detail:`unpinned: ${n.join(`, `)}`})}}return r},at=`Verify the setup: gh tokens resolve, keychain entries exist,
96
96
  git emails match per path, the hook is current, and no MCP server is unpinned.
97
97
  Exits non-zero if any check fails.
98
98
 
package/dist/index.mjs CHANGED
@@ -53,4 +53,4 @@ __inscope_ws="__init__" # force the first resolve, clearing any inherit
53
53
  __inscope_resolve_identity
54
54
  `},P=`1.3.0`,ge={atlassian:`https://mcp.atlassian.com/v1/mcp`,canva:`https://mcp.canva.com/mcp`,clickup:`https://mcp.clickup.com/mcp`,hubspot:`https://mcp.hubspot.com`,intercom:`https://mcp.intercom.com/mcp`,linear:`https://mcp.linear.app/mcp`,monday:`https://mcp.monday.com/mcp`,notion:`https://mcp.notion.com/mcp`,plane:`https://mcp.plane.so/http/mcp`,sentry:`https://mcp.sentry.dev/mcp`,stripe:`https://mcp.stripe.com`,vercel:`https://mcp.vercel.com`,webflow:`https://mcp.webflow.com/`},F=[`github`,`atlassian`,`canva`,`clickup`,`hubspot`,`intercom`,`linear`,`monday`,`notion`,`plane`,`sentry`,`slack`,`stripe`,`vercel`,`webflow`],I=e=>F.map(t=>`${t}-${e}`),L=e=>t.join(c(e.path),`.mcp.json`),_e=(e,t)=>e&&typeof e==`object`&&e.url?e.url:t,R=e=>{let t=e.servers,n={};for(let r of F){let i=t[r];if(!i)continue;let a=`${r}-${e.name}`;if(r===`github`)n[a]={type:`http`,url:`https://api.githubcopilot.com/mcp/`,headers:{Authorization:"Bearer ${GITHUB_TOKEN}"}};else if(r===`slack`){let e=i,t={SLACK_MCP_XOXP_TOKEN:"${SLACK_MCP_XOXP_TOKEN}"};e.addMessageTool&&(t.SLACK_MCP_ADD_MESSAGE_TOOL=`true`),n[a]={type:`stdio`,command:`npx`,args:[`-y`,`slack-mcp-server@${P}`,`--transport`,`stdio`],env:t}}else n[a]={type:`http`,url:_e(i,ge[r])}}return n},ve=e=>({mcpServers:R(e)}),ye=t=>{if(!e.existsSync(t))return{};try{return JSON.parse(e.readFileSync(t,`utf8`))}catch{return{}}},z=t=>{if(!e.existsSync(t))return{};try{return JSON.parse(e.readFileSync(t,`utf8`))}catch{throw Error(`${t} is not valid JSON; fix or remove it, then re-run inscope (left it untouched)`)}},B=t=>{let n=L(t);return e.existsSync(n)?ye(n):null},V=n=>{let r=L(n);e.mkdirSync(t.dirname(r),{recursive:!0});let i=z(r),a=i.mcpServers&&typeof i.mcpServers==`object`?{...i.mcpServers}:{};for(let e of I(n.name))delete a[e];Object.assign(a,R(n)),i.mcpServers=a,e.writeFileSync(r,JSON.stringify(i,null,2)+`
55
55
  `)},be=t=>{let n=L(t);if(!e.existsSync(n))return;let r=z(n);if(r.mcpServers&&typeof r.mcpServers==`object`)for(let e of I(t.name))delete r.mcpServers[e];e.writeFileSync(n,JSON.stringify(r,null,2)+`
56
- `)},xe=e=>{let n=i();return e===n?`$HOME`:e.startsWith(n+t.sep)?`$HOME/${e.slice(n.length+1)}`:e},H=()=>{let e=xe(d());return`[ -r "${e}" ] && source "${e}"`},U=e=>{let t=H();if(e.includes(t))return e;let n=e.replace(/\n*$/,``),r=`# inscope: load each workspace's tokens (GitHub, Slack) from \$PWD on every cd\n${t}`;return n.length?`${n}\n\n${r}\n`:`${r}\n`},W=()=>{let t=m(),n=``;try{n=e.readFileSync(t,`utf8`)}catch{}let r=U(n);r!==n&&e.writeFileSync(t,r)},G=()=>{try{return e.readFileSync(m(),`utf8`).includes(H())}catch{return!1}},Se=n=>{let r=d();e.mkdirSync(t.dirname(r),{recursive:!0}),e.writeFileSync(r,N(n)),M(n),W();let i=[];for(let e of n.workspaces)V(e),i.push(L(e));return{hook:r,gitconfig:n.workspaces.some(e=>e.git?.email||e.git?.name),mcp:i}},K=(e,t,n)=>{let i=r(e,t,{encoding:`utf8`,input:n?.input});return{status:i.status??(i.error?127:1),stdout:i.stdout??``,stderr:i.stderr??``}},q=()=>process.platform===`darwin`,J=()=>process.env.USER||``,Y=(e,t=K)=>{let n=t(`gh`,[`auth`,`token`,`-u`,e]),r=n.stdout.trim();return n.status===0&&r?r:null},X=(e=K)=>{let t=e(`gh`,[`auth`,`status`]);return(t.stdout+t.stderr).trim()},Ce=(e=K)=>{let t=[];for(let n of X(e).matchAll(/account (\S+) \(/g))t.includes(n[1])||t.push(n[1]);return t},we=(e,t=K)=>{let n=t(`git`,[`config`,`--global`,e]),r=n.stdout.trim();return n.status===0&&r?r:null},Z=(e,t=K)=>{let n=t(`security`,[`find-generic-password`,`-a`,J(),`-s`,e,`-w`]);return n.status===0&&n.stdout.trim().length>0},Te=(e,t,n=K)=>{let r=n(`security`,[`add-generic-password`,`-U`,`-a`,J(),`-s`,e,`-w`,t]);if(r.status!==0)throw Error(`security add-generic-password failed: ${r.stderr.trim()||`unknown error`}`)},Q=e=>`security add-generic-password -U -a "${J()||`$USER`}" -s ${e} -w 'xoxp-...'`,$=(e,t=K)=>{let n=t(`git`,[`config`,`--file`,e,`user.email`]);return n.status===0?n.stdout.trim():null},Ee=t=>{try{return e.readFileSync(t,`utf8`)}catch{return null}},De=e=>{let t=[],n=e?.mcpServers;if(!n||typeof n!=`object`)return t;for(let[e,r]of Object.entries(n)){let n=Array.isArray(r?.args)?r.args:[];if(n.some(e=>typeof e==`string`&&/@latest$/.test(e)))t.push(e);else if(r?.command===`npx`){let r=n.find(e=>typeof e==`string`&&!e.startsWith(`-`));r&&!r.includes(`@`)&&t.push(e)}}return t},Oe=(e,n=process.cwd())=>{let r=t.resolve(n);return e.workspaces.find(e=>{let n=c(e.path);return r===n||r.startsWith(n+t.sep)})},ke=(e=K)=>{let t=e(`gh`,[`api`,`user`,`--jq`,`.login`]),n=e(`git`,[`config`,`user.email`]);return{pwd:process.cwd(),gh:t.status===0&&t.stdout.trim()?t.stdout.trim():`none`,gitEmail:n.status===0?n.stdout.trim():`none`,tokenSet:!!process.env.GITHUB_TOKEN}},Ae=(t,n=K)=>{let r=[];q()||r.push({status:`warn`,label:`platform`,detail:`inscope's secret resolution targets macOS (gh keyring + Keychain)`});let i=d(),a=Ee(i);a===null?r.push({status:`fail`,label:`hook`,detail:`missing ${i}; run \`inscope init\``}):a===N(t)?r.push({status:`ok`,label:`hook`,detail:i}):r.push({status:`warn`,label:`hook`,detail:"out of date; run `inscope apply`"}),r.push(G()?{status:`ok`,label:`zshrc`,detail:`sources the hook`}:{status:`warn`,label:`zshrc`,detail:"does not source the hook; run `inscope init`"}),t.workspaces.some(O)&&r.push(fe(p(),D)===null?{status:`fail`,label:`gitconfig`,detail:"missing includeIf block; run `inscope apply`"}:{status:`ok`,label:`gitconfig`,detail:`includeIf block present`});for(let i of t.workspaces){let t=`[${i.name}]`;if(i.gh&&r.push(Y(i.gh,n)?{status:`ok`,label:`${t} gh`,detail:`token for ${i.gh}`}:{status:`fail`,label:`${t} gh`,detail:`no token for ${i.gh}; run \`gh auth login\``}),i.servers.slack){let e=i.servers.slack.keychain;r.push(Z(e,n)?{status:`ok`,label:`${t} slack`,detail:e}:{status:`fail`,label:`${t} slack`,detail:`${e} not in keychain; run \`${Q(e)}\``})}if(O(i)){let a=k(i.name);if(!e.existsSync(a))r.push({status:`fail`,label:`${t} git`,detail:`missing ${a}; run \`inscope apply\``});else if(i.git?.email){let e=$(a,n);r.push(e===i.git.email?{status:`ok`,label:`${t} git`,detail:i.git.email}:{status:`fail`,label:`${t} git`,detail:`email is ${e??`unset`}, expected ${i.git.email}`})}}let a=B(i);if(a===null)r.push({status:`warn`,label:`${t} mcp`,detail:"no .mcp.json; run `inscope apply`"});else{let e=I(i.name).filter(e=>a.mcpServers?.[e]);r.push({status:`ok`,label:`${t} mcp`,detail:`${e.length} server(s)`});let n=De(a);n.length&&r.push({status:`warn`,label:`${t} mcp`,detail:`unpinned: ${n.join(`, `)}`})}}return r};export{ee as CONFIG_VERSION,P as SLACK_MCP_VERSION,h as WORKSPACE_NAME_RE,Se as applyAll,M as applyGitconfig,V as applyMcp,ne as configExists,Oe as currentWorkspace,te as defaultConfig,K as defaultRunner,W as ensureZshrcSource,x as findWorkspace,Ce as ghAccounts,X as ghStatus,Y as ghToken,$ as gitEmailForFile,we as gitGlobal,_ as hookValueError,q as isMacOS,Z as keychainHas,Te as keychainSet,Q as keychainSetCommand,oe as labelFromPath,ke as liveSnapshot,re as loadConfig,I as managedKeys,L as mcpFilePath,B as readMcp,be as removeMcp,ce as removeWorkspace,A as renderGitInclude,N as renderHook,ve as renderMcp,j as renderPerWorkspaceGitconfig,R as renderServers,U as renderZshrcSource,Ae as runDoctor,ie as saveConfig,y as slugify,se as upsertWorkspace,b as validateConfig,g as workspaceNameError,v as workspacePathError,G as zshrcSourcesHook};
56
+ `)},xe=e=>{let n=i();return e===n?`$HOME`:e.startsWith(n+t.sep)?`$HOME/${e.slice(n.length+1)}`:e},H=()=>{let e=xe(d());return`[ -r "${e}" ] && source "${e}"`},U=e=>{let t=H();if(e.includes(t))return e;let n=e.replace(/\n*$/,``),r=`# inscope: load each workspace's tokens (GitHub, Slack) from \$PWD on every cd\n${t}`;return n.length?`${n}\n\n${r}\n`:`${r}\n`},W=()=>{let t=m(),n=``;try{n=e.readFileSync(t,`utf8`)}catch{}let r=U(n);r!==n&&e.writeFileSync(t,r)},G=()=>{try{return e.readFileSync(m(),`utf8`).includes(H())}catch{return!1}},Se=n=>{let r=d();e.mkdirSync(t.dirname(r),{recursive:!0}),e.writeFileSync(r,N(n)),M(n),W();let i=[];for(let e of n.workspaces)V(e),i.push(L(e));return{hook:r,gitconfig:n.workspaces.some(e=>e.git?.email||e.git?.name),mcp:i}},K=(e,t,n)=>{let i=r(e,t,{encoding:`utf8`,input:n?.input});return{status:i.status??(i.error?127:1),stdout:i.stdout??``,stderr:i.stderr??``}},q=()=>process.platform===`darwin`,J=()=>process.env.USER||``,Y=(e,t=K)=>{let n=t(`gh`,[`auth`,`token`,`-u`,e]),r=n.stdout.trim();return n.status===0&&r?r:null},X=(e=K)=>{let t=e(`gh`,[`auth`,`status`]);return(t.stdout+t.stderr).trim()},Ce=(e=K)=>{let t=[];for(let n of X(e).matchAll(/account (\S+) \(/g))t.includes(n[1])||t.push(n[1]);return t},we=(e,t=K)=>{let n=t(`git`,[`config`,`--global`,e]),r=n.stdout.trim();return n.status===0&&r?r:null},Z=(e,t=K)=>{let n=t(`security`,[`find-generic-password`,`-a`,J(),`-s`,e,`-w`]);return n.status===0&&n.stdout.trim().length>0},Te=(e,t,n=K)=>{let r=n(`security`,[`add-generic-password`,`-U`,`-a`,J(),`-s`,e,`-w`,t]);if(r.status!==0)throw Error(`security add-generic-password failed: ${r.stderr.trim()||`unknown error`}`)},Q=e=>`security add-generic-password -U -a "${J()||`$USER`}" -s ${e} -w 'xoxp-...'`,$=(e,t=K)=>{let n=t(`git`,[`config`,`--file`,e,`user.email`]);return n.status===0?n.stdout.trim():null},Ee=t=>{try{return e.readFileSync(t,`utf8`)}catch{return null}},De=e=>{let t=[],n=e?.mcpServers;if(!n||typeof n!=`object`)return t;for(let[e,r]of Object.entries(n)){let n=Array.isArray(r?.args)?r.args:[];if(n.some(e=>typeof e==`string`&&e.endsWith(`@latest`)))t.push(e);else if(r?.command===`npx`){let r=n.find(e=>typeof e==`string`&&!e.startsWith(`-`));r&&!r.includes(`@`)&&t.push(e)}}return t},Oe=(e,n=process.cwd())=>{let r=t.resolve(n);return e.workspaces.find(e=>{let n=c(e.path);return r===n||r.startsWith(n+t.sep)})},ke=(e=K)=>{let t=e(`gh`,[`api`,`user`,`--jq`,`.login`]),n=e(`git`,[`config`,`user.email`]);return{pwd:process.cwd(),gh:t.status===0&&t.stdout.trim()?t.stdout.trim():`none`,gitEmail:n.status===0?n.stdout.trim():`none`,tokenSet:!!process.env.GITHUB_TOKEN}},Ae=(t,n=K)=>{let r=[];q()||r.push({status:`warn`,label:`platform`,detail:`inscope's secret resolution targets macOS (gh keyring + Keychain)`});let i=d(),a=Ee(i);a===null?r.push({status:`fail`,label:`hook`,detail:`missing ${i}; run \`inscope init\``}):a===N(t)?r.push({status:`ok`,label:`hook`,detail:i}):r.push({status:`warn`,label:`hook`,detail:"out of date; run `inscope apply`"}),r.push(G()?{status:`ok`,label:`zshrc`,detail:`sources the hook`}:{status:`warn`,label:`zshrc`,detail:"does not source the hook; run `inscope init`"}),t.workspaces.some(O)&&r.push(fe(p(),D)===null?{status:`fail`,label:`gitconfig`,detail:"missing includeIf block; run `inscope apply`"}:{status:`ok`,label:`gitconfig`,detail:`includeIf block present`});for(let i of t.workspaces){let t=`[${i.name}]`;if(i.gh&&r.push(Y(i.gh,n)?{status:`ok`,label:`${t} gh`,detail:`token for ${i.gh}`}:{status:`fail`,label:`${t} gh`,detail:`no token for ${i.gh}; run \`gh auth login\``}),i.servers.slack){let e=i.servers.slack.keychain;r.push(Z(e,n)?{status:`ok`,label:`${t} slack`,detail:e}:{status:`fail`,label:`${t} slack`,detail:`${e} not in keychain; run \`${Q(e)}\``})}if(O(i)){let a=k(i.name);if(!e.existsSync(a))r.push({status:`fail`,label:`${t} git`,detail:`missing ${a}; run \`inscope apply\``});else if(i.git?.email){let e=$(a,n);r.push(e===i.git.email?{status:`ok`,label:`${t} git`,detail:i.git.email}:{status:`fail`,label:`${t} git`,detail:`email is ${e??`unset`}, expected ${i.git.email}`})}}let a=B(i);if(a===null)r.push({status:`warn`,label:`${t} mcp`,detail:"no .mcp.json; run `inscope apply`"});else{let e=I(i.name).filter(e=>a.mcpServers?.[e]);r.push({status:`ok`,label:`${t} mcp`,detail:`${e.length} server(s)`});let n=De(a);n.length&&r.push({status:`warn`,label:`${t} mcp`,detail:`unpinned: ${n.join(`, `)}`})}}return r};export{ee as CONFIG_VERSION,P as SLACK_MCP_VERSION,h as WORKSPACE_NAME_RE,Se as applyAll,M as applyGitconfig,V as applyMcp,ne as configExists,Oe as currentWorkspace,te as defaultConfig,K as defaultRunner,W as ensureZshrcSource,x as findWorkspace,Ce as ghAccounts,X as ghStatus,Y as ghToken,$ as gitEmailForFile,we as gitGlobal,_ as hookValueError,q as isMacOS,Z as keychainHas,Te as keychainSet,Q as keychainSetCommand,oe as labelFromPath,ke as liveSnapshot,re as loadConfig,I as managedKeys,L as mcpFilePath,B as readMcp,be as removeMcp,ce as removeWorkspace,A as renderGitInclude,N as renderHook,ve as renderMcp,j as renderPerWorkspaceGitconfig,R as renderServers,U as renderZshrcSource,Ae as runDoctor,ie as saveConfig,y as slugify,se as upsertWorkspace,b as validateConfig,g as workspaceNameError,v as workspacePathError,G as zshrcSourcesHook};
package/package.json CHANGED
@@ -1,35 +1,35 @@
1
1
  {
2
2
  "name": "inscope",
3
- "version": "0.7.0-canary.9",
3
+ "version": "0.7.0",
4
4
  "description": "Per-workspace identity for Claude Code: scope MCP servers, GitHub auth, and git commit identity to the directory you are in.",
5
5
  "keywords": [
6
+ "chpwd",
6
7
  "claude-code",
7
- "mcp",
8
8
  "cli",
9
9
  "git",
10
10
  "github",
11
11
  "identity",
12
+ "mcp",
12
13
  "workspace",
13
- "zsh",
14
- "chpwd"
14
+ "zsh"
15
15
  ],
16
16
  "homepage": "https://github.com/nrjdalal/inscope#readme",
17
17
  "bugs": "https://github.com/nrjdalal/inscope/issues",
18
- "repository": "nrjdalal/inscope",
19
- "funding": "https://github.com/sponsors/nrjdalal",
20
18
  "license": "MIT",
21
19
  "author": {
22
20
  "name": "Neeraj Dalal",
23
21
  "email": "admin@nrjdalal.com",
24
22
  "url": "https://nrjdalal.com"
25
23
  },
26
- "type": "module",
27
- "exports": "./dist/index.mjs",
28
- "types": "./dist/index.d.mts",
24
+ "repository": "nrjdalal/inscope",
25
+ "funding": "https://github.com/sponsors/nrjdalal",
26
+ "bin": {
27
+ "inscope": "dist/bin/index.mjs"
28
+ },
29
29
  "files": [
30
30
  "dist"
31
31
  ],
32
- "bin": {
33
- "inscope": "dist/bin/index.mjs"
34
- }
32
+ "type": "module",
33
+ "types": "./dist/index.d.mts",
34
+ "exports": "./dist/index.mjs"
35
35
  }