codex-1up 0.3.9 → 0.3.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  **Codex 1UP** equips your Codex CLI coding agent with powerful tools.
7
7
 
8
8
  - ✅ Installs/updates **Codex CLI** (`@openai/codex`)
9
- - ✅ Adds fast shell power tools: `rg`, `fd`, `fzf`, `jq`, `yq`, `ast-grep`, `bat`, `git`, `git-delta`, `gh`
9
+ - ✅ Adds fast shell power tools: `rg`, `fd`, `fzf`, `jq`, `yq`, `ast-grep`, `bat`, `git`, `git-delta`, `gh` (GitHub CLI)
10
10
  - ✅ **AGENTS.md** template with tool selection guide
11
11
  - ✅ Unified **Codex config** with multiple profiles: `balanced` / `safe` / `yolo`
12
12
  - ✅ 🔊 **Notification sounds** with customizable audio alerts for Codex events
@@ -53,7 +53,7 @@ codex-1up install
53
53
  | **bat** | Better `cat` with syntax highlighting. |
54
54
  | **git** | Version control CLI (required for many workflows). |
55
55
  | **git-delta** | Better `git diff` output formatting. |
56
- | **gh** | GitHub CLI for repo and PR workflows. |
56
+ | **gh** | GitHub CLI for repo and PR workflows (installed/updated by `codex-1up` in the tools step). |
57
57
  | **\~/.codex/config.toml** | Single template with multiple profiles. Active profile is chosen during install (default: `balanced`). See [Codex config reference](https://github.com/openai/codex/blob/main/docs/config.md). |
58
58
  | **AGENTS.md** | Minimal per‑repo rubric; installer can also create global `~/.codex/AGENTS.md`. |
59
59
  | **\~/.codex/skills** | Optional bundled Agent Skills (portable folders with `SKILL.md` + scripts/references). |
package/dist/main.js CHANGED
@@ -1,76 +1,77 @@
1
- import{runMain as jn}from"citty";import{defineCommand as Dn}from"citty";import{defineCommand as dn}from"citty";import{resolve as ct}from"path";import{promises as Jt}from"fs";import*as We from"os";import*as Xt from"toml";import*as F from"@clack/prompts";import Uo from"os";import{resolve as zo}from"path";import{promises as Vo}from"fs";import*as Ft from"toml";import Dt from"fs-extra";import*as Ze from"path";import*as _t from"os";import{createWriteStream as fo}from"fs";function Se(e){let t=null;try{t=fo(e,{flags:"a",mode:384})}catch(n){}let o=(n,i)=>{let s=n?`${n} ${i}
1
+ import{runMain as Fn}from"citty";import{defineCommand as Mn}from"citty";import{defineCommand as gn}from"citty";import{resolve as ut}from"path";import{promises as Zt}from"fs";import*as Be from"os";import*as eo from"toml";import*as F from"@clack/prompts";import Yo from"os";import{resolve as Jo}from"path";import{promises as Xo}from"fs";import*as Ut from"toml";import Ot from"fs-extra";import*as tt from"path";import*as Mt from"os";import{createWriteStream as go}from"fs";function Se(e){let t=null;try{t=go(e,{flags:"a",mode:384})}catch(n){}let o=(n,i)=>{let s=n?`${n} ${i}
2
2
  `:`${i}
3
- `;process.stdout.write(s),t&&t.write(s)};return{log:n=>o("",n),info:n=>o("",n),ok:n=>o("\u2714",n),warn:n=>o("\u26A0",n),err:n=>o("\u2716",n)}}import{$ as ee}from"zx";import{which as uo,$ as mo}from"zx";import{spawn as go}from"child_process";async function $(e){try{return await uo(e),!0}catch{return!1}}async function yt(){return await $("brew")?"brew":await $("apt-get")?"apt":await $("dnf")?"dnf":await $("pacman")?"pacman":await $("zypper")?"zypper":"none"}function pe(e){return typeof process.getuid=="function"&&process.getuid()===0?{cmd:e,argsPrefix:[]}:{cmd:"sudo",argsPrefix:[e]}}async function bt(e){if(await $("pnpm"))try{let o=(await mo`pnpm bin -g`.quiet()).stdout.trim();return o?{pm:"pnpm",binDir:o}:(e?.warn('Detected pnpm but global bin dir is not configured; skipping global Node installs to avoid duplicates. Run "pnpm setup" then re-run.'),{pm:"none",reason:"pnpm-misconfigured"})}catch{return e?.warn('Detected pnpm but global bin dir is not configured; skipping global Node installs to avoid duplicates. Run "pnpm setup" then re-run.'),{pm:"none",reason:"pnpm-error"}}return await $("npm")?{pm:"npm",reason:"npm-default"}:{pm:"none",reason:"not-found"}}async function I(e,t,o={dryRun:!1}){if(o.dryRun){let i=[e,...t].map(s=>s.includes(" ")?`"${s}"`:s).join(" ");o.logger?.log(`[dry-run] ${i}`);return}let n=go(e,t,{stdio:"inherit",cwd:o.cwd||process.cwd(),shell:!1});await new Promise((i,s)=>{n.on("error",s),n.on("exit",r=>{if(r===0)return i();s(new Error(`Command failed (${r}): ${e} ${t.join(" ")}`))})})}function O(e){let t=new Date().toISOString().replace(/[:.]/g,"-").slice(0,-5);return`${e}.backup.${t}`}import kt from"fs-extra";import*as $e from"path";import*as de from"os";import*as te from"@clack/prompts";async function vt(e){let t=await $("node"),o=await $("npm");if(t&&o){let i=(await ee`node -v`).stdout.trim();e.logger.ok(`Node.js present (${i})`);return}switch(e.options.installNode){case"nvm":await wo(e);break;case"brew":await ho(e);break;case"skip":e.logger.warn("Skipping Node installation; please install Node 18+ manually");return}if(await $("node")){let i=(await ee`node -v`).stdout.trim();e.logger.ok(`Node.js installed (${i})`)}else throw e.logger.err("Node installation failed"),new Error("Node.js installation failed")}async function wo(e){if(e.logger.info("Installing Node.js via nvm"),e.options.dryRun){e.logger.log("[dry-run] install nvm + Node LTS");return}let t=process.stdout.isTTY&&!e.options.dryRun&&!e.options.skipConfirmation&&!e.options.assumeYes,o=$e.join(e.homeDir,".nvm");if(!await kt.pathExists(o)){if(t){let i=await te.confirm({message:"This will download and run the nvm installer script (from GitHub) and then install Node LTS. Continue?",initialValue:!0});if(te.isCancel(i)||!i)throw new Error("Node installation aborted by user")}e.logger.info("Installing nvm..."),await ee`bash -c "curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash"`}let n=`export NVM_DIR="${o}" && [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" && nvm install --lts`;await ee`bash -c ${n}`}async function ho(e){e.logger.info("Installing Node.js via Homebrew");let t=process.stdout.isTTY&&!e.options.dryRun&&!e.options.skipConfirmation&&!e.options.assumeYes;if(!await $("brew"))if(de.platform()==="darwin"){if(e.logger.info("Homebrew not found; installing Homebrew"),e.options.dryRun){e.logger.log("[dry-run] install Homebrew");return}if(t){let n=await te.confirm({message:"This will download and run the official Homebrew installer script (from GitHub). Continue?",initialValue:!0});if(te.isCancel(n)||!n)throw new Error("Homebrew installation aborted by user")}await ee`/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`;let o=de.platform()==="darwin"&&de.arch()==="arm64"?"/opt/homebrew/bin/brew":"/usr/local/bin/brew";if(await kt.pathExists(o)){let n=$e.dirname(o);process.env.PATH=`${n}:${process.env.PATH||""}`;try{let s=(await ee`${o} shellenv`).stdout.trim().match(/export PATH="([^"]+)"/);s&&(process.env.PATH=`${s[1]}:${process.env.PATH||""}`)}catch(i){}}}else throw new Error("Homebrew is only available on macOS");await I("brew",["install","node"],{dryRun:e.options.dryRun,logger:e.logger})}import*as oe from"@clack/prompts";import{$ as Ve}from"zx";var Ke="@openai/codex";async function xe(e){let t=await bo(),o=await yo(e),n=!!(t.found&&t.version&&o&&t.version!==o);return{found:t.found,version:t.version,latest:o,updateAvailable:n}}async function yo(e){try{let o=(await Ve`npm view ${Ke} version`.quiet()).stdout.trim();if(!o){e?.warn("Could not fetch latest Codex CLI version; skipping upgrade check");return}return o}catch(t){e?.warn(`Error checking latest Codex CLI version: ${t}`);return}}async function bo(){if(!await $("codex"))return{found:!1};let t="";try{let o=await Ve`codex --version`.quiet().nothrow();t=ko(o.stdout||"")}catch(o){}if(!t)try{let o=await Ve`npm ls -g ${Ke} --depth=0 --json`.quiet().nothrow();t=JSON.parse(o.stdout||"{}").dependencies?.[Ke]?.version||""}catch(o){}return{found:!0,version:t||void 0}}function ko(e){let t=e.match(/(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)/);return t?t[1]:""}import*as Ie from"@clack/prompts";async function Te(e){let t=await bt(e.logger);if(t.pm==="pnpm")return"pnpm";if(t.pm==="npm")return"npm";if(t.pm==="none"&&t.reason?.startsWith("pnpm-")){if(e.interactive){let o=await Ie.select({message:"pnpm is installed but its global bin is not configured. How should we proceed?",initialValue:"npm",options:[{value:"npm",label:"Use npm for global installs this run"},{value:"skip",label:'Skip global installs (run "pnpm setup" then re-run)'}]});return Ie.isCancel(o)||o==="skip"?(e.logger?.warn('Skipping global Node installs; pnpm is misconfigured. Run "pnpm setup" then re-run.'),"none"):(e.logger?.info("pnpm misconfigured; falling back to npm for global installs."),"npm")}return e.logger?.warn('pnpm detected but global bin dir is not configured; falling back to npm for this run. Run "pnpm setup" to use pnpm.'),"npm"}return"none"}var Ct="@openai/codex";async function St(e){if(e.options.installCodexCli==="no"){e.logger.info("Skipping Codex CLI install (user choice)");return}let t=process.stdout.isTTY&&!e.options.dryRun&&!e.options.skipConfirmation&&!e.options.assumeYes,o=await xe(e.logger);if(o.found){let a=o.version?`v${o.version}`:"unknown version";e.logger.info(`Found Codex CLI ${a}. Checking for newer version...`)}else e.logger.info("Codex CLI not found.");let n=!1,i=!1;if(o.found)if(o.updateAvailable){let a=o.latest?`v${o.latest}`:"a newer version";if(e.options.installCodexCli==="yes")i=!0;else if(t){let p=await oe.confirm({message:`Codex CLI ${o.version} found; latest is ${a}. Update now?`,initialValue:!0});oe.isCancel(p)?e.logger.info("Codex CLI update cancelled; keeping existing version."):p?i=!0:e.logger.info("Keeping existing Codex CLI version as requested.")}else i=!0}else o.found&&(o.latest&&o.version?e.logger.ok(`Codex CLI up-to-date (${o.version})`):e.logger.ok("Codex CLI found; unable to verify latest version."));else if(e.options.installCodexCli==="yes")n=!0;else if(t){let a=await oe.confirm({message:"Codex CLI not found. Install now?",initialValue:!0});oe.isCancel(a)?e.logger.info("Codex CLI install cancelled."):a?n=!0:e.logger.info("Skipping Codex CLI install.")}else n=!0;let s=[];if((n||i)&&(o.latest?s.push(`${Ct}@${o.latest}`):s.push(Ct)),s.length===0)return;let r=await Te({logger:e.logger,interactive:process.stdout.isTTY&&!e.options.dryRun&&!e.options.skipConfirmation&&!e.options.assumeYes});r==="none"?e.logger.warn("Skipping global Node installs because no supported package manager was found."):r==="pnpm"?(e.logger.info("Installing/updating Codex CLI via pnpm"),await I("pnpm",["add","-g",...s],{dryRun:e.options.dryRun,logger:e.logger})):(e.logger.info("Installing/updating Codex CLI via npm"),await I("npm",["install","-g",...s],{dryRun:e.options.dryRun,logger:e.logger})),await $("codex")?e.logger.ok("Codex CLI installed"):e.logger.err("Codex CLI not found after install")}var $t=[{id:"rg",label:"rg",bins:["rg"],packages:{brew:["ripgrep"],apt:["ripgrep"],dnf:["ripgrep"],pacman:["ripgrep"],zypper:["ripgrep"]}},{id:"fd",label:"fd",bins:["fd","fdfind"],packages:{brew:["fd"],apt:["fd-find"],dnf:["fd-find"],pacman:["fd"],zypper:["fd"]}},{id:"fzf",label:"fzf",bins:["fzf"],packages:{brew:["fzf"],apt:["fzf"],dnf:["fzf"],pacman:["fzf"],zypper:["fzf"]}},{id:"jq",label:"jq",bins:["jq"],packages:{brew:["jq"],apt:["jq"],dnf:["jq"],pacman:["jq"],zypper:["jq"]}},{id:"yq",label:"yq",bins:["yq"],packages:{brew:["yq"],apt:["yq"],dnf:["yq"],pacman:["yq"],zypper:["yq"]}},{id:"ast-grep",label:"ast-grep",bins:["ast-grep","sg"],packages:{brew:["ast-grep"],apt:["ast-grep"],dnf:["ast-grep"],pacman:["ast-grep"],zypper:["ast-grep"]}},{id:"bat",label:"bat",bins:["bat","batcat"],packages:{brew:["bat"],apt:["bat"],dnf:["bat"],pacman:["bat"],zypper:["bat"]}},{id:"git",label:"git",bins:["git"],packages:{brew:["git"],apt:["git"],dnf:["git"],pacman:["git"],zypper:["git"]}},{id:"git-delta",label:"git-delta",bins:["delta"],packages:{brew:["git-delta"],apt:["git-delta"],dnf:["git-delta"],pacman:["git-delta"],zypper:["git-delta"]}},{id:"gh",label:"gh",bins:["gh"],packages:{brew:["gh"],apt:["gh"],dnf:["gh"],pacman:["github-cli"],zypper:["gh"]}}],vo=new Set($t.map(e=>e.id));function xt(e){return vo.has(e)}function ne(){return $t}import*as He from"path";import Ye from"fs-extra";import{which as Co}from"zx";async function Pe(e){if(e.options.installTools==="skip"){e.logger.info("Skipping developer tool installs (user choice)");return}let t=So(e.options.installTools,e.options.toolsSelected);if(t.length===0){e.logger.info("Skipping developer tool installs (no tools selected)");return}let o=await yt();if(e.logger.info(`Detected package manager: ${o}`),o==="none"){e.logger.warn("Could not detect a supported package manager; please install tools manually");return}let n=ne().filter(s=>t.includes(s.id)),i=$o(n,o);if(i.length>0)switch(o!=="brew"&&(typeof process.getuid=="function"&&process.getuid()===0||e.logger.warn("Package installation may require sudo password. Please enter it when prompted.")),o){case"brew":await I("brew",["update"],{dryRun:e.options.dryRun,logger:e.logger}),await I("brew",["install",...i],{dryRun:e.options.dryRun,logger:e.logger});break;case"apt":{let{cmd:s,argsPrefix:r}=pe("apt-get");e.logger.info("Running apt-get update...");try{await I(s,[...r,"update","-y"],{dryRun:e.options.dryRun,logger:e.logger})}catch{e.logger.warn(`apt-get update failed; install tools manually: ${i.join(", ")}`);break}for(let a of i)try{await I(s,[...r,"install","-y",a],{dryRun:e.options.dryRun,logger:e.logger})}catch{e.logger.warn(`apt-get install failed for ${a}; install manually if needed.`)}}break;case"dnf":{let{cmd:s,argsPrefix:r}=pe("dnf");await I(s,[...r,"install","-y",...i],{dryRun:e.options.dryRun,logger:e.logger}).catch(()=>{})}break;case"pacman":{let{cmd:s,argsPrefix:r}=pe("pacman");await I(s,[...r,"-Sy","--noconfirm",...i],{dryRun:e.options.dryRun,logger:e.logger}).catch(()=>{})}break;case"zypper":{let{cmd:s,argsPrefix:r}=pe("zypper");await I(s,[...r,"refresh"],{dryRun:e.options.dryRun,logger:e.logger}),await I(s,[...r,"install","-y",...i],{dryRun:e.options.dryRun,logger:e.logger}).catch(()=>{})}break}t.includes("fd")&&await It(e,"fdfind","fd"),t.includes("bat")&&await It(e,"batcat","bat"),await xo(e,n)}function So(e,t){return e==="all"?ne().map(o=>o.id):e==="select"?t?[...t]:[]:[]}function $o(e,t){let o=[];for(let n of e){let i=n.packages[t]||[];for(let s of i)o.includes(s)||o.push(s)}return o}async function It(e,t,o){if(!await $(t)||await $(o))return;let n=He.join(e.homeDir,".local","bin");await Ye.ensureDir(n);let i=He.join(n,o);if(await Ye.pathExists(i))return;let s=t;try{s=await Co(t)}catch(r){}if(e.options.dryRun){e.logger.log(`[dry-run] ln -s ${s} ${i}`);return}await Ye.symlink(s,i),e.logger.ok(`${o} alias created at ~/.local/bin/${o}`)}async function xo(e,t){for(let o of t)await Io(o)?e.logger.ok(`${o.id} \u2713`):e.logger.warn(`${o.id} not detected after install`)}async function Io(e){for(let t of e.bins)if(await $(t))return!0;return!1}import ce from"fs-extra";import*as Re from"path";var Tt={balanced:{root:[["approval_policy",'"on-request"'],["sandbox_mode",'"workspace-write"'],["model",'"gpt-5.2-codex"'],["model_reasoning_effort",'"medium"'],["model_reasoning_summary",'"concise"']],features:[["web_search_request","true"]],tables:{sandbox_workspace_write:[["network_access","true"]]}},safe:{root:[["approval_policy",'"on-failure"'],["sandbox_mode",'"read-only"'],["model",'"gpt-5.2-codex"'],["model_reasoning_effort",'"medium"'],["model_reasoning_summary",'"concise"']],features:[["web_search_request","false"]]},yolo:{root:[["approval_policy",'"never"'],["sandbox_mode",'"danger-full-access"'],["model",'"gpt-5.2-codex"'],["model_reasoning_effort",'"high"'],["model_reasoning_summary",'"detailed"']],features:[["web_search_request","true"]]}},To=`# ~/.codex/config.toml \u2014 managed by codex-1up (patch mode)
4
- `;async function Pt(e){let t=Re.join(e.homeDir,".codex","config.toml");await ce.ensureDir(Re.dirname(t));let o=await ce.pathExists(t),n=o?await ce.readFile(t,"utf8"):To,i=Lo(n),s=Do(i.toml),r=new Je(s.toml),a=i.changed||s.changed;if(a=Po(r,e.options.profileScope,e.options.profile,e.options.profileMode,e.options.profilesSelected)||a,a=Ao(r,e.options.profile,e.options.setDefaultProfile)||a,a=Ro(r,e.options.notificationSound)||a,!a){e.logger.info("Config already up to date; no changes needed.");return}let p=r.content();if(e.options.dryRun){e.logger.log(`[dry-run] write ${t}`),e.logger.log("[dry-run] config content omitted"),e.logger.log(`[dry-run] would write ${p.length} bytes`);return}if(o){let l=O(t);await ce.copy(t,l),e.logger.info(`Backed up current config to ${l}`)}await ce.writeFile(t,p,"utf8"),e.logger.ok("Updated ~/.codex/config.toml with requested settings.")}function Po(e,t,o,n,i){let s=[];if(t==="all")s=Object.keys(Tt);else if(t==="selected")s=i||[];else{if(o==="skip")return!1;s=[o]}if(s.length===0)return!1;let r=!1;for(let a of s){let p=Tt[a];if(n==="overwrite"){r=e.replaceTable(`profiles.${a}`,p.root)||r,r=e.replaceTable(`profiles.${a}.features`,p.features)||r;for(let[l,c]of Object.entries(p.tables||{}))r=e.replaceTable(`profiles.${a}.${l}`,c)||r}else{e.ensureTable(`profiles.${a}`);for(let[l,c]of p.root)r=e.setKey(`profiles.${a}`,l,c,{mode:"if-missing"})||r;e.ensureTable(`profiles.${a}.features`);for(let[l,c]of p.features)r=e.setKey(`profiles.${a}.features`,l,c,{mode:"if-missing"})||r;for(let[l,c]of Object.entries(p.tables||{})){e.ensureTable(`profiles.${a}.${l}`);for(let[d,u]of c)r=e.setKey(`profiles.${a}.${l}`,d,u,{mode:"if-missing"})||r}}}return r}function Ao(e,t,o){return!o||t==="skip"?!1:e.setRootKey("profile",`"${t}"`,{mode:"force"})}function Ro(e,t){if(!t||t==="none")return!1;e.ensureTable("tui");let o=e.getValue("tui","notifications");if(o){let n=o.trim().toLowerCase();if(n.startsWith("true")||n.startsWith("["))return!1}return e.setKey("tui","notifications","true",{mode:"force"})}var Je=class{text;constructor(t){this.text=t||""}content(){return No(this.text)}ensureTable(t){if(this.hasTable(t))return!1;let o=this.text.length===0?"":Ae(this.text);return this.text=o+`[${t}]
5
- `,!0}setKey(t,o,n,i){let s=ie(this.text,t);if(!s)return this.ensureTable(t),this.setKey(t,o,n,i);let r=this.text.slice(s.start,s.end),p=new RegExp(`^\\s*${fe(o)}\\s*=.*$`,"m").exec(r);if(p){if(i.mode==="if-missing")return!1;let C=this.text,R=s.start+p.index,D=R+p[0].length;return this.text=C.slice(0,R)+`${o} = ${n}`+C.slice(D),this.text!==C}let l=this.text,c=s.end,d=l.slice(0,c),u=l.slice(c),w=d.length>0&&!d.endsWith(`
3
+ `;process.stdout.write(s),t&&t.write(s)};return{log:n=>o("",n),info:n=>o("",n),ok:n=>o("\u2714",n),warn:n=>o("\u26A0",n),err:n=>o("\u2716",n)}}import{$ as ee}from"zx";import{which as ho,$ as wo}from"zx";import{spawn as yo}from"child_process";async function S(e){try{return await ho(e),!0}catch{return!1}}async function kt(){return await S("brew")?"brew":await S("apt-get")?"apt":await S("dnf")?"dnf":await S("pacman")?"pacman":await S("zypper")?"zypper":"none"}function de(e){return typeof process.getuid=="function"&&process.getuid()===0?{cmd:e,argsPrefix:[]}:{cmd:"sudo",argsPrefix:[e]}}async function vt(e){if(await S("pnpm"))try{let o=(await wo`pnpm bin -g`.quiet()).stdout.trim();return o?{pm:"pnpm",binDir:o}:(e?.warn('Detected pnpm but global bin dir is not configured; skipping global Node installs to avoid duplicates. Run "pnpm setup" then re-run.'),{pm:"none",reason:"pnpm-misconfigured"})}catch{return e?.warn('Detected pnpm but global bin dir is not configured; skipping global Node installs to avoid duplicates. Run "pnpm setup" then re-run.'),{pm:"none",reason:"pnpm-error"}}return await S("npm")?{pm:"npm",reason:"npm-default"}:{pm:"none",reason:"not-found"}}async function I(e,t,o={dryRun:!1}){if(o.dryRun){let i=[e,...t].map(s=>s.includes(" ")?`"${s}"`:s).join(" ");o.logger?.log(`[dry-run] ${i}`);return}let n=yo(e,t,{stdio:"inherit",cwd:o.cwd||process.cwd(),shell:!1});await new Promise((i,s)=>{n.on("error",s),n.on("exit",r=>{if(r===0)return i();s(new Error(`Command failed (${r}): ${e} ${t.join(" ")}`))})})}function O(e){let t=new Date().toISOString().replace(/[:.]/g,"-").slice(0,-5);return`${e}.backup.${t}`}import Ct from"fs-extra";import*as $e from"path";import*as ce from"os";import*as te from"@clack/prompts";async function St(e){let t=await S("node"),o=await S("npm");if(t&&o){let i=(await ee`node -v`).stdout.trim();e.logger.ok(`Node.js present (${i})`);return}switch(e.options.installNode){case"nvm":await bo(e);break;case"brew":await ko(e);break;case"skip":e.logger.warn("Skipping Node installation; please install Node 18+ manually");return}if(await S("node")){let i=(await ee`node -v`).stdout.trim();e.logger.ok(`Node.js installed (${i})`)}else throw e.logger.err("Node installation failed"),new Error("Node.js installation failed")}async function bo(e){if(e.logger.info("Installing Node.js via nvm"),e.options.dryRun){e.logger.log("[dry-run] install nvm + Node LTS");return}let t=process.stdout.isTTY&&!e.options.dryRun&&!e.options.skipConfirmation&&!e.options.assumeYes,o=$e.join(e.homeDir,".nvm");if(!await Ct.pathExists(o)){if(t){let i=await te.confirm({message:"This will download and run the nvm installer script (from GitHub) and then install Node LTS. Continue?",initialValue:!0});if(te.isCancel(i)||!i)throw new Error("Node installation aborted by user")}e.logger.info("Installing nvm..."),await ee`bash -c "curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash"`}let n=`export NVM_DIR="${o}" && [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" && nvm install --lts`;await ee`bash -c ${n}`}async function ko(e){e.logger.info("Installing Node.js via Homebrew");let t=process.stdout.isTTY&&!e.options.dryRun&&!e.options.skipConfirmation&&!e.options.assumeYes;if(!await S("brew"))if(ce.platform()==="darwin"){if(e.logger.info("Homebrew not found; installing Homebrew"),e.options.dryRun){e.logger.log("[dry-run] install Homebrew");return}if(t){let n=await te.confirm({message:"This will download and run the official Homebrew installer script (from GitHub). Continue?",initialValue:!0});if(te.isCancel(n)||!n)throw new Error("Homebrew installation aborted by user")}await ee`/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`;let o=ce.platform()==="darwin"&&ce.arch()==="arm64"?"/opt/homebrew/bin/brew":"/usr/local/bin/brew";if(await Ct.pathExists(o)){let n=$e.dirname(o);process.env.PATH=`${n}:${process.env.PATH||""}`;try{let s=(await ee`${o} shellenv`).stdout.trim().match(/export PATH="([^"]+)"/);s&&(process.env.PATH=`${s[1]}:${process.env.PATH||""}`)}catch(i){}}}else throw new Error("Homebrew is only available on macOS");await I("brew",["install","node"],{dryRun:e.options.dryRun,logger:e.logger})}import*as oe from"@clack/prompts";import{$ as Ke}from"zx";var He="@openai/codex";async function xe(e){let t=await Co(),o=await vo(e),n=!!(t.found&&t.version&&o&&t.version!==o);return{found:t.found,version:t.version,latest:o,updateAvailable:n}}async function vo(e){try{let o=(await Ke`npm view ${He} version`.quiet()).stdout.trim();if(!o){e?.warn("Could not fetch latest Codex CLI version; skipping upgrade check");return}return o}catch(t){e?.warn(`Error checking latest Codex CLI version: ${t}`);return}}async function Co(){if(!await S("codex"))return{found:!1};let t="";try{let o=await Ke`codex --version`.quiet().nothrow();t=So(o.stdout||"")}catch(o){}if(!t)try{let o=await Ke`npm ls -g ${He} --depth=0 --json`.quiet().nothrow();t=JSON.parse(o.stdout||"{}").dependencies?.[He]?.version||""}catch(o){}return{found:!0,version:t||void 0}}function So(e){let t=e.match(/(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)/);return t?t[1]:""}import*as Ie from"@clack/prompts";async function Te(e){let t=await vt(e.logger);if(t.pm==="pnpm")return"pnpm";if(t.pm==="npm")return"npm";if(t.pm==="none"&&t.reason?.startsWith("pnpm-")){if(e.interactive){let o=await Ie.select({message:"pnpm is installed but its global bin is not configured. How should we proceed?",initialValue:"npm",options:[{value:"npm",label:"Use npm for global installs this run"},{value:"skip",label:'Skip global installs (run "pnpm setup" then re-run)'}]});return Ie.isCancel(o)||o==="skip"?(e.logger?.warn('Skipping global Node installs; pnpm is misconfigured. Run "pnpm setup" then re-run.'),"none"):(e.logger?.info("pnpm misconfigured; falling back to npm for global installs."),"npm")}return e.logger?.warn('pnpm detected but global bin dir is not configured; falling back to npm for this run. Run "pnpm setup" to use pnpm.'),"npm"}return"none"}var $t="@openai/codex";async function xt(e){if(e.options.installCodexCli==="no"){e.logger.info("Skipping Codex CLI install (user choice)");return}let t=process.stdout.isTTY&&!e.options.dryRun&&!e.options.skipConfirmation&&!e.options.assumeYes,o=await xe(e.logger);if(o.found){let a=o.version?`v${o.version}`:"unknown version";e.logger.info(`Found Codex CLI ${a}. Checking for newer version...`)}else e.logger.info("Codex CLI not found.");let n=!1,i=!1;if(o.found)if(o.updateAvailable){let a=o.latest?`v${o.latest}`:"a newer version";if(e.options.installCodexCli==="yes")i=!0;else if(t){let p=await oe.confirm({message:`Codex CLI ${o.version} found; latest is ${a}. Update now?`,initialValue:!0});oe.isCancel(p)?e.logger.info("Codex CLI update cancelled; keeping existing version."):p?i=!0:e.logger.info("Keeping existing Codex CLI version as requested.")}else i=!0}else o.found&&(o.latest&&o.version?e.logger.ok(`Codex CLI up-to-date (${o.version})`):e.logger.ok("Codex CLI found; unable to verify latest version."));else if(e.options.installCodexCli==="yes")n=!0;else if(t){let a=await oe.confirm({message:"Codex CLI not found. Install now?",initialValue:!0});oe.isCancel(a)?e.logger.info("Codex CLI install cancelled."):a?n=!0:e.logger.info("Skipping Codex CLI install.")}else n=!0;let s=[];if((n||i)&&(o.latest?s.push(`${$t}@${o.latest}`):s.push($t)),s.length===0)return;let r=await Te({logger:e.logger,interactive:process.stdout.isTTY&&!e.options.dryRun&&!e.options.skipConfirmation&&!e.options.assumeYes});r==="none"?e.logger.warn("Skipping global Node installs because no supported package manager was found."):r==="pnpm"?(e.logger.info("Installing/updating Codex CLI via pnpm"),await I("pnpm",["add","-g",...s],{dryRun:e.options.dryRun,logger:e.logger})):(e.logger.info("Installing/updating Codex CLI via npm"),await I("npm",["install","-g",...s],{dryRun:e.options.dryRun,logger:e.logger})),await S("codex")?e.logger.ok("Codex CLI installed"):e.logger.err("Codex CLI not found after install")}var It=[{id:"rg",label:"rg",bins:["rg"],packages:{brew:["ripgrep"],apt:["ripgrep"],dnf:["ripgrep"],pacman:["ripgrep"],zypper:["ripgrep"]}},{id:"fd",label:"fd",bins:["fd","fdfind"],packages:{brew:["fd"],apt:["fd-find"],dnf:["fd-find"],pacman:["fd"],zypper:["fd"]}},{id:"fzf",label:"fzf",bins:["fzf"],packages:{brew:["fzf"],apt:["fzf"],dnf:["fzf"],pacman:["fzf"],zypper:["fzf"]}},{id:"jq",label:"jq",bins:["jq"],packages:{brew:["jq"],apt:["jq"],dnf:["jq"],pacman:["jq"],zypper:["jq"]}},{id:"yq",label:"yq",bins:["yq"],packages:{brew:["yq"],apt:["yq"],dnf:["yq"],pacman:["yq"],zypper:["yq"]}},{id:"ast-grep",label:"ast-grep",bins:["ast-grep","sg"],packages:{brew:["ast-grep"],apt:["ast-grep"],dnf:["ast-grep"],pacman:["ast-grep"],zypper:["ast-grep"]}},{id:"bat",label:"bat",bins:["bat","batcat"],packages:{brew:["bat"],apt:["bat"],dnf:["bat"],pacman:["bat"],zypper:["bat"]}},{id:"git",label:"git",bins:["git"],packages:{brew:["git"],apt:["git"],dnf:["git"],pacman:["git"],zypper:["git"]}},{id:"git-delta",label:"git-delta",bins:["delta"],packages:{brew:["git-delta"],apt:["git-delta"],dnf:["git-delta"],pacman:["git-delta"],zypper:["git-delta"]}},{id:"gh",label:"gh",bins:["gh"],packages:{brew:["gh"],apt:["gh"],dnf:["gh"],pacman:["github-cli"],zypper:["gh"]}}],$o=new Set(It.map(e=>e.id));function Tt(e){return $o.has(e)}function ne(){return It}import*as Je from"path";import Ye from"fs-extra";import{which as xo}from"zx";async function Pe(e){if(e.options.installTools==="skip"){e.logger.info("Skipping developer tool installs (user choice)");return}let t=Io(e.options.installTools,e.options.toolsSelected);if(t.length===0){e.logger.info("Skipping developer tool installs (no tools selected)");return}let o=await kt();if(e.logger.info(`Detected package manager: ${o}`),o==="none"){e.logger.warn("Could not detect a supported package manager; please install tools manually");return}let n=ne().filter(s=>t.includes(s.id)),i=To(n,o);if(i.length>0)switch(o!=="brew"&&(typeof process.getuid=="function"&&process.getuid()===0||e.logger.warn("Package installation may require sudo password. Please enter it when prompted.")),o){case"brew":await I("brew",["update"],{dryRun:e.options.dryRun,logger:e.logger}),await I("brew",["install",...i],{dryRun:e.options.dryRun,logger:e.logger});break;case"apt":{t.includes("gh")&&!await S("gh")&&await Ao(e);let{cmd:s,argsPrefix:r}=de("apt-get");e.logger.info("Running apt-get update...");try{await I(s,[...r,"update","-y"],{dryRun:e.options.dryRun,logger:e.logger})}catch{e.logger.warn(`apt-get update failed; install tools manually: ${i.join(", ")}`);break}for(let a of i)try{await I(s,[...r,"install","-y",a],{dryRun:e.options.dryRun,logger:e.logger})}catch{e.logger.warn(`apt-get install failed for ${a}; install manually if needed.`)}}break;case"dnf":{let{cmd:s,argsPrefix:r}=de("dnf");await I(s,[...r,"install","-y",...i],{dryRun:e.options.dryRun,logger:e.logger}).catch(()=>{})}break;case"pacman":{let{cmd:s,argsPrefix:r}=de("pacman");await I(s,[...r,"-Sy","--noconfirm",...i],{dryRun:e.options.dryRun,logger:e.logger}).catch(()=>{})}break;case"zypper":{let{cmd:s,argsPrefix:r}=de("zypper");await I(s,[...r,"refresh"],{dryRun:e.options.dryRun,logger:e.logger}),await I(s,[...r,"install","-y",...i],{dryRun:e.options.dryRun,logger:e.logger}).catch(()=>{})}break}t.includes("fd")&&await Pt(e,"fdfind","fd"),t.includes("bat")&&await Pt(e,"batcat","bat"),await Po(e,n)}function Io(e,t){return e==="all"?ne().map(o=>o.id):e==="select"?t?[...t]:[]:[]}function To(e,t){let o=[];for(let n of e){let i=n.packages[t]||[];for(let s of i)o.includes(s)||o.push(s)}return o}async function Pt(e,t,o){if(!await S(t)||await S(o))return;let n=Je.join(e.homeDir,".local","bin");await Ye.ensureDir(n);let i=Je.join(n,o);if(await Ye.pathExists(i))return;let s=t;try{s=await xo(t)}catch(r){}if(e.options.dryRun){e.logger.log(`[dry-run] ln -s ${s} ${i}`);return}await Ye.symlink(s,i),e.logger.ok(`${o} alias created at ~/.local/bin/${o}`)}async function Po(e,t){for(let o of t)await Ro(o)?e.logger.ok(`${o.id} \u2713`):e.logger.warn(`${o.id} not detected after install`)}async function Ro(e){for(let t of e.bins)if(await S(t))return!0;return!1}async function Ao(e){let t=["set -euo pipefail","if [ -f /etc/apt/sources.list.d/github-cli.list ]; then exit 0; fi",'SUDO=""','if [ "$(id -u)" -ne 0 ]; then SUDO="sudo"; fi',"$SUDO mkdir -p -m 755 /etc/apt/keyrings","if command -v curl >/dev/null 2>&1; then"," curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | $SUDO tee /etc/apt/keyrings/githubcli-archive-keyring.gpg >/dev/null","elif command -v wget >/dev/null 2>&1; then"," wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | $SUDO tee /etc/apt/keyrings/githubcli-archive-keyring.gpg >/dev/null","else",' echo "Missing curl/wget; cannot set up GitHub CLI apt repo automatically." 1>&2'," exit 0","fi","$SUDO chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg",'ARCH="$(dpkg --print-architecture)"','echo "deb [arch=${ARCH} signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | $SUDO tee /etc/apt/sources.list.d/github-cli.list >/dev/null'].join(`
4
+ `);try{await I("bash",["-lc",t],{dryRun:e.options.dryRun,logger:e.logger})}catch{e.logger.warn("Failed to set up GitHub CLI apt repo; will still try apt-get install gh (may fail).")}}import fe from"fs-extra";import*as Ee from"path";var Xe={balanced:{root:[["approval_policy",'"on-request"'],["sandbox_mode",'"workspace-write"'],["model",'"gpt-5.2-codex"'],["model_reasoning_effort",'"medium"'],["model_reasoning_summary",'"detailed"']],features:[["web_search_request","true"]],tables:{sandbox_workspace_write:[["network_access","true"]]}},safe:{root:[["approval_policy",'"on-failure"'],["sandbox_mode",'"read-only"'],["model",'"gpt-5.2-codex"'],["model_reasoning_effort",'"medium"'],["model_reasoning_summary",'"detailed"']],features:[["web_search_request","false"]]},yolo:{root:[["approval_policy",'"never"'],["sandbox_mode",'"danger-full-access"'],["model",'"gpt-5.2-codex"'],["model_reasoning_effort",'"high"'],["model_reasoning_summary",'"detailed"']],features:[["web_search_request","true"]]}},Eo=`# ~/.codex/config.toml \u2014 managed by codex-1up (patch mode)
5
+ `;async function Et(e){let t=Ee.join(e.homeDir,".codex","config.toml");await fe.ensureDir(Ee.dirname(t));let o=await fe.pathExists(t),n=o?await fe.readFile(t,"utf8"):Eo,i=Go(n),s=Mo(i.toml),r=new Qe(s.toml),a=i.changed||s.changed;if(a=No(r,e.options.profileScope,e.options.profile,e.options.profileMode,e.options.profilesSelected)||a,a=Lo(r,e.options.profile,e.options.setDefaultProfile)||a,a=Do(r,e.options.notificationSound)||a,a=_o(r)||a,!a){e.logger.info("Config already up to date; no changes needed.");return}let p=r.content();if(e.options.dryRun){e.logger.log(`[dry-run] write ${t}`),e.logger.log("[dry-run] config content omitted"),e.logger.log(`[dry-run] would write ${p.length} bytes`);return}if(o){let l=O(t);await fe.copy(t,l),e.logger.info(`Backed up current config to ${l}`)}await fe.writeFile(t,p,"utf8"),e.logger.ok("Updated ~/.codex/config.toml with requested settings.")}function No(e,t,o,n,i){let s=[];if(t==="all")s=Object.keys(Xe);else if(t==="selected")s=i||[];else{if(o==="skip")return!1;s=[o]}if(s.length===0)return!1;let r=!1;for(let a of s){let p=Xe[a];if(n==="overwrite"){r=e.replaceTable(`profiles.${a}`,p.root)||r,r=e.replaceTable(`profiles.${a}.features`,p.features)||r;for(let[l,c]of Object.entries(p.tables||{}))r=e.replaceTable(`profiles.${a}.${l}`,c)||r}else{e.ensureTable(`profiles.${a}`);for(let[l,c]of p.root)r=e.setKey(`profiles.${a}`,l,c,{mode:"if-missing"})||r;e.ensureTable(`profiles.${a}.features`);for(let[l,c]of p.features)r=e.setKey(`profiles.${a}.features`,l,c,{mode:"if-missing"})||r;for(let[l,c]of Object.entries(p.tables||{})){e.ensureTable(`profiles.${a}.${l}`);for(let[d,u]of c)r=e.setKey(`profiles.${a}.${l}`,d,u,{mode:"if-missing"})||r}}}return r}function Lo(e,t,o){return!o||t==="skip"?!1:e.setRootKey("profile",`"${t}"`,{mode:"force"})}function Do(e,t){if(!t||t==="none")return!1;e.ensureTable("tui");let o=e.getValue("tui","notifications");if(o){let n=o.trim().toLowerCase();if(n.startsWith("true")||n.startsWith("["))return!1}return e.setKey("tui","notifications","true",{mode:"force"})}var Qe=class{text;constructor(t){this.text=t||""}content(){return Oo(this.text)}ensureTable(t){if(this.hasTable(t))return!1;let o=this.text.length===0?"":Ae(this.text);return this.text=o+`[${t}]
6
+ `,!0}setKey(t,o,n,i){let s=ie(this.text,t);if(!s)return this.ensureTable(t),this.setKey(t,o,n,i);let r=this.text.slice(s.start,s.end),p=new RegExp(`^\\s*${se(o)}\\s*=.*$`,"m").exec(r);if(p){if(i.mode==="if-missing")return!1;let C=this.text,A=s.start+p.index,D=A+p[0].length;return this.text=C.slice(0,A)+`${o} = ${n}`+C.slice(D),this.text!==C}let l=this.text,c=s.end,d=l.slice(0,c),u=l.slice(c),h=d.length>0&&!d.endsWith(`
6
7
  `),v=u.length>0&&!u.startsWith(`
7
- `),k=`${w?`
8
+ `),k=`${h?`
8
9
  `:""}${o} = ${n}
9
10
  ${v?`
10
- `:""}`;return this.text=d+k+u,this.text!==l}getValue(t,o){let n=ie(this.text,t);if(!n)return;let i=this.text.slice(n.start,n.end),r=new RegExp(`^\\s*${fe(o)}\\s*=\\s*(.+)$`,"m").exec(i);return r?r[1]:void 0}replaceTable(t,o){let n=o.map(([a,p])=>`${a} = ${p}`).join(`
11
+ `:""}`;return this.text=d+k+u,this.text!==l}getValue(t,o){let n=ie(this.text,t);if(!n)return;let i=this.text.slice(n.start,n.end),r=new RegExp(`^\\s*${se(o)}\\s*=\\s*(.+)$`,"m").exec(i);return r?r[1]:void 0}getRootValue(t){let o=Rt(this.text),n=this.text.slice(o.start,o.end),s=new RegExp(`^\\s*${se(t)}\\s*=\\s*(.+)$`,"m").exec(n);return s?s[1]:void 0}replaceTable(t,o){let n=o.map(([a,p])=>`${a} = ${p}`).join(`
11
12
  `),i=`[${t}]
12
13
  ${n}
13
14
 
14
- `,s=this.text,r=ie(this.text,t);if(!r){let a=s.length===0?"":Ae(s);return this.text=a+i,this.text!==s}return this.text=s.slice(0,r.start)+i+s.slice(r.end),this.text!==s}setRootKey(t,o,n){let i=Eo(this.text),s=this.text.slice(i.start,i.end),a=new RegExp(`^\\s*${fe(t)}\\s*=.*$`,"m").exec(s);if(a){if(n.mode==="if-missing")return!1;let v=this.text,k=i.start+a.index,C=k+a[0].length;return this.text=v.slice(0,k)+`${t} = ${o}`+v.slice(C),this.text!==v}let p=this.text,l=i.end,c=l>0&&!p.slice(0,l).endsWith(`
15
+ `,s=this.text,r=ie(this.text,t);if(!r){let a=s.length===0?"":Ae(s);return this.text=a+i,this.text!==s}return this.text=s.slice(0,r.start)+i+s.slice(r.end),this.text!==s}setRootKey(t,o,n){let i=Rt(this.text),s=this.text.slice(i.start,i.end),a=new RegExp(`^\\s*${se(t)}\\s*=.*$`,"m").exec(s);if(a){if(n.mode==="if-missing")return!1;let v=this.text,k=i.start+a.index,C=k+a[0].length;return this.text=v.slice(0,k)+`${t} = ${o}`+v.slice(C),this.text!==v}let p=this.text,l=i.end,c=l>0&&!p.slice(0,l).endsWith(`
15
16
  `),d=p.slice(l),u=d.length>0&&!d.startsWith(`
16
- `),w=`${c?`
17
+ `),h=`${c?`
17
18
  `:""}${t} = ${o}
18
19
  ${u?`
19
- `:""}`;return this.text=p.slice(0,l)+w+d,this.text!==p}hasTable(t){return ie(this.text,t)!==null}};function ie(e,t){let o=/^\s*\[([^\]]+)\]\s*$/gm,n=[],i;for(;i=o.exec(e);)n.push({name:i[1].trim(),index:i.index});for(let s=0;s<n.length;s++)if(n[s].name===t){let r=n[s].index,a=n[s+1]?.index??e.length;return{start:r,end:a}}return null}function Eo(e){let o=/^\s*\[([^\]]+)\]\s*$/gm.exec(e);return o?{start:0,end:o.index}:{start:0,end:e.length}}function fe(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function No(e){return e.endsWith(`
20
+ `:""}`;return this.text=p.slice(0,l)+h+d,this.text!==p}hasTable(t){return ie(this.text,t)!==null}};function ie(e,t){let o=/^\s*\[([^\]]+)\]\s*$/gm,n=[],i;for(;i=o.exec(e);)n.push({name:i[1].trim(),index:i.index});for(let s=0;s<n.length;s++)if(n[s].name===t){let r=n[s].index,a=n[s+1]?.index??e.length;return{start:r,end:a}}return null}function Rt(e){let o=/^\s*\[([^\]]+)\]\s*$/gm.exec(e);return o?{start:0,end:o.index}:{start:0,end:e.length}}function se(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function jo(e){let t=/^\s*\[profiles\.([^. \]]+)\]\s*$/gm,o=new Set,n;for(;n=t.exec(e);){let i=n[1]?.trim();i&&o.add(i)}return[...o]}function Re(e){if(!e)return;let t=e.trim(),o=/^"([^"]*)"\s*(?:#.*)?$/.exec(t);return o?o[1]:void 0}function At(e){return e?e.endsWith("-codex"):!1}function _o(e){let t=!1,o=Re(e.getRootValue("model"));if(At(o)){let s=Re(e.getRootValue("model_reasoning_summary"));s&&s!=="detailed"&&(t=e.setRootKey("model_reasoning_summary",'"detailed"',{mode:"force"})||t)}let n=e.content(),i=new Set([...Object.keys(Xe),...jo(n)]);for(let s of i){let r=`profiles.${s}`,a=Re(e.getValue(r,"model"));if(!At(a))continue;let p=Re(e.getValue(r,"model_reasoning_summary"));p&&p!=="detailed"&&(t=e.setKey(r,"model_reasoning_summary",'"detailed"',{mode:"force"})||t)}return t}function Oo(e){return e.endsWith(`
20
21
  `)?e:e+`
21
22
  `}function Ae(e){let t=e;return t.endsWith(`
22
23
  `)||(t+=`
23
24
  `),t.endsWith(`
24
25
 
25
26
  `)||(t+=`
26
- `),t}function Lo(e){let t="enable_experimental_windows_sandbox",o="experimental_windows_sandbox";if(!e.includes(t))return{toml:e,changed:!1};let n=e.split(/\r?\n/),i="",s=d=>d==="features"||/^profiles\.[^.]+\.features$/.test(d),r=new Set;for(let d of n){let u=d.match(/^\s*\[([^\]]+)\]\s*$/);if(u){i=u[1].trim();continue}/^\s*#/.test(d)||s(i)&&new RegExp(`^\\s*${o}\\s*=`).test(d)&&r.add(i)}i="";let a=!1,p,l=[];for(let d of n){let u=d.match(/^\s*\[([^\]]+)\]\s*$/);if(u){i=u[1].trim(),l.push(d);continue}if(!/^\s*#/.test(d)){if(i===""){let w=d.match(new RegExp(`^\\s*${t}\\s*=\\s*(.+?)\\s*$`));if(w){p=w[1],a=!0;continue}}if(s(i)&&new RegExp(`^\\s*${t}\\s*=`).test(d)){if(r.has(i)){a=!0;continue}l.push(d.replace(new RegExp(`^(\\s*)${t}(\\s*=\\s*)`),`$1${o}$2`)),a=!0;continue}}l.push(d)}let c=l.join(`
27
- `);if(p!==void 0){let d=ie(c,"features");if(!(()=>{if(!d)return!1;let w=c.slice(d.start,d.end);return new RegExp(`^\\s*${o}\\s*=`,"m").test(w)})()){let w=`${o} = ${p}`;if(d){let v=c.slice(0,d.end),k=c.slice(d.end),C=v.length>0&&!v.endsWith(`
28
- `),R=k.length>0&&!k.startsWith(`
27
+ `),t}function Go(e){let t="enable_experimental_windows_sandbox",o="experimental_windows_sandbox";if(!e.includes(t))return{toml:e,changed:!1};let n=e.split(/\r?\n/),i="",s=d=>d==="features"||/^profiles\.[^.]+\.features$/.test(d),r=new Set;for(let d of n){let u=d.match(/^\s*\[([^\]]+)\]\s*$/);if(u){i=u[1].trim();continue}/^\s*#/.test(d)||s(i)&&new RegExp(`^\\s*${o}\\s*=`).test(d)&&r.add(i)}i="";let a=!1,p,l=[];for(let d of n){let u=d.match(/^\s*\[([^\]]+)\]\s*$/);if(u){i=u[1].trim(),l.push(d);continue}if(!/^\s*#/.test(d)){if(i===""){let h=d.match(new RegExp(`^\\s*${t}\\s*=\\s*(.+?)\\s*$`));if(h){p=h[1],a=!0;continue}}if(s(i)&&new RegExp(`^\\s*${t}\\s*=`).test(d)){if(r.has(i)){a=!0;continue}l.push(d.replace(new RegExp(`^(\\s*)${t}(\\s*=\\s*)`),`$1${o}$2`)),a=!0;continue}}l.push(d)}let c=l.join(`
28
+ `);if(p!==void 0){let d=ie(c,"features");if(!(()=>{if(!d)return!1;let h=c.slice(d.start,d.end);return new RegExp(`^\\s*${o}\\s*=`,"m").test(h)})()){let h=`${o} = ${p}`;if(d){let v=c.slice(0,d.end),k=c.slice(d.end),C=v.length>0&&!v.endsWith(`
29
+ `),A=k.length>0&&!k.startsWith(`
29
30
  `);c=v+`${C?`
30
- `:""}${w}
31
- ${R?`
31
+ `:""}${h}
32
+ ${A?`
32
33
  `:""}`+k}else c=(c.length===0?"":Ae(c))+`[features]
33
- ${w}
34
- `;a=!0}}return{toml:c,changed:a}}function Do(e){let t=[{oldKey:"experimental_use_exec_command_tool",newKey:"streamable_shell"},{oldKey:"experimental_use_unified_exec_tool",newKey:"unified_exec"},{oldKey:"experimental_use_rmcp_client",newKey:"rmcp_client"},{oldKey:"include_apply_patch_tool",newKey:"apply_patch_freeform"}];if(!t.some(c=>e.includes(c.oldKey)))return{toml:e,changed:!1};function n(c){let d=c.trim(),u=/^(true|false)\b/i.exec(d);return u?u[1].toLowerCase():d||void 0}let i=e.split(/\r?\n/),s="",r={},a=[],p=!1;for(let c of i){let d=c.match(/^\s*\[([^\]]+)\]\s*$/);if(d){s=d[1].trim(),a.push(c);continue}if(s===""&&!/^\s*#/.test(c)){let u=!1;for(let{oldKey:w,newKey:v}of t){let k=c.match(new RegExp(`^\\s*${fe(w)}\\s*=\\s*(.+?)\\s*$`));if(k){let C=n(k[1]);C!==void 0&&(r[v]=C),p=!0,u=!0;break}}if(u)continue}a.push(c)}let l=a.join(`
35
- `);if(Object.keys(r).length===0)return{toml:l,changed:p};for(let{newKey:c}of t){let d=r[c];if(d===void 0)continue;let u=ie(l,"features");if((()=>{if(!u)return!1;let k=l.slice(u.start,u.end);return new RegExp(`^\\s*${fe(c)}\\s*=`,"m").test(k)})())continue;let v=`${c} = ${d}`;if(u){let k=l.slice(0,u.end),C=l.slice(u.end),R=k.length>0&&!k.endsWith(`
34
+ ${h}
35
+ `;a=!0}}return{toml:c,changed:a}}function Mo(e){let t=[{oldKey:"experimental_use_exec_command_tool",newKey:"streamable_shell"},{oldKey:"experimental_use_unified_exec_tool",newKey:"unified_exec"},{oldKey:"experimental_use_rmcp_client",newKey:"rmcp_client"},{oldKey:"include_apply_patch_tool",newKey:"apply_patch_freeform"}];if(!t.some(c=>e.includes(c.oldKey)))return{toml:e,changed:!1};function n(c){let d=c.trim(),u=/^(true|false)\b/i.exec(d);return u?u[1].toLowerCase():d||void 0}let i=e.split(/\r?\n/),s="",r={},a=[],p=!1;for(let c of i){let d=c.match(/^\s*\[([^\]]+)\]\s*$/);if(d){s=d[1].trim(),a.push(c);continue}if(s===""&&!/^\s*#/.test(c)){let u=!1;for(let{oldKey:h,newKey:v}of t){let k=c.match(new RegExp(`^\\s*${se(h)}\\s*=\\s*(.+?)\\s*$`));if(k){let C=n(k[1]);C!==void 0&&(r[v]=C),p=!0,u=!0;break}}if(u)continue}a.push(c)}let l=a.join(`
36
+ `);if(Object.keys(r).length===0)return{toml:l,changed:p};for(let{newKey:c}of t){let d=r[c];if(d===void 0)continue;let u=ie(l,"features");if((()=>{if(!u)return!1;let k=l.slice(u.start,u.end);return new RegExp(`^\\s*${se(c)}\\s*=`,"m").test(k)})())continue;let v=`${c} = ${d}`;if(u){let k=l.slice(0,u.end),C=l.slice(u.end),A=k.length>0&&!k.endsWith(`
36
37
  `),D=C.length>0&&!C.startsWith(`
37
- `);l=k+`${R?`
38
+ `);l=k+`${A?`
38
39
  `:""}${v}
39
40
  ${D?`
40
41
  `:""}`+C}else l=(l.length===0?"":Ae(l))+`[features]
41
42
  ${v}
42
- `;p=!0}return{toml:l,changed:p}}import G from"fs-extra";import*as se from"path";async function At(e){let t=se.join(e.homeDir,".codex","notify.sh"),o=se.join(e.rootDir,"templates","notification.sh");await G.ensureDir(se.dirname(t));let n=e.options.notify;if(n==="no"){e.logger.info("Skipping notify hook installation");return}if(!await G.pathExists(o)){e.logger.warn(`Notification template missing at ${o}; skipping notify hook install`);return}if(await G.pathExists(t))if(n==="yes"){let s=O(t);e.options.dryRun?e.logger.log(`[dry-run] cp ${t} ${s}`):await G.copy(t,s),e.options.dryRun?e.logger.log(`[dry-run] cp ${o} ${t}`):(await G.copy(o,t),await G.chmod(t,493)),e.logger.ok("Updated notify hook (backup created)")}else!e.options.assumeYes&&!e.options.skipConfirmation&&e.logger.info("Keeping existing notify hook");else e.options.dryRun?e.logger.log(`[dry-run] cp ${o} ${t}`):(await G.copy(o,t),await G.chmod(t,493)),e.logger.ok("Installed notify hook to ~/.codex/notify.sh");let i=se.join(e.homeDir,".codex","config.toml");await G.pathExists(i)?await jo(i,t,e):e.logger.warn(`Config not found at ${i}; run again after config is created`)}async function jo(e,t,o){if(o.options.dryRun){o.logger.log("[dry-run] update config notify and tui.notifications");return}let i=(await G.readFile(e,"utf8")).split(/\r?\n/),s="",r=null,a=null;for(let d=0;d<i.length;d++){let u=i[d],w=u.match(/^\s*\[([^\]]+)\]\s*$/);if(w){s=w[1],s==="tui"&&(a=d);continue}let v=/^\s*notify\s*=\s*\[/.test(u),k=/^\s*tui\.notifications\s*=/.test(u),C=/^\s*notifications\s*=/.test(u);v&&(s===""?r===null&&(r=d):/^profiles\.[^.]+\.features$/.test(s)&&(i.splice(d,1),d--)),k&&/^profiles\.[^.]+\.features$/.test(s)&&(i.splice(d,1),d--),C&&s===""&&(i.splice(d,1),d--)}function p(d){let u=0;for(;u<i.length&&/^\s*(#.*)?$/.test(i[u]);)u++;i.splice(u,0,d)}if(r!==null){let d=i[r].match(/^(\s*notify\s*=\s*\[)([^\]]*)\]/);if(d){let u=d[2].trim();if(!u.includes(JSON.stringify(t))){let v=u&&!u.endsWith(",")?", ":"";i[r]=`${d[1]}${u}${v}${JSON.stringify(t)}]`,o.logger.ok("Added notify hook to config")}}}else p(`notify = [${JSON.stringify(t)}]`),o.logger.ok("Enabled notify hook in config");let l=!1;if(a!==null){let d=a+1,u=!1;for(;d<i.length;d++){let w=i[d];if(/^\s*\[/.test(w))break;if(/^\s*notifications\s*=/.test(w)){i[d]="notifications = true",u=!0,l=!0;break}}u||(i.splice(a+1,0,"notifications = true"),l=!0)}l||p(`[tui]
43
- notifications = true`);let c=[];s="";for(let d=0;d<i.length;d++){let u=i[d],w=u.match(/^\s*\[([^\]]+)\]\s*$/);if(w){s=w[1],c.push(u);continue}/^\s*tui\.notifications\s*=/.test(u)||/^\s*notifications\s*=/.test(u)&&s!=="tui"||c.push(u)}await G.writeFile(e,c.join(`
44
- `),"utf8")}import U from"fs-extra";import*as N from"path";async function Rt(e){let t=N.join(e.rootDir,"sounds"),o=N.join(e.homeDir,".codex","sounds");await U.ensureDir(o);let n=e.options.notificationSound;if(n==="none"){let l=N.join(e.homeDir,".codex","notify.sh");if(await U.pathExists(l)){let c=await U.readFile(l,"utf8"),d=c.replace(/^DEFAULT_CODEX_SOUND=.*$/m,'DEFAULT_CODEX_SOUND=""');e.options.dryRun?e.logger.log(`[dry-run] patch ${l} DEFAULT_CODEX_SOUND -> empty`):d!==c&&await U.writeFile(l,d,"utf8")}e.logger.ok("Notification sound disabled");return}let i;if(n&&!N.isAbsolute(n)?i=N.join(t,n):n?i=n:e.options.mode==="recommended"&&(i=N.join(t,"noti_1.wav")),!i||!await U.pathExists(i)){e.logger.warn("No notification sound selected or file missing; skipping sound setup");return}let s=N.isAbsolute(i),r=i.startsWith(N.join(e.rootDir,"sounds")),a=!s||r?N.join(o,N.basename(i)):i;(!s||r)&&(e.options.dryRun?e.logger.log(`[dry-run] cp ${i} ${a}`):await U.copy(i,a));let p=N.join(e.homeDir,".codex","notify.sh");if(await U.pathExists(p)){let l=await U.readFile(p,"utf8"),c=`DEFAULT_CODEX_SOUND="${a}"`,d=l.replace(/^DEFAULT_CODEX_SOUND=.*$/m,c);d!==l&&(e.options.dryRun?e.logger.log(`[dry-run] patch ${p} DEFAULT_CODEX_SOUND -> ${a}`):await U.writeFile(p,d,"utf8"))}e.logger.ok("Notification sound configured")}import L from"fs-extra";import*as H from"path";async function Et(e){let t=H.join(e.homeDir,".codex","AGENTS.md"),o=e.options.globalAgents;if(o==="skip"){e.logger.info("Skipping global AGENTS.md creation");return}let n=H.join(e.rootDir,"templates","agent-templates","AGENTS-default.md");if(!await L.pathExists(n)){e.logger.warn(`Template not found at ${n}`);return}switch(o){case"create-default":{if(await L.pathExists(t)){e.logger.info("Global AGENTS.md already exists; leaving unchanged");return}await L.ensureDir(H.dirname(t)),e.options.dryRun?e.logger.log(`[dry-run] cp ${n} ${t}`):await L.copy(n,t),e.logger.ok(`Wrote ${t}`);break}case"overwrite-default":{if(await L.ensureDir(H.dirname(t)),await L.pathExists(t)){let i=O(t);e.options.dryRun?e.logger.log(`[dry-run] cp ${t} ${i}`):await L.copy(t,i),e.logger.info(`Backed up existing AGENTS.md to: ${i}`)}e.options.dryRun?e.logger.log(`[dry-run] cp ${n} ${t}`):await L.copy(n,t),e.logger.ok(`Wrote ${t}`);break}case"append-default":{if(await L.ensureDir(H.dirname(t)),await L.pathExists(t)){let s=O(t);e.options.dryRun?e.logger.log(`[dry-run] cp ${t} ${s}`):await L.copy(t,s),e.logger.info(`Backed up existing AGENTS.md to: ${s}`)}let i=await L.readFile(n,"utf8");e.options.dryRun?e.logger.log(`[dry-run] append template to ${t}`):await L.appendFile(t,`
43
+ `;p=!0}return{toml:l,changed:p}}import G from"fs-extra";import*as re from"path";async function Nt(e){let t=re.join(e.homeDir,".codex","notify.sh"),o=re.join(e.rootDir,"templates","notification.sh");await G.ensureDir(re.dirname(t));let n=e.options.notify;if(n==="no"){e.logger.info("Skipping notify hook installation");return}if(!await G.pathExists(o)){e.logger.warn(`Notification template missing at ${o}; skipping notify hook install`);return}if(await G.pathExists(t))if(n==="yes"){let s=O(t);e.options.dryRun?e.logger.log(`[dry-run] cp ${t} ${s}`):await G.copy(t,s),e.options.dryRun?e.logger.log(`[dry-run] cp ${o} ${t}`):(await G.copy(o,t),await G.chmod(t,493)),e.logger.ok("Updated notify hook (backup created)")}else!e.options.assumeYes&&!e.options.skipConfirmation&&e.logger.info("Keeping existing notify hook");else e.options.dryRun?e.logger.log(`[dry-run] cp ${o} ${t}`):(await G.copy(o,t),await G.chmod(t,493)),e.logger.ok("Installed notify hook to ~/.codex/notify.sh");let i=re.join(e.homeDir,".codex","config.toml");await G.pathExists(i)?await Fo(i,t,e):e.logger.warn(`Config not found at ${i}; run again after config is created`)}async function Fo(e,t,o){if(o.options.dryRun){o.logger.log("[dry-run] update config notify and tui.notifications");return}let i=(await G.readFile(e,"utf8")).split(/\r?\n/),s="",r=null,a=null;for(let d=0;d<i.length;d++){let u=i[d],h=u.match(/^\s*\[([^\]]+)\]\s*$/);if(h){s=h[1],s==="tui"&&(a=d);continue}let v=/^\s*notify\s*=\s*\[/.test(u),k=/^\s*tui\.notifications\s*=/.test(u),C=/^\s*notifications\s*=/.test(u);v&&(s===""?r===null&&(r=d):/^profiles\.[^.]+\.features$/.test(s)&&(i.splice(d,1),d--)),k&&/^profiles\.[^.]+\.features$/.test(s)&&(i.splice(d,1),d--),C&&s===""&&(i.splice(d,1),d--)}function p(d){let u=0;for(;u<i.length&&/^\s*(#.*)?$/.test(i[u]);)u++;i.splice(u,0,d)}if(r!==null){let d=i[r].match(/^(\s*notify\s*=\s*\[)([^\]]*)\]/);if(d){let u=d[2].trim();if(!u.includes(JSON.stringify(t))){let v=u&&!u.endsWith(",")?", ":"";i[r]=`${d[1]}${u}${v}${JSON.stringify(t)}]`,o.logger.ok("Added notify hook to config")}}}else p(`notify = [${JSON.stringify(t)}]`),o.logger.ok("Enabled notify hook in config");let l=!1;if(a!==null){let d=a+1,u=!1;for(;d<i.length;d++){let h=i[d];if(/^\s*\[/.test(h))break;if(/^\s*notifications\s*=/.test(h)){i[d]="notifications = true",u=!0,l=!0;break}}u||(i.splice(a+1,0,"notifications = true"),l=!0)}l||p(`[tui]
44
+ notifications = true`);let c=[];s="";for(let d=0;d<i.length;d++){let u=i[d],h=u.match(/^\s*\[([^\]]+)\]\s*$/);if(h){s=h[1],c.push(u);continue}/^\s*tui\.notifications\s*=/.test(u)||/^\s*notifications\s*=/.test(u)&&s!=="tui"||c.push(u)}await G.writeFile(e,c.join(`
45
+ `),"utf8")}import V from"fs-extra";import*as N from"path";async function Lt(e){let t=N.join(e.rootDir,"sounds"),o=N.join(e.homeDir,".codex","sounds");await V.ensureDir(o);let n=e.options.notificationSound;if(n==="none"){let l=N.join(e.homeDir,".codex","notify.sh");if(await V.pathExists(l)){let c=await V.readFile(l,"utf8"),d=c.replace(/^DEFAULT_CODEX_SOUND=.*$/m,'DEFAULT_CODEX_SOUND=""');e.options.dryRun?e.logger.log(`[dry-run] patch ${l} DEFAULT_CODEX_SOUND -> empty`):d!==c&&await V.writeFile(l,d,"utf8")}e.logger.ok("Notification sound disabled");return}let i;if(n&&!N.isAbsolute(n)?i=N.join(t,n):n?i=n:e.options.mode==="recommended"&&(i=N.join(t,"noti_1.wav")),!i||!await V.pathExists(i)){e.logger.warn("No notification sound selected or file missing; skipping sound setup");return}let s=N.isAbsolute(i),r=i.startsWith(N.join(e.rootDir,"sounds")),a=!s||r?N.join(o,N.basename(i)):i;(!s||r)&&(e.options.dryRun?e.logger.log(`[dry-run] cp ${i} ${a}`):await V.copy(i,a));let p=N.join(e.homeDir,".codex","notify.sh");if(await V.pathExists(p)){let l=await V.readFile(p,"utf8"),c=`DEFAULT_CODEX_SOUND="${a}"`,d=l.replace(/^DEFAULT_CODEX_SOUND=.*$/m,c);d!==l&&(e.options.dryRun?e.logger.log(`[dry-run] patch ${p} DEFAULT_CODEX_SOUND -> ${a}`):await V.writeFile(p,d,"utf8"))}e.logger.ok("Notification sound configured")}import L from"fs-extra";import*as Y from"path";async function Dt(e){let t=Y.join(e.homeDir,".codex","AGENTS.md"),o=e.options.globalAgents;if(o==="skip"){e.logger.info("Skipping global AGENTS.md creation");return}let n=Y.join(e.rootDir,"templates","agent-templates","AGENTS-default.md");if(!await L.pathExists(n)){e.logger.warn(`Template not found at ${n}`);return}switch(o){case"create-default":{if(await L.pathExists(t)){e.logger.info("Global AGENTS.md already exists; leaving unchanged");return}await L.ensureDir(Y.dirname(t)),e.options.dryRun?e.logger.log(`[dry-run] cp ${n} ${t}`):await L.copy(n,t),e.logger.ok(`Wrote ${t}`);break}case"overwrite-default":{if(await L.ensureDir(Y.dirname(t)),await L.pathExists(t)){let i=O(t);e.options.dryRun?e.logger.log(`[dry-run] cp ${t} ${i}`):await L.copy(t,i),e.logger.info(`Backed up existing AGENTS.md to: ${i}`)}e.options.dryRun?e.logger.log(`[dry-run] cp ${n} ${t}`):await L.copy(n,t),e.logger.ok(`Wrote ${t}`);break}case"append-default":{if(await L.ensureDir(Y.dirname(t)),await L.pathExists(t)){let s=O(t);e.options.dryRun?e.logger.log(`[dry-run] cp ${t} ${s}`):await L.copy(t,s),e.logger.info(`Backed up existing AGENTS.md to: ${s}`)}let i=await L.readFile(n,"utf8");e.options.dryRun?e.logger.log(`[dry-run] append template to ${t}`):await L.appendFile(t,`
45
46
  ---
46
47
 
47
- ${i}`,"utf8"),e.logger.ok(`Appended template to ${t}`);break}default:e.options.skipConfirmation&&e.logger.info("Skipping global AGENTS.md creation (non-interactive mode)");break}}async function Nt(e){if(e.options.noVscode)return;let t=e.options.vscodeId;if(!t){e.logger.info("VS Code extension id not provided. Use: --vscode <publisher.extension>");return}if(!await $("code")){e.logger.warn("'code' (VS Code) not in PATH; skipping extension install");return}if(e.options.dryRun){e.logger.log(`[dry-run] code --install-extension ${t}`);return}e.logger.info(`Installing VS Code extension: ${t}`),await I("code",["--install-extension",t,"--force"],{dryRun:!1,logger:e.logger}),e.logger.ok(`VS Code extension '${t}' installed (or already present)`)}import ue from"fs-extra";import*as me from"path";async function Lt(e){let t=e.options.agentsMd;if(!t)return;let o=t;(await ue.stat(o).catch(()=>null))?.isDirectory()&&(o=me.join(o,"AGENTS.md"));let n=me.join(e.rootDir,"templates","agent-templates","AGENTS-default.md");if(await ue.pathExists(o)){e.logger.warn(`${o} already exists`);let i=O(o);e.options.dryRun?e.logger.log(`[dry-run] cp ${o} ${i}`):await ue.copy(o,i),e.logger.info(`Backed up existing AGENTS.md to: ${i}`)}e.logger.info(`Writing starter AGENTS.md to: ${o}`),e.options.dryRun?e.logger.log(`[dry-run] write AGENTS.md to ${o}`):(await ue.ensureDir(me.dirname(o)),await ue.copy(n,o),e.logger.ok("Wrote AGENTS.md"))}import ge from"fs-extra";import*as Qe from"path";import*as Le from"@clack/prompts";import Xe from"fs-extra";import*as Ee from"path";async function Ne(e){let t=Ee.join(e,"templates","skills"),o=await Xe.readdir(t,{withFileTypes:!0}).catch(()=>[]),n=[];for(let i of o){if(!i.isDirectory())continue;let s=i.name,r=Ee.join(t,s),a=Ee.join(r,"SKILL.md");if(!await Xe.pathExists(a))continue;let p=await Xe.readFile(a,"utf8").catch(()=>""),l=_o(p);!l?.name||!l?.description||n.push({id:s,name:l.name,description:l.description,srcDir:r})}return n.sort((i,s)=>i.id.localeCompare(s.id)),n}function _o(e){let t=e.split(/\r?\n/);if(t.length<3||t[0].trim()!=="---")return null;let o=[],n=-1;for(let s=1;s<t.length;s++){if(t[s].trim()==="---"){n=s;break}o.push(t[s])}if(n===-1)return null;let i={};for(let s of o){let r=s.trim();if(!r||r.startsWith("#"))continue;let a=r.indexOf(":");if(a===-1)continue;let p=r.slice(0,a).trim();if(!p)continue;let l=r.slice(a+1).trim();l&&(l=Go(Oo(l)),i[p]=l)}return{name:i.name,description:i.description}}function Oo(e){let t=e.trim();if(!t||t.startsWith('"')||t.startsWith("'"))return t;let o=t.indexOf(" #");return o===-1?t:t.slice(0,o).trim()}function Go(e){let t=e.trim();return t.length>=2&&(t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'"))?t.slice(1,-1):t}async function De(e){let t=e.options.skills;if(t==="skip"){e.logger.info("Skipping bundled skills installation");return}let o=await Ne(e.rootDir);if(o.length===0){e.logger.info("No bundled skills found; skipping");return}let n=(()=>{if(t==="all")return o;let r=new Set((e.options.skillsSelected||[]).map(a=>a.trim()).filter(Boolean));return o.filter(a=>r.has(a.id)||r.has(a.name))})();if(n.length===0){e.logger.info("No skills selected; skipping");return}let i=Qe.join(e.homeDir,".codex","skills"),s=process.stdout.isTTY&&!e.options.dryRun&&!e.options.skipConfirmation&&!e.options.assumeYes;e.options.dryRun?e.logger.log(`[dry-run] mkdir -p ${i}`):await ge.ensureDir(i),e.logger.info(`Installing ${n.length} skill(s) into: ${i}`);for(let r of n){let a=Qe.join(i,r.id);if(await ge.pathExists(a)){if(s){let c=await Le.select({message:`Skill "${r.id}" already exists. Overwrite? (backup created)`,options:[{label:"Overwrite",value:"overwrite"},{label:"Skip",value:"skip"}],initialValue:"overwrite"});if(Le.isCancel(c)||c==="skip"){e.logger.info(`Skipping existing skill: ${r.id}`);continue}}let l=O(a);e.options.dryRun?(e.logger.log(`[dry-run] cp -R ${a} ${l}`),e.logger.log(`[dry-run] rm -rf ${a}`)):(await ge.copy(a,l),await ge.remove(a)),e.logger.info(`Backed up existing skill ${r.id} to: ${l}`)}e.options.dryRun?e.logger.log(`[dry-run] cp -R ${r.srcDir} ${a}`):await ge.copy(r.srcDir,a),e.logger.ok(`Installed skill: ${r.id}`)}}var jt="codex-1up";async function Ot(e,t){let o=_t.homedir(),n=Ze.join(o,`.${jt}`);await Dt.ensureDir(n);try{await Dt.chmod(n,448)}catch{}let i=new Date().toISOString().replace(/[:.]/g,"-").slice(0,-5),s=Ze.join(n,`install-${i}.log`),r=Se(s);r.info(`==> ${jt} installer`),r.info(`Log: ${s}`);let a={cwd:process.cwd(),homeDir:o,rootDir:t,logDir:n,logFile:s,options:e,logger:r};try{await vt(a),await St(a),await Pe(a);let l=await $("codex")||a.options.installCodexCli==="yes";l||r.warn("Codex CLI not found and codex install was skipped; skipping config/notify setup until codex is installed."),l&&(await Pt(a),await At(a),await Rt(a),await Et(a)),await De(a),await Nt(a),await Lt(a),r.ok("All done. Open a new shell or 'source' your rc file to load aliases."),r.info("Next steps:"),r.info(" 1) codex # sign in; then ask it to plan a refactor"),r.info(" 2) ./bin/codex-1up agents --path $PWD # write a starter AGENTS.md to your repo"),r.info(" 3) Review ~/.codex/config.toml (see: https://github.com/openai/codex/blob/main/docs/config.md)")}catch(p){throw r.err(`Installation failed: ${p}`),p}}import Bo from"os";import*as tt from"path";import{promises as Gt}from"fs";import{accessSync as Mo}from"fs";import{dirname as Fo,resolve as et}from"path";import{fileURLToPath as Wo}from"url";function T(e=import.meta.url){let t=Fo(Wo(e)),o=t;for(let n=0;n<6;n++){try{return Mo(et(o,"templates","codex-config.toml")),o}catch{}o=et(o,"..")}return et(t,"..")}function qo(){return{profile:"skip",profileScope:"selected",profileMode:"add",setDefaultProfile:!1,profilesSelected:void 0,installTools:"skip",toolsSelected:void 0,installCodexCli:"no",notify:"no",globalAgents:"skip",notificationSound:void 0,skills:"skip",skillsSelected:void 0,mode:"manual",installNode:"skip",shell:"auto",vscodeId:void 0,noVscode:!0,agentsMd:void 0,dryRun:!1,assumeYes:!1,skipConfirmation:!1}}async function re(e={}){let t=Bo.homedir(),o=tt.join(t,".codex-1up");await Gt.mkdir(o,{recursive:!0});try{await Gt.chmod(o,448)}catch{}let n=new Date().toISOString().replace(/[:.]/g,"-").slice(0,-5),i=tt.join(o,`command-${n}.log`),s=Se(i),r=qo();return{cwd:process.cwd(),homeDir:t,rootDir:T(),logDir:o,logFile:i,options:{...r,...e},logger:s}}function J(){return ne()}function X(e){return xt(e)}function Mt(){return J().map(e=>e.id)}async function we(){let e=ne(),t=[];for(let o of e){let n=await nt(o.bins);t.push({id:o.id,installed:n})}return t}async function ot(e,t={}){let o=e==="all",n={installTools:o?"all":"select",toolsSelected:o?void 0:e,dryRun:!!t.dryRun},i=await re(n);await Pe(i)}async function nt(e){for(let t of e)if(await $(t))return!0;return!1}async function it(e,t){let o=t||T();await Ot(e,o)}async function st(){let e=Uo.homedir(),t=zo(e,".codex","config.toml"),o,n=[];try{let l=await Vo.readFile(t,"utf8"),c=Ft.parse(l);o=typeof c.profile=="string"?c.profile:void 0;let d=c.profiles&&typeof c.profiles=="object"?c.profiles:{};n=Object.keys(d)}catch(l){}let i=J(),s=[{id:"codex",bins:["codex"]},...i],a=(await Promise.all(s.map(async l=>{let c=await nt(l.bins);return[l.id,c]}))).filter(([,l])=>l).map(([l])=>l),p=[];p.push(""),p.push("codex-1up: Installation summary"),p.push("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),p.push(`Config: ${t}${o?` (active profile: ${o})`:""}`),n.length&&p.push(`Profiles: ${n.join(", ")}`),p.push(`Tools detected: ${a.join(", ")||"none"}`),p.push(""),p.push("Usage:"),p.push(" - Switch profile for a session: codex --profile <name>"),p.push(" - List available profiles: codex-1up config profiles"),p.push(" - Persist active profile: codex-1up config set-profile <name>"),p.push(" - Write AGENTS.md to a repo: codex-1up agents --path ."),p.push(""),process.stdout.write(p.join(`
48
+ ${i}`,"utf8"),e.logger.ok(`Appended template to ${t}`);break}default:e.options.skipConfirmation&&e.logger.info("Skipping global AGENTS.md creation (non-interactive mode)");break}}async function jt(e){if(e.options.noVscode)return;let t=e.options.vscodeId;if(!t){e.logger.info("VS Code extension id not provided. Use: --vscode <publisher.extension>");return}if(!await S("code")){e.logger.warn("'code' (VS Code) not in PATH; skipping extension install");return}if(e.options.dryRun){e.logger.log(`[dry-run] code --install-extension ${t}`);return}e.logger.info(`Installing VS Code extension: ${t}`),await I("code",["--install-extension",t,"--force"],{dryRun:!1,logger:e.logger}),e.logger.ok(`VS Code extension '${t}' installed (or already present)`)}import ue from"fs-extra";import*as me from"path";async function _t(e){let t=e.options.agentsMd;if(!t)return;let o=t;(await ue.stat(o).catch(()=>null))?.isDirectory()&&(o=me.join(o,"AGENTS.md"));let n=me.join(e.rootDir,"templates","agent-templates","AGENTS-default.md");if(await ue.pathExists(o)){e.logger.warn(`${o} already exists`);let i=O(o);e.options.dryRun?e.logger.log(`[dry-run] cp ${o} ${i}`):await ue.copy(o,i),e.logger.info(`Backed up existing AGENTS.md to: ${i}`)}e.logger.info(`Writing starter AGENTS.md to: ${o}`),e.options.dryRun?e.logger.log(`[dry-run] write AGENTS.md to ${o}`):(await ue.ensureDir(me.dirname(o)),await ue.copy(n,o),e.logger.ok("Wrote AGENTS.md"))}import ge from"fs-extra";import*as et from"path";import*as De from"@clack/prompts";import Ze from"fs-extra";import*as Ne from"path";async function Le(e){let t=Ne.join(e,"templates","skills"),o=await Ze.readdir(t,{withFileTypes:!0}).catch(()=>[]),n=[];for(let i of o){if(!i.isDirectory())continue;let s=i.name,r=Ne.join(t,s),a=Ne.join(r,"SKILL.md");if(!await Ze.pathExists(a))continue;let p=await Ze.readFile(a,"utf8").catch(()=>""),l=Wo(p);!l?.name||!l?.description||n.push({id:s,name:l.name,description:l.description,srcDir:r})}return n.sort((i,s)=>i.id.localeCompare(s.id)),n}function Wo(e){let t=e.split(/\r?\n/);if(t.length<3||t[0].trim()!=="---")return null;let o=[],n=-1;for(let s=1;s<t.length;s++){if(t[s].trim()==="---"){n=s;break}o.push(t[s])}if(n===-1)return null;let i={};for(let s of o){let r=s.trim();if(!r||r.startsWith("#"))continue;let a=r.indexOf(":");if(a===-1)continue;let p=r.slice(0,a).trim();if(!p)continue;let l=r.slice(a+1).trim();l&&(l=Uo(Bo(l)),i[p]=l)}return{name:i.name,description:i.description}}function Bo(e){let t=e.trim();if(!t||t.startsWith('"')||t.startsWith("'"))return t;let o=t.indexOf(" #");return o===-1?t:t.slice(0,o).trim()}function Uo(e){let t=e.trim();return t.length>=2&&(t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'"))?t.slice(1,-1):t}async function je(e){let t=e.options.skills;if(t==="skip"){e.logger.info("Skipping bundled skills installation");return}let o=await Le(e.rootDir);if(o.length===0){e.logger.info("No bundled skills found; skipping");return}let n=(()=>{if(t==="all")return o;let r=new Set((e.options.skillsSelected||[]).map(a=>a.trim()).filter(Boolean));return o.filter(a=>r.has(a.id)||r.has(a.name))})();if(n.length===0){e.logger.info("No skills selected; skipping");return}let i=et.join(e.homeDir,".codex","skills"),s=process.stdout.isTTY&&!e.options.dryRun&&!e.options.skipConfirmation&&!e.options.assumeYes;e.options.dryRun?e.logger.log(`[dry-run] mkdir -p ${i}`):await ge.ensureDir(i),e.logger.info(`Installing ${n.length} skill(s) into: ${i}`);for(let r of n){let a=et.join(i,r.id);if(await ge.pathExists(a)){if(s){let c=await De.select({message:`Skill "${r.id}" already exists. Overwrite? (backup created)`,options:[{label:"Overwrite",value:"overwrite"},{label:"Skip",value:"skip"}],initialValue:"overwrite"});if(De.isCancel(c)||c==="skip"){e.logger.info(`Skipping existing skill: ${r.id}`);continue}}let l=O(a);e.options.dryRun?(e.logger.log(`[dry-run] cp -R ${a} ${l}`),e.logger.log(`[dry-run] rm -rf ${a}`)):(await ge.copy(a,l),await ge.remove(a)),e.logger.info(`Backed up existing skill ${r.id} to: ${l}`)}e.options.dryRun?e.logger.log(`[dry-run] cp -R ${r.srcDir} ${a}`):await ge.copy(r.srcDir,a),e.logger.ok(`Installed skill: ${r.id}`)}}var Gt="codex-1up";async function Ft(e,t){let o=Mt.homedir(),n=tt.join(o,`.${Gt}`);await Ot.ensureDir(n);try{await Ot.chmod(n,448)}catch{}let i=new Date().toISOString().replace(/[:.]/g,"-").slice(0,-5),s=tt.join(n,`install-${i}.log`),r=Se(s);r.info(`==> ${Gt} installer`),r.info(`Log: ${s}`);let a={cwd:process.cwd(),homeDir:o,rootDir:t,logDir:n,logFile:s,options:e,logger:r};try{await St(a),await xt(a),await Pe(a);let l=await S("codex")||a.options.installCodexCli==="yes";l||r.warn("Codex CLI not found and codex install was skipped; skipping config/notify setup until codex is installed."),l&&(await Et(a),await Nt(a),await Lt(a),await Dt(a)),await je(a),await jt(a),await _t(a),r.ok("All done. Open a new shell or 'source' your rc file to load aliases."),r.info("Next steps:"),r.info(" 1) codex # sign in; then ask it to plan a refactor"),r.info(" 2) ./bin/codex-1up agents --path $PWD # write a starter AGENTS.md to your repo"),r.info(" 3) Review ~/.codex/config.toml (see: https://github.com/openai/codex/blob/main/docs/config.md)")}catch(p){throw r.err(`Installation failed: ${p}`),p}}import Ko from"os";import*as nt from"path";import{promises as Wt}from"fs";import{accessSync as Vo}from"fs";import{dirname as qo,resolve as ot}from"path";import{fileURLToPath as zo}from"url";function T(e=import.meta.url){let t=qo(zo(e)),o=t;for(let n=0;n<6;n++){try{return Vo(ot(o,"templates","codex-config.toml")),o}catch{}o=ot(o,"..")}return ot(t,"..")}function Ho(){return{profile:"skip",profileScope:"selected",profileMode:"add",setDefaultProfile:!1,profilesSelected:void 0,installTools:"skip",toolsSelected:void 0,installCodexCli:"no",notify:"no",globalAgents:"skip",notificationSound:void 0,skills:"skip",skillsSelected:void 0,mode:"manual",installNode:"skip",shell:"auto",vscodeId:void 0,noVscode:!0,agentsMd:void 0,dryRun:!1,assumeYes:!1,skipConfirmation:!1}}async function ae(e={}){let t=Ko.homedir(),o=nt.join(t,".codex-1up");await Wt.mkdir(o,{recursive:!0});try{await Wt.chmod(o,448)}catch{}let n=new Date().toISOString().replace(/[:.]/g,"-").slice(0,-5),i=nt.join(o,`command-${n}.log`),s=Se(i),r=Ho();return{cwd:process.cwd(),homeDir:t,rootDir:T(),logDir:o,logFile:i,options:{...r,...e},logger:s}}function J(){return ne()}function X(e){return Tt(e)}function Bt(){return J().map(e=>e.id)}async function he(){let e=ne(),t=[];for(let o of e){let n=await st(o.bins);t.push({id:o.id,installed:n})}return t}async function it(e,t={}){let o=e==="all",n={installTools:o?"all":"select",toolsSelected:o?void 0:e,dryRun:!!t.dryRun},i=await ae(n);await Pe(i)}async function st(e){for(let t of e)if(await S(t))return!0;return!1}async function rt(e,t){let o=t||T();await Ft(e,o)}async function at(){let e=Yo.homedir(),t=Jo(e,".codex","config.toml"),o,n=[];try{let l=await Xo.readFile(t,"utf8"),c=Ut.parse(l);o=typeof c.profile=="string"?c.profile:void 0;let d=c.profiles&&typeof c.profiles=="object"?c.profiles:{};n=Object.keys(d)}catch(l){}let i=J(),s=[{id:"codex",bins:["codex"]},...i],a=(await Promise.all(s.map(async l=>{let c=await st(l.bins);return[l.id,c]}))).filter(([,l])=>l).map(([l])=>l),p=[];p.push(""),p.push("codex-1up: Installation summary"),p.push("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),p.push(`Config: ${t}${o?` (active profile: ${o})`:""}`),n.length&&p.push(`Profiles: ${n.join(", ")}`),p.push(`Tools detected: ${a.join(", ")||"none"}`),p.push(""),p.push("Usage:"),p.push(" - Switch profile for a session: codex --profile <name>"),p.push(" - List available profiles: codex-1up config profiles"),p.push(" - Persist active profile: codex-1up config set-profile <name>"),p.push(" - Write AGENTS.md to a repo: codex-1up agents --path ."),p.push(""),process.stdout.write(p.join(`
48
49
  `)+`
49
- `)}import Ko from"fs-extra";import Yo from"os";import Wt from"path";async function rt(e){return Ne(e)}var at=rt;async function Bt(){let e=Wt.join(Yo.homedir(),".codex","skills");return(await Ko.readdir(e,{withFileTypes:!0}).catch(()=>[])).filter(o=>o.isDirectory()).map(o=>({id:o.name,path:Wt.join(e,o.name)})).sort((o,n)=>o.id.localeCompare(n.id))}async function je(e,t,o={}){let n=await re({skills:e,skillsSelected:t,dryRun:!!o.dryRun});await De(n)}import{existsSync as Ho,readFileSync as Jo}from"fs";import{dirname as Ut,join as qt}from"path";import{fileURLToPath as Xo}from"url";var Qo=Ut(Xo(import.meta.url)),zt=(e,t=!1)=>{try{return JSON.parse(Jo(e,"utf-8"))}catch(o){if(t)return{};throw o}},Zo=e=>!!(e.name==="codex-1up"||e.bin==="codex-1up"||e.bin&&typeof e.bin=="object"&&"codex-1up"in e.bin),en=e=>{let t=e,o=null;for(;;){let n=qt(t,"package.json");if(Ho(n)){o||(o=n);let s=zt(n,!0);if(Zo(s))return n}let i=Ut(t);if(i===t)break;t=i}return o??qt(e,"package.json")},tn=en(Qo),lt=zt(tn),_e=lt.name||"codex-1up",ae=lt.version||"0.0.0",Vt=lt.description||"Codex CLI helper";import{promises as dt}from"fs";import{resolve as pt}from"path";import*as f from"@clack/prompts";import{$ as he,which as ye}from"zx";import*as Oe from"@clack/prompts";async function on(){let e=ae,t=await nn(_e),o=!!(t&&sn(t,e));return{current:e,latest:t,updateAvailable:o}}async function Ge(e){let t=e.logger,o=await on();if(!o.latest)return t?.warn("Unable to check for codex-1up updates right now."),"error";if(!o.updateAvailable)return t?.ok(`codex-1up is up-to-date (v${o.current}).`),"up-to-date";let n=e.interactive&&!e.assumeYes&&!e.skipConfirmation,i=e.assumeYes||e.skipConfirmation;if(n){let p=await Oe.confirm({message:`New codex-1up version available (v${o.latest}). Update now?`,initialValue:!0});if(Oe.isCancel(p))return t?.info("Update canceled."),"skipped";i=!!p}if(!i)return t?.info("Skipping codex-1up update."),"skipped";let s=await Te({logger:t,interactive:e.interactive&&!e.assumeYes&&!e.skipConfirmation});if(s==="none")return t?.warn("No supported Node package manager found; cannot update codex-1up."),"error";let r=o.latest?`${_e}@${o.latest}`:_e,a=!!e.dryRun;return s==="pnpm"?(t?.info("Updating codex-1up via pnpm"),await I("pnpm",["add","-g",r],{dryRun:a,logger:t})):(t?.info("Updating codex-1up via npm"),await I("npm",["install","-g",r],{dryRun:a,logger:t})),t?.ok(`codex-1up updated to v${o.latest}`),"updated"}async function nn(e){try{let t=await fetch(`https://registry.npmjs.org/${encodeURIComponent(e)}/latest`);return t.ok?(await t.json()).version:void 0}catch{return}}function sn(e,t){let o=Kt(e),n=Kt(t);if(!o||!n)return e!==t;for(let i=0;i<3;i++){if(o[i]>n[i])return!0;if(o[i]<n[i])return!1}return!1}function Kt(e){let t=e.match(/(\d+)\.(\d+)\.(\d+)/);return t?[Number(t[1]),Number(t[2]),Number(t[3])]:null}async function Yt(e){return xe(e)}var rn=["balanced","safe","yolo"];async function Ht(e){let{repoRoot:t,isUnixLike:o,globalAgentsExists:n,currentProfile:i,seededProfile:s,bundledSkills:r,availableTools:a,cliArgs:p}=e,{profileChoice:l,profileMode:c,profileScope:d,setDefaultProfile:u,profilesSelected:w,installTools:v,toolsSelected:k,installCodexCli:C,notifyAction:R,globalAgentsAction:D,notificationSound:z,skillsMode:K,skillsSelected:Q}=e.selections;await Ge({interactive:!0,assumeYes:!1,skipConfirmation:!1,dryRun:!1,logger:{log:m=>f.log.info(m),info:m=>f.log.info(m),ok:m=>f.log.success(m),warn:m=>f.log.warn(m),err:m=>f.log.warn(m)}});let x=await Yt();if(x.found){let m=x.version?`v${x.version}`:"unknown version";x.latest?x.updateAvailable?f.log.info(`Codex CLI detected (${m}). Newer version available: v${x.latest}.`):f.log.info(`Codex CLI detected (${m}). Latest: v${x.latest}.`):f.log.info(`Codex CLI detected (${m}).`)}else f.log.info("Codex CLI not detected.");if(C==="no")x.found?x.updateAvailable&&f.log.info("Codex CLI update disabled by --codex-cli no."):f.log.info("Codex CLI install disabled by --codex-cli no.");else if(C==="auto")if(x.found){if(x.updateAvailable){let m=await f.confirm({message:`Codex CLI ${x.version} found; latest is ${x.latest}. Update now?`,initialValue:!0});if(f.isCancel(m))return A();C=m?"yes":"no"}}else{let m=await f.confirm({message:"Codex CLI not found. Install now?",initialValue:!0});if(f.isCancel(m))return A();C=m?"yes":"no"}if(o&&!p.toolsArg){let m=await we(),h=m.filter(y=>y.installed).map(y=>y.id),b=m.filter(y=>!y.installed).map(y=>y.id);for(f.log.info(`Tools detected: ${h.join(", ")||"none"}`),b.length&&f.log.info(`Missing tools: ${b.join(", ")}`);;){let y=await f.select({message:"Install/update developer tools",options:[{label:"Install/Update all",value:"all"},{label:"Select",value:"select"},{label:"Skip",value:"skip"}],initialValue:"all"});if(f.isCancel(y))return A();if(v=y,y!=="select"){k=void 0;break}f.log.info("Tip: press Esc to go back.");let E=await Me({message:"Select tools to install",options:a.map(g=>{let S=h.includes(g.id);return{label:g.id,value:g.id,hint:S?"installed":"missing"}})});if(E==="back")continue;let j=Array.isArray(E)?E.map(g=>String(g).trim().toLowerCase()).filter(X):[];j.length===0?(v="skip",k=void 0):k=Array.from(new Set(j));break}}else!o&&!p.toolsArg&&(v="skip",k=void 0);let Y=[{label:"Balanced (recommended)",value:"balanced",hint:"on-request approvals \xB7 workspace-write \xB7 web search on"},{label:"Safe",value:"safe",hint:"on-failure approvals \xB7 read-only \xB7 web search off"},{label:"YOLO",value:"yolo",hint:"never approvals \xB7 danger-full-access \xB7 gpt-5.2-codex"}];if(!p.profileScope)for(;;){let m=await f.select({message:"Install all profiles (balanced, safe, yolo)?",options:[{label:"Yes \u2014 install/update all profiles",value:"all"},{label:"Choose profiles\u2026",value:"selected"},{label:"No \u2014 don't install any profiles",value:"skip"}],initialValue:"all"});if(f.isCancel(m))return A();if(m==="skip"){d="selected",w=[],l="skip";break}if(m!=="selected"){d=m;break}f.log.info("Tip: press Esc to go back.");let h=await Me({message:"Select profiles to install",options:Y.map(E=>({label:E.label,value:E.value,hint:E.hint}))});if(h==="back")continue;let b=Array.isArray(h)?h.map(E=>String(E).trim().toLowerCase()).filter(be):[],y=Array.from(new Set(b));d="selected",y.length===0?(w=[],l="skip"):w=y;break}if(d!=="all"&&!p.profileChoice&&f.log.info(["Profiles:"," - Balanced: on-request approvals, workspace-write sandbox, web search on."," - Safe: on-failure approvals, read-only sandbox, web search off."," - YOLO: never approvals, danger-full-access, gpt-5.2-codex, high reasoning."].join(`
50
- `)),d==="single"){if(!p.profileChoice){let m=await f.select({message:"Choose a Codex profile to install",options:[...Y,{label:"Skip (no profile changes)",value:"skip"}],initialValue:pn(i)});if(f.isCancel(m))return A();l=m}}else if(d==="selected"){if(w===void 0){f.log.info("Tip: press Esc to go back.");let m=await Me({message:"Select profiles to install",options:Y.map(h=>({label:h.label,value:h.value,hint:h.hint}))});if(m==="back")w=[],l="skip";else{let h=Array.isArray(m)?m.map(y=>String(y).trim().toLowerCase()).filter(be):[],b=Array.from(new Set(h));b.length===0?(w=[],l="skip"):w=b}}(w||[]).length>0&&be(l)&&!w.includes(l)&&(l=w[0])}else d==="all"&&l==="skip"&&(l=s);let P=d==="all"?[...rn]:d==="selected"?w||[]:l==="skip"?[]:[l];if(P.length>0&&!p.profileMode){let m=await f.select({message:d==="all"?"How should we write all profiles?":P.length>1?"How should we write selected profiles?":`How should we write profiles.${P[0]}?`,options:[{label:"Overwrite (use codex-1up defaults)",value:"overwrite"},{label:"Add Merge (add missing, keep your default settings)",value:"add"}],initialValue:c});if(f.isCancel(m))return A();c=m}if(P.length===0)u=!1;else if(P.length===1){let m=P[0],h=await f.confirm({message:`Wrote profiles.${m} to ~/.codex/config.toml (mode: ${c}). Set this as the default profile?`,initialValue:!0});if(f.isCancel(h))return A();u=!!h,u&&(l=m)}else{let m=[{label:"Keep current default (skip)",value:"skip"},...P.map(y=>({label:y==="balanced"?"Balanced":y==="safe"?"Safe":"YOLO",value:y}))],h=be(l)&&P.includes(l)?l:P[0],b=await f.select({message:"Select a default profile (optional)",options:m,initialValue:h});if(f.isCancel(b))return A();b==="skip"?u=!1:(u=!0,l=b)}if(!p.soundArg){let y=function(){return[{label:"Skip (leave current setup)",value:"skip"},{label:"None (disable sounds)",value:"none"},...h.map(g=>({label:g,value:g})),{label:"Custom path\u2026",value:"custom"}]};var Z=y;let m=pt(t,"sounds"),h=[];try{h=(await dt.readdir(m)).filter(g=>/\.(wav|mp3|ogg)$/i.test(g)).sort()}catch(g){}R="yes";let b=h.includes("noti_1.wav")?"noti_1.wav":h[0]||"none";async function E(g){let S=await f.text({message:"Enter absolute path to a .wav file",placeholder:g||"/absolute/path/to/sound.wav",validate(_){if(!_)return"Path required";if(!_.startsWith("/"))return"Use an absolute path";if(!/(\.wav|\.mp3|\.ogg)$/i.test(_))return"Supported: .wav, .mp3, .ogg"}});if(f.isCancel(S))return null;try{await dt.access(String(S))}catch{return f.log.warn("File not found. Try again."),await E(String(S))}return String(S)}let j=await f.select({message:"Notification sound",options:y(),initialValue:b});if(f.isCancel(j))return A();if(j==="skip")R="no",z=void 0;else if(j==="custom"){let g=await E();if(g===null)return A();b=g}else b=j;if(j!=="skip"){for(;;){let g=await f.select({message:`Selected: ${b}. What next?`,options:[{label:"Preview \u25B6 (press p then Enter)",value:"preview"},{label:"Use this",value:"use"},{label:"Choose another\u2026",value:"change"}],initialValue:"use"});if(f.isCancel(g))return A();if(g==="use")break;if(g==="change"){let S=await f.select({message:"Notification sound",options:y(),initialValue:b});if(f.isCancel(S))return A();if(S==="custom"){let _=await E();if(_===null)return A();b=_}else if(S==="skip"){R="no",z=void 0;break}else b=S;continue}try{let S=b==="none"?"none":b.startsWith("/")?b:pt(t,"sounds",b);await an(S)}catch(S){f.log.warn(String(S))}}z===void 0&&(z=b)}}let W=["Global AGENTS.md is shared instructions Codex can reference in any repo.","We add a short starter guide (fd/ast-grep/jq/yq patterns, deterministic selects).","Backups will be created.","You can remove it later from ~/.codex/AGENTS.md."].join(`
51
- `),B=pt(t,"templates","agent-templates","AGENTS-default.md"),M=await(async m=>{for(;;){f.log.info(W);let h=await f.select({message:"Global ~/.codex/AGENTS.md (optional)",options:m?[{label:"Add to your existing AGENTS.md (keeps your content, adds ours; backup created)",value:"append-default"},{label:"Overwrite existing (replace with starter; backup created)",value:"overwrite-default"},{label:"Preview starter AGENTS.md",value:"preview"},{label:"Skip \u2014 leave as-is (you can run codex-1up agents later)",value:"skip"}]:[{label:"Create starter AGENTS.md (recommended; helps give Codex repo context everywhere)",value:"create-default"},{label:"Preview starter AGENTS.md",value:"preview"},{label:"Skip for now (you can add later with codex-1up agents --global)",value:"skip"}],initialValue:m?"append-default":"create-default"});if(f.isCancel(h))return null;if(h==="preview"){await ln(B);continue}return h}})(n);if(!M)return A();if(D=M,!p.skillsArg&&r.length)for(f.log.info(["Agent Skills are optional, portable skill folders (SKILL.md + optional scripts/references).","codex-1up can install bundled skills into ~/.codex/skills so your agent can reference them.",`Bundled skills: ${r.map(m=>m.id).join(", ")}`].join(`
52
- `));;){let m=await f.select({message:"Install bundled Agent Skills (optional)",options:[{label:"None (do not install skills)",value:"skip"},{label:"Select skills\u2026",value:"select"},{label:"All (install every bundled skill)",value:"all"}],initialValue:"skip"});if(f.isCancel(m))return A();if(K=m,m!=="select")break;f.log.info("Tip: press Esc to go back.");let h=await Me({message:"Select skills to install",options:r.map(y=>({label:y.id,value:y.id,hint:y.description.length>120?`${y.description.slice(0,117)}\u2026`:y.description}))});if(h==="back")continue;let b=Array.isArray(h)?h.map(y=>String(y).trim()).filter(Boolean):[];b.length===0?(K="skip",Q=void 0):Q=b;break}return{selections:{profileChoice:l,profileMode:c,profileScope:d,setDefaultProfile:u,profilesSelected:w,installTools:v,toolsSelected:k,installCodexCli:C,notifyAction:R,globalAgentsAction:D,notificationSound:z,skillsMode:K,skillsSelected:Q}}}async function an(e){if(e.endsWith("/none")||e==="none")return;let t=[async o=>{await ye("afplay"),await he`afplay ${o}`},async o=>{await ye("paplay"),await he`paplay ${o}`},async o=>{await ye("aplay"),await he`aplay ${o}`},async o=>{await ye("mpg123"),await he`mpg123 -q ${o}`},async o=>{await ye("ffplay"),await he`ffplay -nodisp -autoexit -loglevel quiet ${o}`}];for(let o of t)try{await o(e);return}catch{}throw new Error("No audio player found (afplay/paplay/aplay/mpg123/ffplay)")}async function Me(e){let o=await f.multiselect({message:e.message,options:e.options});return f.isCancel(o)?"back":Array.isArray(o)?o.map(i=>String(i)):[]}async function ln(e){let o="";try{o=await dt.readFile(e,"utf8")}catch{f.log.warn(`Starter AGENTS template not found at ${e}`);return}let n=o.split(/\r?\n/);if(n.length===0||n.length===1&&n[0].trim()===""){f.log.warn("Starter AGENTS template is empty.");return}let i=n.filter(r=>/^#{1,3}\s+/.test(r)).map(r=>r.replace(/^#{1,3}\s+/,"").trim()).filter(Boolean).slice(0,12);f.log.info(`Preview: ${e}`),i.length&&f.log.info(`Sections: ${i.join(" | ")}`);let s=n.slice(0,40).join(`
50
+ `)}import Qo from"fs-extra";import Zo from"os";import Vt from"path";async function lt(e){return Le(e)}var pt=lt;async function qt(){let e=Vt.join(Zo.homedir(),".codex","skills");return(await Qo.readdir(e,{withFileTypes:!0}).catch(()=>[])).filter(o=>o.isDirectory()).map(o=>({id:o.name,path:Vt.join(e,o.name)})).sort((o,n)=>o.id.localeCompare(n.id))}async function _e(e,t,o={}){let n=await ae({skills:e,skillsSelected:t,dryRun:!!o.dryRun});await je(n)}import{existsSync as en,readFileSync as tn}from"fs";import{dirname as Kt,join as zt}from"path";import{fileURLToPath as on}from"url";var nn=Kt(on(import.meta.url)),Ht=(e,t=!1)=>{try{return JSON.parse(tn(e,"utf-8"))}catch(o){if(t)return{};throw o}},sn=e=>!!(e.name==="codex-1up"||e.bin==="codex-1up"||e.bin&&typeof e.bin=="object"&&"codex-1up"in e.bin),rn=e=>{let t=e,o=null;for(;;){let n=zt(t,"package.json");if(en(n)){o||(o=n);let s=Ht(n,!0);if(sn(s))return n}let i=Kt(t);if(i===t)break;t=i}return o??zt(e,"package.json")},an=rn(nn),dt=Ht(an),Oe=dt.name||"codex-1up",le=dt.version||"0.0.0",Yt=dt.description||"Codex CLI helper";import{promises as ft}from"fs";import{resolve as ct}from"path";import*as f from"@clack/prompts";import{$ as we,which as ye}from"zx";import*as Ge from"@clack/prompts";async function ln(){let e=le,t=await pn(Oe),o=!!(t&&dn(t,e));return{current:e,latest:t,updateAvailable:o}}async function Me(e){let t=e.logger,o=await ln();if(!o.latest)return t?.warn("Unable to check for codex-1up updates right now."),"error";if(!o.updateAvailable)return t?.ok(`codex-1up is up-to-date (v${o.current}).`),"up-to-date";let n=e.interactive&&!e.assumeYes&&!e.skipConfirmation,i=e.assumeYes||e.skipConfirmation;if(n){let p=await Ge.confirm({message:`New codex-1up version available (v${o.latest}). Update now?`,initialValue:!0});if(Ge.isCancel(p))return t?.info("Update canceled."),"skipped";i=!!p}if(!i)return t?.info("Skipping codex-1up update."),"skipped";let s=await Te({logger:t,interactive:e.interactive&&!e.assumeYes&&!e.skipConfirmation});if(s==="none")return t?.warn("No supported Node package manager found; cannot update codex-1up."),"error";let r=o.latest?`${Oe}@${o.latest}`:Oe,a=!!e.dryRun;return s==="pnpm"?(t?.info("Updating codex-1up via pnpm"),await I("pnpm",["add","-g",r],{dryRun:a,logger:t})):(t?.info("Updating codex-1up via npm"),await I("npm",["install","-g",r],{dryRun:a,logger:t})),t?.ok(`codex-1up updated to v${o.latest}`),"updated"}async function pn(e){try{let t=await fetch(`https://registry.npmjs.org/${encodeURIComponent(e)}/latest`);return t.ok?(await t.json()).version:void 0}catch{return}}function dn(e,t){let o=Jt(e),n=Jt(t);if(!o||!n)return e!==t;for(let i=0;i<3;i++){if(o[i]>n[i])return!0;if(o[i]<n[i])return!1}return!1}function Jt(e){let t=e.match(/(\d+)\.(\d+)\.(\d+)/);return t?[Number(t[1]),Number(t[2]),Number(t[3])]:null}async function Xt(e){return xe(e)}var cn=["balanced","safe","yolo"];async function Qt(e){let{repoRoot:t,isUnixLike:o,globalAgentsExists:n,currentProfile:i,seededProfile:s,bundledSkills:r,availableTools:a,cliArgs:p}=e,{profileChoice:l,profileMode:c,profileScope:d,setDefaultProfile:u,profilesSelected:h,installTools:v,toolsSelected:k,installCodexCli:C,notifyAction:A,globalAgentsAction:D,notificationSound:q,skillsMode:K,skillsSelected:Q}=e.selections;await Me({interactive:!0,assumeYes:!1,skipConfirmation:!1,dryRun:!1,logger:{log:m=>f.log.info(m),info:m=>f.log.info(m),ok:m=>f.log.success(m),warn:m=>f.log.warn(m),err:m=>f.log.warn(m)}});let x=await Xt();if(x.found){let m=x.version?`v${x.version}`:"unknown version";x.latest?x.updateAvailable?f.log.info(`Codex CLI detected (${m}). Newer version available: v${x.latest}.`):f.log.info(`Codex CLI detected (${m}). Latest: v${x.latest}.`):f.log.info(`Codex CLI detected (${m}).`)}else f.log.info("Codex CLI not detected.");if(C==="no")x.found?x.updateAvailable&&f.log.info("Codex CLI update disabled by --codex-cli no."):f.log.info("Codex CLI install disabled by --codex-cli no.");else if(C==="auto")if(x.found){if(x.updateAvailable){let m=await f.confirm({message:`Codex CLI ${x.version} found; latest is ${x.latest}. Update now?`,initialValue:!0});if(f.isCancel(m))return R();C=m?"yes":"no"}}else{let m=await f.confirm({message:"Codex CLI not found. Install now?",initialValue:!0});if(f.isCancel(m))return R();C=m?"yes":"no"}if(o&&!p.toolsArg){let m=await he(),w=m.filter(y=>y.installed).map(y=>y.id),b=m.filter(y=>!y.installed).map(y=>y.id);for(f.log.info(`Tools detected: ${w.join(", ")||"none"}`),b.length&&f.log.info(`Missing tools: ${b.join(", ")}`);;){let y=await f.select({message:"Install/update developer tools",options:[{label:"Install/Update all",value:"all"},{label:"Select",value:"select"},{label:"Skip",value:"skip"}],initialValue:"all"});if(f.isCancel(y))return R();if(v=y,y!=="select"){k=void 0;break}f.log.info("Tip: press Esc to go back.");let E=await Fe({message:"Select tools to install",options:a.map(g=>{let $=w.includes(g.id);return{label:g.id,value:g.id,hint:$?"installed":"missing"}})});if(E==="back")continue;let j=Array.isArray(E)?E.map(g=>String(g).trim().toLowerCase()).filter(X):[];j.length===0?(v="skip",k=void 0):k=Array.from(new Set(j));break}}else!o&&!p.toolsArg&&(v="skip",k=void 0);let H=[{label:"Balanced (recommended)",value:"balanced",hint:"on-request approvals \xB7 workspace-write \xB7 web search on"},{label:"Safe",value:"safe",hint:"on-failure approvals \xB7 read-only \xB7 web search off"},{label:"YOLO",value:"yolo",hint:"never approvals \xB7 danger-full-access \xB7 gpt-5.2-codex"}];if(!p.profileScope)for(;;){let m=await f.select({message:"Install all profiles (balanced, safe, yolo)?",options:[{label:"Yes \u2014 install/update all profiles",value:"all"},{label:"Choose profiles\u2026",value:"selected"},{label:"No \u2014 don't install any profiles",value:"skip"}],initialValue:"all"});if(f.isCancel(m))return R();if(m==="skip"){d="selected",h=[],l="skip";break}if(m!=="selected"){d=m;break}f.log.info("Tip: press Esc to go back.");let w=await Fe({message:"Select profiles to install",options:H.map(E=>({label:E.label,value:E.value,hint:E.hint}))});if(w==="back")continue;let b=Array.isArray(w)?w.map(E=>String(E).trim().toLowerCase()).filter(be):[],y=Array.from(new Set(b));d="selected",y.length===0?(h=[],l="skip"):h=y;break}if(d!=="all"&&!p.profileChoice&&f.log.info(["Profiles:"," - Balanced: on-request approvals, workspace-write sandbox, web search on."," - Safe: on-failure approvals, read-only sandbox, web search off."," - YOLO: never approvals, danger-full-access, gpt-5.2-codex, high reasoning."].join(`
51
+ `)),d==="single"){if(!p.profileChoice){let m=await f.select({message:"Choose a Codex profile to install",options:[...H,{label:"Skip (no profile changes)",value:"skip"}],initialValue:mn(i)});if(f.isCancel(m))return R();l=m}}else if(d==="selected"){if(h===void 0){f.log.info("Tip: press Esc to go back.");let m=await Fe({message:"Select profiles to install",options:H.map(w=>({label:w.label,value:w.value,hint:w.hint}))});if(m==="back")h=[],l="skip";else{let w=Array.isArray(m)?m.map(y=>String(y).trim().toLowerCase()).filter(be):[],b=Array.from(new Set(w));b.length===0?(h=[],l="skip"):h=b}}(h||[]).length>0&&be(l)&&!h.includes(l)&&(l=h[0])}else d==="all"&&l==="skip"&&(l=s);let P=d==="all"?[...cn]:d==="selected"?h||[]:l==="skip"?[]:[l];if(P.length>0&&!p.profileMode){let m=await f.select({message:d==="all"?"How should we write all profiles?":P.length>1?"How should we write selected profiles?":`How should we write profiles.${P[0]}?`,options:[{label:"Overwrite (use codex-1up defaults)",value:"overwrite"},{label:"Add Merge (add missing, keep your default settings)",value:"add"}],initialValue:c});if(f.isCancel(m))return R();c=m}if(P.length===0)u=!1;else if(P.length===1){let m=P[0],w=await f.confirm({message:`Wrote profiles.${m} to ~/.codex/config.toml (mode: ${c}). Set this as the default profile?`,initialValue:!0});if(f.isCancel(w))return R();u=!!w,u&&(l=m)}else{let m=[{label:"Keep current default (skip)",value:"skip"},...P.map(y=>({label:y==="balanced"?"Balanced":y==="safe"?"Safe":"YOLO",value:y}))],w=be(l)&&P.includes(l)?l:P[0],b=await f.select({message:"Select a default profile (optional)",options:m,initialValue:w});if(f.isCancel(b))return R();b==="skip"?u=!1:(u=!0,l=b)}if(!p.soundArg){let y=function(){return[{label:"Skip (leave current setup)",value:"skip"},{label:"None (disable sounds)",value:"none"},...w.map(g=>({label:g,value:g})),{label:"Custom path\u2026",value:"custom"}]};var Z=y;let m=ct(t,"sounds"),w=[];try{w=(await ft.readdir(m)).filter(g=>/\.(wav|mp3|ogg)$/i.test(g)).sort()}catch(g){}A="yes";let b=w.includes("noti_1.wav")?"noti_1.wav":w[0]||"none";async function E(g){let $=await f.text({message:"Enter absolute path to a .wav file",placeholder:g||"/absolute/path/to/sound.wav",validate(_){if(!_)return"Path required";if(!_.startsWith("/"))return"Use an absolute path";if(!/(\.wav|\.mp3|\.ogg)$/i.test(_))return"Supported: .wav, .mp3, .ogg"}});if(f.isCancel($))return null;try{await ft.access(String($))}catch{return f.log.warn("File not found. Try again."),await E(String($))}return String($)}let j=await f.select({message:"Notification sound",options:y(),initialValue:b});if(f.isCancel(j))return R();if(j==="skip")A="no",q=void 0;else if(j==="custom"){let g=await E();if(g===null)return R();b=g}else b=j;if(j!=="skip"){for(;;){let g=await f.select({message:`Selected: ${b}. What next?`,options:[{label:"Preview \u25B6 (press p then Enter)",value:"preview"},{label:"Use this",value:"use"},{label:"Choose another\u2026",value:"change"}],initialValue:"use"});if(f.isCancel(g))return R();if(g==="use")break;if(g==="change"){let $=await f.select({message:"Notification sound",options:y(),initialValue:b});if(f.isCancel($))return R();if($==="custom"){let _=await E();if(_===null)return R();b=_}else if($==="skip"){A="no",q=void 0;break}else b=$;continue}try{let $=b==="none"?"none":b.startsWith("/")?b:ct(t,"sounds",b);await fn($)}catch($){f.log.warn(String($))}}q===void 0&&(q=b)}}let W=["Global AGENTS.md is shared instructions Codex can reference in any repo.","We add a short starter guide (fd/ast-grep/jq/yq patterns, deterministic selects).","Backups will be created.","You can remove it later from ~/.codex/AGENTS.md."].join(`
52
+ `),B=ct(t,"templates","agent-templates","AGENTS-default.md"),M=await(async m=>{for(;;){f.log.info(W);let w=await f.select({message:"Global ~/.codex/AGENTS.md (optional)",options:m?[{label:"Add to your existing AGENTS.md (keeps your content, adds ours; backup created)",value:"append-default"},{label:"Overwrite existing (replace with starter; backup created)",value:"overwrite-default"},{label:"Preview starter AGENTS.md",value:"preview"},{label:"Skip \u2014 leave as-is (you can run codex-1up agents later)",value:"skip"}]:[{label:"Create starter AGENTS.md (recommended; helps give Codex repo context everywhere)",value:"create-default"},{label:"Preview starter AGENTS.md",value:"preview"},{label:"Skip for now (you can add later with codex-1up agents --global)",value:"skip"}],initialValue:m?"append-default":"create-default"});if(f.isCancel(w))return null;if(w==="preview"){await un(B);continue}return w}})(n);if(!M)return R();if(D=M,!p.skillsArg&&r.length)for(f.log.info(["Agent Skills are optional, portable skill folders (SKILL.md + optional scripts/references).","codex-1up can install bundled skills into ~/.codex/skills so your agent can reference them.",`Bundled skills: ${r.map(m=>m.id).join(", ")}`].join(`
53
+ `));;){let m=await f.select({message:"Install bundled Agent Skills (optional)",options:[{label:"None (do not install skills)",value:"skip"},{label:"Select skills\u2026",value:"select"},{label:"All (install every bundled skill)",value:"all"}],initialValue:"skip"});if(f.isCancel(m))return R();if(K=m,m!=="select")break;f.log.info("Tip: press Esc to go back.");let w=await Fe({message:"Select skills to install",options:r.map(y=>({label:y.id,value:y.id,hint:y.description.length>120?`${y.description.slice(0,117)}\u2026`:y.description}))});if(w==="back")continue;let b=Array.isArray(w)?w.map(y=>String(y).trim()).filter(Boolean):[];b.length===0?(K="skip",Q=void 0):Q=b;break}return{selections:{profileChoice:l,profileMode:c,profileScope:d,setDefaultProfile:u,profilesSelected:h,installTools:v,toolsSelected:k,installCodexCli:C,notifyAction:A,globalAgentsAction:D,notificationSound:q,skillsMode:K,skillsSelected:Q}}}async function fn(e){if(e.endsWith("/none")||e==="none")return;let t=[async o=>{await ye("afplay"),await we`afplay ${o}`},async o=>{await ye("paplay"),await we`paplay ${o}`},async o=>{await ye("aplay"),await we`aplay ${o}`},async o=>{await ye("mpg123"),await we`mpg123 -q ${o}`},async o=>{await ye("ffplay"),await we`ffplay -nodisp -autoexit -loglevel quiet ${o}`}];for(let o of t)try{await o(e);return}catch{}throw new Error("No audio player found (afplay/paplay/aplay/mpg123/ffplay)")}async function Fe(e){let o=await f.multiselect({message:e.message,options:e.options});return f.isCancel(o)?"back":Array.isArray(o)?o.map(i=>String(i)):[]}async function un(e){let o="";try{o=await ft.readFile(e,"utf8")}catch{f.log.warn(`Starter AGENTS template not found at ${e}`);return}let n=o.split(/\r?\n/);if(n.length===0||n.length===1&&n[0].trim()===""){f.log.warn("Starter AGENTS template is empty.");return}let i=n.filter(r=>/^#{1,3}\s+/.test(r)).map(r=>r.replace(/^#{1,3}\s+/,"").trim()).filter(Boolean).slice(0,12);f.log.info(`Preview: ${e}`),i.length&&f.log.info(`Sections: ${i.join(" | ")}`);let s=n.slice(0,40).join(`
53
54
  `);process.stdout.write(s+`
54
- `),n.length>40&&f.log.info(`... (${n.length-40} more lines)`)}function pn(e){return be(e)?e:"balanced"}function be(e){return e==="balanced"||e==="safe"||e==="yolo"}function A(){return f.cancel("Install aborted"),null}var Fe=T(),cn=["balanced","safe","yolo"],Qt=dn({meta:{name:"install",description:"Run the codex-1up installer with validated flags"},args:{yes:{type:"boolean",description:"Non-interactive; accept safe defaults"},"dry-run":{type:"boolean",description:"Print actions without making changes"},"skip-confirmation":{type:"boolean",description:"Skip prompts"},shell:{type:"string",description:"auto|zsh|bash|fish"},vscode:{type:"string",description:"Install VS Code extension id"},"no-vscode":{type:"boolean",description:"Skip VS Code extension checks"},"install-node":{type:"string",description:"nvm|brew|skip"},tools:{type:"string",description:"all|skip|<comma-separated tool ids> (rg, fd, fzf, jq, yq, ast-grep, bat, git, git-delta, gh)"},"codex-cli":{type:"string",description:"yes|no install/upgrade Codex CLI + ast-grep globally"},"profiles-scope":{type:"string",description:"single|all (write one profile or all profiles)"},profile:{type:"string",description:"balanced|safe|yolo|skip (choose profile to write)"},"profile-mode":{type:"string",description:"add|overwrite (profile table merge strategy)"},sound:{type:"string",description:'Sound file, "none", or "skip" to leave unchanged'},"agents-md":{type:"string",description:"Write starter AGENTS.md to PATH (default PWD/AGENTS.md)",required:!1},skills:{type:"string",description:"Install bundled Agent Skills to ~/.codex/skills: all|skip|<comma-separated names>"}},async run({args:e,rawArgs:t}){let o=ct(We.homedir(),".codex","config.toml"),n=await ft(o),i=ct(We.homedir(),".codex","notify.sh"),s=await ft(i),r=ct(We.homedir(),".codex","AGENTS.md"),a=await ft(r),p=n?await wn(o):void 0,l=process.stdout.isTTY&&!e["dry-run"]&&!e["skip-confirmation"]&&!e.yes,c=fn(e.profile),d=un(e["profile-mode"]),u=mn(e["profiles-scope"]),w=gn(e["codex-cli"]),v=process.platform==="darwin"||process.platform==="linux",k=typeof e.sound>"u"?void 0:String(e.sound).trim(),C=typeof e.tools>"u"?void 0:String(e.tools).trim(),R=e,D=typeof R.skills>"u"?void 0:String(R.skills).trim();if(k==="")throw new Error('Invalid --sound value (expected path, "none", or "skip")');if(C==="")throw new Error("Invalid --tools value (expected all|skip|<comma-separated tool ids>)");if(D==="")throw new Error("Invalid --skills value (expected all|skip|<comma-separated skill names>)");let z=t.some(g=>g==="--no-vscode"||g.startsWith("--no-vscode=")),K=await rt(Fe),Q=J(),ze=(c&&c!=="skip"?c:ut(p)?p:void 0)||"balanced",x=ze,Y=d||"add",P=u||"single",le=!0,W,B=v?"all":"skip",Ce=w||"auto",M,Z,m,h="skip",b,y;if(k&&(g=>{let S=g.trim().toLowerCase();if(S==="skip"){M="no",m=void 0;return}M="yes",m=S==="none"?"none":g})(k),D){let g=D.trim().toLowerCase();if(g==="all")h="all";else if(g==="skip"||g==="none")h="skip";else{let S=D.split(",").map(q=>q.trim()).filter(Boolean);if(S.length===0)throw new Error("Invalid --skills value (expected all|skip|<comma-separated skill names>)");let _=new Set(K.map(q=>q.id)),V=S.filter(q=>!_.has(q));if(V.length){let q=K.map(co=>co.id).join(", ")||"(none)";throw new Error(`Unknown skill(s): ${V.join(", ")}. Available: ${q}`)}h="select",b=S}}if(C){let g=C.trim().toLowerCase();if(g==="all")B="all";else if(g==="skip"||g==="none")B="skip";else{let S=C.split(",").map(V=>V.trim().toLowerCase()).filter(Boolean);if(S.length===0)throw new Error("Invalid --tools value (expected all|skip|<comma-separated tool ids>)");let _=S.filter(V=>!X(V));if(_.length){let V=Q.map(q=>q.id).join(", ")||"(none)";throw new Error(`Unknown tool(s): ${_.join(", ")}. Available: ${V}`)}B="select",y=Array.from(new Set(S)).filter(X)}}else v||(B="skip");if(l){F.log.info(`Codex 1up v${ae} - equips your coding agent with powerful tools`),F.log.info("Install wizard");let g=await Ht({repoRoot:Fe,isUnixLike:v,globalAgentsExists:a,currentProfile:p,seededProfile:ze,bundledSkills:K,availableTools:Q,cliArgs:{profileChoice:c,profileMode:d,profileScope:u,soundArg:k,toolsArg:C,skillsArg:D},selections:{profileChoice:x,profileMode:Y,profileScope:P,setDefaultProfile:le,profilesSelected:W,installTools:B,toolsSelected:y,installCodexCli:Ce,notifyAction:M,globalAgentsAction:Z,notificationSound:m,skillsMode:h,skillsSelected:b}});if(!g)return;({profileChoice:x,profileMode:Y,profileScope:P,setDefaultProfile:le,profilesSelected:W,installTools:B,toolsSelected:y,installCodexCli:Ce,notifyAction:M,globalAgentsAction:Z,notificationSound:m,skillsMode:h,skillsSelected:b}=g.selections)}l||(P==="selected"&&W?.length&&ut(x)&&!W.includes(x)&&(x=W[0]),(P==="all"?[...cn]:P==="selected"?W||[]:x==="skip"?[]:[x]).length===0&&(le=!1),typeof M>"u"&&(M=s?"no":"yes"),typeof Z>"u"&&(Z="skip"));let j={profile:x,profileScope:P,profileMode:Y,setDefaultProfile:le,profilesSelected:W,installCodexCli:Ce,installTools:B,toolsSelected:y,notify:M??(s?"no":"yes"),globalAgents:Z??"skip",notificationSound:m,skills:h,skillsSelected:b,mode:"manual",installNode:e["install-node"]||"skip",shell:String(e.shell||"auto"),vscodeId:z?void 0:e.vscode?String(e.vscode):void 0,noVscode:z||e["no-vscode"]||!1,agentsMd:typeof e["agents-md"]<"u"?String(e["agents-md"]||process.cwd()):void 0,dryRun:e["dry-run"]||!1,assumeYes:e.yes||!1,skipConfirmation:e["skip-confirmation"]||!1};if(l){F.log.info("Installing prerequisites and writing config..."),F.log.warn("Some steps may require sudo password or confirmation prompts.");try{await it(j,Fe),F.log.success("Base install complete"),F.log.success("Install finished")}catch(g){throw F.cancel(`Installation failed: ${g}`),g}await st();return}try{await it(j,Fe),await st()}catch(g){throw F.cancel(`Installation failed: ${g}`),g}}});async function ft(e){try{return await Jt.access(e),!0}catch{return!1}}function fn(e){if(e==null)return;let t=String(e).toLowerCase();if(ut(t))return t;if(t==="skip")return"skip";throw new Error("Invalid --profile value (use balanced|safe|yolo|skip).")}function un(e){if(e==null)return;let t=String(e).toLowerCase();if(t==="add"||t==="overwrite")return t;throw new Error("Invalid --profile-mode value (use add|overwrite).")}function mn(e){if(e==null)return;let t=String(e).toLowerCase();if(t==="single"||t==="all")return t;throw new Error("Invalid --profiles-scope value (use single|all).")}function gn(e){if(e==null)return;let t=String(e).toLowerCase();if(t==="yes"||t==="no")return t;throw new Error("Expected yes|no")}function ut(e){return e==="balanced"||e==="safe"||e==="yolo"}async function wn(e){try{let t=await Jt.readFile(e,"utf8"),n=Xt.parse(t).profile;return typeof n=="string"?n:void 0}catch(t){return}}import{defineCommand as hn}from"citty";import{promises as ke}from"fs";import{resolve as Zt,dirname as yn}from"path";var bn=T();async function mt(e){try{return await ke.access(e),!0}catch{return!1}}async function kn(e,t){if(await mt(t)){let n=`${t}.backup.${new Date().toISOString().replace(/[:.]/g,"").replace("T","_").slice(0,15)}`;await ke.copyFile(t,n)}await ke.mkdir(yn(t),{recursive:!0}),await ke.copyFile(e,t)}var eo=hn({meta:{name:"agents",description:"Write an AGENTS.md template"},args:{path:{type:"string",required:!0,description:"Target repo path or file"}},async run({args:e}){let t=String(e.path),o=Zt(bn,"templates/agent-templates","AGENTS-default.md"),i=await mt(t).then(async s=>s&&(await ke.stat(t)).isDirectory()).catch(()=>!1)?Zt(t,"AGENTS.md"):t;if(!await mt(o))throw new Error(`Template not found: ${o}`);await kn(o,i),process.stdout.write(`Wrote ${i}
55
- `)}});import{defineCommand as vn}from"citty";import{$ as Cn}from"zx";import{resolve as Sn}from"path";var $n=T(),to=vn({meta:{name:"doctor",description:"Run environment checks"},async run(){await Cn`bash ${Sn($n,"scripts/doctor.sh")}`}});import{defineCommand as xn}from"citty";import{$ as In}from"zx";import{resolve as Tn}from"path";var Pn=T(),oo=xn({meta:{name:"uninstall",description:"Clean up aliases and config created by this tool"},async run(){await In`bash ${Tn(Pn,"scripts/uninstall.sh")}`}});import{defineCommand as Be}from"citty";import{promises as ve}from"fs";import{resolve as ht,dirname as An}from"path";import Rn from"os";var En=T();function gt(){let e=ht(Rn.homedir(),".codex"),t=ht(e,"config.toml");return{CODEX_HOME:e,CFG:t}}async function wt(e){return ve.readFile(e,"utf8")}async function no(e,t){await ve.mkdir(An(e),{recursive:!0}),await ve.writeFile(e,t,"utf8")}function io(e){let t=/^\[profiles\.(.+?)\]/gm,o=[],n;for(;n=t.exec(e);)o.push(n[1]);return o}function Nn(e,t){let o=`profile = "${t}"`;if(/^profile\s*=\s*".*"/m.test(e))return e.replace(/^profile\s*=\s*".*"/m,o);let n=e.indexOf(`
55
+ `),n.length>40&&f.log.info(`... (${n.length-40} more lines)`)}function mn(e){return be(e)?e:"balanced"}function be(e){return e==="balanced"||e==="safe"||e==="yolo"}function R(){return f.cancel("Install aborted"),null}var We=T(),hn=["balanced","safe","yolo"],to=gn({meta:{name:"install",description:"Run the codex-1up installer with validated flags"},args:{yes:{type:"boolean",description:"Non-interactive; accept safe defaults"},"dry-run":{type:"boolean",description:"Print actions without making changes"},"skip-confirmation":{type:"boolean",description:"Skip prompts"},shell:{type:"string",description:"auto|zsh|bash|fish"},vscode:{type:"string",description:"Install VS Code extension id"},"no-vscode":{type:"boolean",description:"Skip VS Code extension checks"},"install-node":{type:"string",description:"nvm|brew|skip"},tools:{type:"string",description:"all|skip|<comma-separated tool ids> (rg, fd, fzf, jq, yq, ast-grep, bat, git, git-delta, gh)"},"codex-cli":{type:"string",description:"yes|no install/upgrade Codex CLI + ast-grep globally"},"profiles-scope":{type:"string",description:"single|all (write one profile or all profiles)"},profile:{type:"string",description:"balanced|safe|yolo|skip (choose profile to write)"},"profile-mode":{type:"string",description:"add|overwrite (profile table merge strategy)"},sound:{type:"string",description:'Sound file, "none", or "skip" to leave unchanged'},"agents-md":{type:"string",description:"Write starter AGENTS.md to PATH (default PWD/AGENTS.md)",required:!1},skills:{type:"string",description:"Install bundled Agent Skills to ~/.codex/skills: all|skip|<comma-separated names>"}},async run({args:e,rawArgs:t}){let o=ut(Be.homedir(),".codex","config.toml"),n=await mt(o),i=ut(Be.homedir(),".codex","notify.sh"),s=await mt(i),r=ut(Be.homedir(),".codex","AGENTS.md"),a=await mt(r),p=n?await vn(o):void 0,l=process.stdout.isTTY&&!e["dry-run"]&&!e["skip-confirmation"]&&!e.yes,c=wn(e.profile),d=yn(e["profile-mode"]),u=bn(e["profiles-scope"]),h=kn(e["codex-cli"]),v=process.platform==="darwin"||process.platform==="linux",k=typeof e.sound>"u"?void 0:String(e.sound).trim(),C=typeof e.tools>"u"?void 0:String(e.tools).trim(),A=e,D=typeof A.skills>"u"?void 0:String(A.skills).trim();if(k==="")throw new Error('Invalid --sound value (expected path, "none", or "skip")');if(C==="")throw new Error("Invalid --tools value (expected all|skip|<comma-separated tool ids>)");if(D==="")throw new Error("Invalid --skills value (expected all|skip|<comma-separated skill names>)");let q=t.some(g=>g==="--no-vscode"||g.startsWith("--no-vscode=")),K=await lt(We),Q=J(),ze=(c&&c!=="skip"?c:gt(p)?p:void 0)||"balanced",x=ze,H=d||"add",P=u||"single",pe=!0,W,B=v?"all":"skip",Ce=h||"auto",M,Z,m,w="skip",b,y;if(k&&(g=>{let $=g.trim().toLowerCase();if($==="skip"){M="no",m=void 0;return}M="yes",m=$==="none"?"none":g})(k),D){let g=D.trim().toLowerCase();if(g==="all")w="all";else if(g==="skip"||g==="none")w="skip";else{let $=D.split(",").map(U=>U.trim()).filter(Boolean);if($.length===0)throw new Error("Invalid --skills value (expected all|skip|<comma-separated skill names>)");let _=new Set(K.map(U=>U.id)),z=$.filter(U=>!_.has(U));if(z.length){let U=K.map(mo=>mo.id).join(", ")||"(none)";throw new Error(`Unknown skill(s): ${z.join(", ")}. Available: ${U}`)}w="select",b=$}}if(C){let g=C.trim().toLowerCase();if(g==="all")B="all";else if(g==="skip"||g==="none")B="skip";else{let $=C.split(",").map(z=>z.trim().toLowerCase()).filter(Boolean);if($.length===0)throw new Error("Invalid --tools value (expected all|skip|<comma-separated tool ids>)");let _=$.filter(z=>!X(z));if(_.length){let z=Q.map(U=>U.id).join(", ")||"(none)";throw new Error(`Unknown tool(s): ${_.join(", ")}. Available: ${z}`)}B="select",y=Array.from(new Set($)).filter(X)}}else v||(B="skip");if(l){F.log.info(`Codex 1up v${le} - equips your coding agent with powerful tools`),F.log.info("Install wizard");let g=await Qt({repoRoot:We,isUnixLike:v,globalAgentsExists:a,currentProfile:p,seededProfile:ze,bundledSkills:K,availableTools:Q,cliArgs:{profileChoice:c,profileMode:d,profileScope:u,soundArg:k,toolsArg:C,skillsArg:D},selections:{profileChoice:x,profileMode:H,profileScope:P,setDefaultProfile:pe,profilesSelected:W,installTools:B,toolsSelected:y,installCodexCli:Ce,notifyAction:M,globalAgentsAction:Z,notificationSound:m,skillsMode:w,skillsSelected:b}});if(!g)return;({profileChoice:x,profileMode:H,profileScope:P,setDefaultProfile:pe,profilesSelected:W,installTools:B,toolsSelected:y,installCodexCli:Ce,notifyAction:M,globalAgentsAction:Z,notificationSound:m,skillsMode:w,skillsSelected:b}=g.selections)}l||(P==="selected"&&W?.length&&gt(x)&&!W.includes(x)&&(x=W[0]),(P==="all"?[...hn]:P==="selected"?W||[]:x==="skip"?[]:[x]).length===0&&(pe=!1),typeof M>"u"&&(M=s?"no":"yes"),typeof Z>"u"&&(Z="skip"));let j={profile:x,profileScope:P,profileMode:H,setDefaultProfile:pe,profilesSelected:W,installCodexCli:Ce,installTools:B,toolsSelected:y,notify:M??(s?"no":"yes"),globalAgents:Z??"skip",notificationSound:m,skills:w,skillsSelected:b,mode:"manual",installNode:e["install-node"]||"skip",shell:String(e.shell||"auto"),vscodeId:q?void 0:e.vscode?String(e.vscode):void 0,noVscode:q||e["no-vscode"]||!1,agentsMd:typeof e["agents-md"]<"u"?String(e["agents-md"]||process.cwd()):void 0,dryRun:e["dry-run"]||!1,assumeYes:e.yes||!1,skipConfirmation:e["skip-confirmation"]||!1};if(l){F.log.info("Installing prerequisites and writing config..."),F.log.warn("Some steps may require sudo password or confirmation prompts.");try{await rt(j,We),F.log.success("Base install complete"),F.log.success("Install finished")}catch(g){throw F.cancel(`Installation failed: ${g}`),g}await at();return}try{await rt(j,We),await at()}catch(g){throw F.cancel(`Installation failed: ${g}`),g}}});async function mt(e){try{return await Zt.access(e),!0}catch{return!1}}function wn(e){if(e==null)return;let t=String(e).toLowerCase();if(gt(t))return t;if(t==="skip")return"skip";throw new Error("Invalid --profile value (use balanced|safe|yolo|skip).")}function yn(e){if(e==null)return;let t=String(e).toLowerCase();if(t==="add"||t==="overwrite")return t;throw new Error("Invalid --profile-mode value (use add|overwrite).")}function bn(e){if(e==null)return;let t=String(e).toLowerCase();if(t==="single"||t==="all")return t;throw new Error("Invalid --profiles-scope value (use single|all).")}function kn(e){if(e==null)return;let t=String(e).toLowerCase();if(t==="yes"||t==="no")return t;throw new Error("Expected yes|no")}function gt(e){return e==="balanced"||e==="safe"||e==="yolo"}async function vn(e){try{let t=await Zt.readFile(e,"utf8"),n=eo.parse(t).profile;return typeof n=="string"?n:void 0}catch(t){return}}import{defineCommand as Cn}from"citty";import{promises as ke}from"fs";import{resolve as oo,dirname as Sn}from"path";var $n=T();async function ht(e){try{return await ke.access(e),!0}catch{return!1}}async function xn(e,t){if(await ht(t)){let n=`${t}.backup.${new Date().toISOString().replace(/[:.]/g,"").replace("T","_").slice(0,15)}`;await ke.copyFile(t,n)}await ke.mkdir(Sn(t),{recursive:!0}),await ke.copyFile(e,t)}var no=Cn({meta:{name:"agents",description:"Write an AGENTS.md template"},args:{path:{type:"string",required:!0,description:"Target repo path or file"}},async run({args:e}){let t=String(e.path),o=oo($n,"templates/agent-templates","AGENTS-default.md"),i=await ht(t).then(async s=>s&&(await ke.stat(t)).isDirectory()).catch(()=>!1)?oo(t,"AGENTS.md"):t;if(!await ht(o))throw new Error(`Template not found: ${o}`);await xn(o,i),process.stdout.write(`Wrote ${i}
56
+ `)}});import{defineCommand as In}from"citty";import{$ as Tn}from"zx";import{resolve as Pn}from"path";var Rn=T(),io=In({meta:{name:"doctor",description:"Run environment checks"},async run(){await Tn`bash ${Pn(Rn,"scripts/doctor.sh")}`}});import{defineCommand as An}from"citty";import{$ as En}from"zx";import{resolve as Nn}from"path";var Ln=T(),so=An({meta:{name:"uninstall",description:"Clean up aliases and config created by this tool"},async run(){await En`bash ${Nn(Ln,"scripts/uninstall.sh")}`}});import{defineCommand as Ue}from"citty";import{promises as ve}from"fs";import{resolve as bt,dirname as Dn}from"path";import jn from"os";var _n=T();function wt(){let e=bt(jn.homedir(),".codex"),t=bt(e,"config.toml");return{CODEX_HOME:e,CFG:t}}async function yt(e){return ve.readFile(e,"utf8")}async function ro(e,t){await ve.mkdir(Dn(e),{recursive:!0}),await ve.writeFile(e,t,"utf8")}function ao(e){let t=/^\[profiles\.(.+?)\]/gm,o=[],n;for(;n=t.exec(e);)o.push(n[1]);return o}function On(e,t){let o=`profile = "${t}"`;if(/^profile\s*=\s*".*"/m.test(e))return e.replace(/^profile\s*=\s*".*"/m,o);let n=e.indexOf(`
56
57
  `);return n===-1?o+`
57
58
  `+e:e.slice(0,n+1)+o+`
58
- `+e.slice(n+1)}var so=Be({meta:{name:"config",description:"Manage Codex config profiles"},subCommands:{init:Be({meta:{name:"init",description:"Install unified config with multiple profiles"},args:{force:{type:"boolean",description:"Backup and overwrite if exists"}},async run({args:e}){let t=ht(En,"templates/codex-config.toml"),o=await wt(t),{CFG:n}=gt(),i=await ve.access(n).then(()=>!0).catch(()=>!1);if(i&&!e.force){process.stdout.write(`${n} exists. Use --force to overwrite.
59
+ `+e.slice(n+1)}var lo=Ue({meta:{name:"config",description:"Manage Codex config profiles"},subCommands:{init:Ue({meta:{name:"init",description:"Install unified config with multiple profiles"},args:{force:{type:"boolean",description:"Backup and overwrite if exists"}},async run({args:e}){let t=bt(_n,"templates/codex-config.toml"),o=await yt(t),{CFG:n}=wt(),i=await ve.access(n).then(()=>!0).catch(()=>!1);if(i&&!e.force){process.stdout.write(`${n} exists. Use --force to overwrite.
59
60
  `);return}if(i){let s=`${n}.backup.${Date.now()}`;await ve.copyFile(n,s),process.stdout.write(`Backed up to ${s}
60
- `)}await no(n,o),process.stdout.write(`Wrote ${n}
61
- `)}}),profiles:Be({meta:{name:"profiles",description:"List profiles in the current config"},async run(){let{CFG:e}=gt(),t=await wt(e),o=io(t);process.stdout.write(o.length?o.join(`
61
+ `)}await ro(n,o),process.stdout.write(`Wrote ${n}
62
+ `)}}),profiles:Ue({meta:{name:"profiles",description:"List profiles in the current config"},async run(){let{CFG:e}=wt(),t=await yt(e),o=ao(t);process.stdout.write(o.length?o.join(`
62
63
  `)+`
63
64
  `:`No profiles found
64
- `)}}),"set-profile":Be({meta:{name:"set-profile",description:"Set the active profile in config.toml"},args:{name:{type:"positional",required:!0,description:"Profile name"}},async run({args:e}){let{CFG:t}=gt(),o=await wt(t),n=io(o),i=String(e.name);if(!n.includes(i))throw new Error(`Unknown profile: ${i}`);let s=Nn(o,i);await no(t,s),process.stdout.write(`profile set to ${i}
65
- `)}})}});import{defineCommand as Ln}from"citty";var ro=Ln({meta:{name:"update",description:"Check for and apply codex-1up updates"},args:{yes:{type:"boolean",description:"Non-interactive; apply updates without prompting"},"dry-run":{type:"boolean",description:"Print actions without making changes"},"skip-confirmation":{type:"boolean",description:"Skip prompts"}},async run({args:e}){let t=await re(),o=process.stdout.isTTY&&!e["dry-run"]&&!e["skip-confirmation"]&&!e.yes;await Ge({interactive:o,assumeYes:!!e.yes,skipConfirmation:!!e["skip-confirmation"],dryRun:!!e["dry-run"],logger:t.logger})}});import{defineCommand as qe}from"citty";var ao=qe({meta:{name:"tools",description:"Manage developer tools"},subCommands:{list:qe({meta:{name:"list",description:"List known tools and installation status"},async run(){let e=await we();for(let t of e)process.stdout.write(`${t.id} ${t.installed?"\u2713":"\u2716"}
66
- `)}}),install:qe({meta:{name:"install",description:"Install tools by id or all"},args:{tool:{type:"positional",required:!0,description:'Tool id or "all"'},"dry-run":{type:"boolean",description:"Print actions without making changes"}},async run({args:e}){let t=String(e.tool||"").trim().toLowerCase();if(!t)throw new Error("Tool id required");if(t==="all"){await ot("all",{dryRun:!!e["dry-run"]});return}let o=t.split(",").map(s=>s.trim()).filter(Boolean),n=Array.from(new Set(o)),i=n.filter(s=>!X(s));if(i.length){let s=Mt().join(", ");throw new Error(`Unknown tool id(s): ${i.join(", ")}. Known: ${s}`)}await ot(n,{dryRun:!!e["dry-run"]})}}),doctor:qe({meta:{name:"doctor",description:"Show missing tools and hints"},async run(){let t=(await we()).filter(n=>!n.installed).map(n=>n.id);if(t.length===0){process.stdout.write(`All tools are installed.
65
+ `)}}),"set-profile":Ue({meta:{name:"set-profile",description:"Set the active profile in config.toml"},args:{name:{type:"positional",required:!0,description:"Profile name"}},async run({args:e}){let{CFG:t}=wt(),o=await yt(t),n=ao(o),i=String(e.name);if(!n.includes(i))throw new Error(`Unknown profile: ${i}`);let s=On(o,i);await ro(t,s),process.stdout.write(`profile set to ${i}
66
+ `)}})}});import{defineCommand as Gn}from"citty";var po=Gn({meta:{name:"update",description:"Check for and apply codex-1up updates"},args:{yes:{type:"boolean",description:"Non-interactive; apply updates without prompting"},"dry-run":{type:"boolean",description:"Print actions without making changes"},"skip-confirmation":{type:"boolean",description:"Skip prompts"}},async run({args:e}){let t=await ae(),o=process.stdout.isTTY&&!e["dry-run"]&&!e["skip-confirmation"]&&!e.yes;await Me({interactive:o,assumeYes:!!e.yes,skipConfirmation:!!e["skip-confirmation"],dryRun:!!e["dry-run"],logger:t.logger})}});import{defineCommand as Ve}from"citty";var co=Ve({meta:{name:"tools",description:"Manage developer tools"},subCommands:{list:Ve({meta:{name:"list",description:"List known tools and installation status"},async run(){let e=await he();for(let t of e)process.stdout.write(`${t.id} ${t.installed?"\u2713":"\u2716"}
67
+ `)}}),install:Ve({meta:{name:"install",description:"Install tools by id or all"},args:{tool:{type:"positional",required:!0,description:'Tool id or "all"'},"dry-run":{type:"boolean",description:"Print actions without making changes"}},async run({args:e}){let t=String(e.tool||"").trim().toLowerCase();if(!t)throw new Error("Tool id required");if(t==="all"){await it("all",{dryRun:!!e["dry-run"]});return}let o=t.split(",").map(s=>s.trim()).filter(Boolean),n=Array.from(new Set(o)),i=n.filter(s=>!X(s));if(i.length){let s=Bt().join(", ");throw new Error(`Unknown tool id(s): ${i.join(", ")}. Known: ${s}`)}await it(n,{dryRun:!!e["dry-run"]})}}),doctor:Ve({meta:{name:"doctor",description:"Show missing tools and hints"},async run(){let t=(await he()).filter(n=>!n.installed).map(n=>n.id);if(t.length===0){process.stdout.write(`All tools are installed.
67
68
  `);return}let o=J().map(n=>n.id).join(", ");process.stdout.write(`Missing tools: ${t.join(", ")}
68
69
  `),process.stdout.write(`Known tools: ${o}
69
- `)}})}});import{defineCommand as Ue}from"citty";var lo=Ue({meta:{name:"skills",description:"Manage bundled Agent Skills"},subCommands:{list:Ue({meta:{name:"list",description:"List bundled and installed skills"},async run(){let e=T(),t=await at(e),o=await Bt();if(process.stdout.write(`Bundled skills:
70
+ `)}})}});import{defineCommand as qe}from"citty";var fo=qe({meta:{name:"skills",description:"Manage bundled Agent Skills"},subCommands:{list:qe({meta:{name:"list",description:"List bundled and installed skills"},async run(){let e=T(),t=await pt(e),o=await qt();if(process.stdout.write(`Bundled skills:
70
71
  `),t.length===0)process.stdout.write(` (none)
71
72
  `);else for(let n of t)process.stdout.write(` ${n.id} \u2014 ${n.description}
72
73
  `);if(process.stdout.write(`
73
74
  Installed skills:
74
75
  `),o.length===0)process.stdout.write(` (none)
75
76
  `);else for(let n of o)process.stdout.write(` ${n.id}
76
- `)}}),install:Ue({meta:{name:"install",description:"Install bundled skills by id or all"},args:{name:{type:"positional",required:!0,description:'Skill id or "all"'},"dry-run":{type:"boolean",description:"Print actions without making changes"}},async run({args:e}){let t=String(e.name||"").trim();if(!t)throw new Error("Skill id required");if(t==="all"){await je("all",void 0,{dryRun:!!e["dry-run"]});return}let o=T(),n=await at(o),i=t.split(",").map(p=>p.trim()).filter(Boolean),s=new Set(n.map(p=>p.id)),r=new Set(n.map(p=>p.name)),a=i.filter(p=>!s.has(p)&&!r.has(p));if(a.length){let p=n.map(l=>l.id).join(", ")||"(none)";throw new Error(`Unknown skill(s): ${a.join(", ")}. Available: ${p}`)}await je("select",i,{dryRun:!!e["dry-run"]})}}),refresh:Ue({meta:{name:"refresh",description:"Reinstall bundled skills into ~/.codex/skills"},args:{"dry-run":{type:"boolean",description:"Print actions without making changes"}},async run({args:e}){await je("all",void 0,{dryRun:!!e["dry-run"]})}})}});var po=Dn({meta:{name:"codex-1up",version:ae,description:Vt},subCommands:{install:Qt,agents:eo,doctor:to,uninstall:oo,config:so,update:ro,tools:ao,skills:lo}});jn(po);
77
+ `)}}),install:qe({meta:{name:"install",description:"Install bundled skills by id or all"},args:{name:{type:"positional",required:!0,description:'Skill id or "all"'},"dry-run":{type:"boolean",description:"Print actions without making changes"}},async run({args:e}){let t=String(e.name||"").trim();if(!t)throw new Error("Skill id required");if(t==="all"){await _e("all",void 0,{dryRun:!!e["dry-run"]});return}let o=T(),n=await pt(o),i=t.split(",").map(p=>p.trim()).filter(Boolean),s=new Set(n.map(p=>p.id)),r=new Set(n.map(p=>p.name)),a=i.filter(p=>!s.has(p)&&!r.has(p));if(a.length){let p=n.map(l=>l.id).join(", ")||"(none)";throw new Error(`Unknown skill(s): ${a.join(", ")}. Available: ${p}`)}await _e("select",i,{dryRun:!!e["dry-run"]})}}),refresh:qe({meta:{name:"refresh",description:"Reinstall bundled skills into ~/.codex/skills"},args:{"dry-run":{type:"boolean",description:"Print actions without making changes"}},async run({args:e}){await _e("all",void 0,{dryRun:!!e["dry-run"]})}})}});var uo=Mn({meta:{name:"codex-1up",version:le,description:Yt},subCommands:{install:to,agents:no,doctor:io,uninstall:so,config:lo,update:po,tools:co,skills:fo}});Fn(uo);
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "codex-1up",
3
3
  "private": false,
4
4
  "type": "module",
5
- "version": "0.3.9",
5
+ "version": "0.3.10",
6
6
  "description": "TypeScript CLI for codex-1up (citty-based)",
7
7
  "bin": {
8
8
  "codex-1up": "bin/codex-1up.mjs"
@@ -1,24 +1,41 @@
1
- When you need to call tools from the shell, use this rubric:
1
+ ## Non-negotiables
2
+ - Ship production-grade, scalable (>1000 users) implementations; avoid MVP/minimal shortcuts.
3
+ - Optimize for long-term sustainability: maintainable, reliable designs.
4
+ - Make changes the single canonical implementation in the primary codepath; delete legacy/dead/duplicate paths as part of delivery.
5
+ - Use direct, first-class integrations; do not introduce shims, wrappers, glue code, or adapter layers.
6
+ - Keep a single source of truth for business rules/policy (validation, enums, flags, constants, config).
7
+ - Clean API invariants: define required inputs, validate up front, fail fast.
8
+ - Use latest stable libs/docs; if unsure, do a web search.
9
+ ## Codex behaviour
10
+ - If files change unexpectedly, assume parallel edits and continue; keep your diff scoped. Stop only for conflicts/breakage, then ask the user.
11
+ - When web searching, prefer 2026 (latest) sources/docs unless an older version is explicitly needed.
2
12
 
3
- ## File Operations
4
- - Find files by file name: `fd`
5
- - Find files with path name: `fd -p <file-path>`
6
- - List files in a directory: `fd . <directory>`
7
- - Find files with extension and pattern: `fd -e <extension> <pattern>`
13
+ ## Codex Prompts & Skills
14
+ - Skills live in repo `.codex/skills` and global `~/.codex/skills`; if `$<myskill>` isn’t found locally, explicitly load `~/.codex/skills/<myskill>/SKILL.md` (plus any `references/`/`scripts/`).
15
+ - Prompts live in `~/.codex/prompts/*.md`
8
16
 
9
- ## Structured Code Search
10
- - Find code structure: `ast-grep --lang <language> -p '<pattern>'`
11
- - List matching files: `ast-grep --lang <language> -p '<pattern>' | head -n 10`
12
- - Prefer `ast-grep` over `rg`/`grep` when you need syntax-aware matching
17
+ ## Coding Style
18
+ - Target <=500 LOC (hard cap 750; imports/types excluded).
19
+ - Keep UI/markup nesting <=3 levels; extract components/helpers when JSX/templating repeats, responsibilities pile up, or variant/conditional switches grow.
13
20
 
14
- ## Data Processing
15
- - JSON: `jq`
16
- - YAML/XML: `yq`
21
+ ## Security guards
22
+ - No delete/move/overwrite without explicit user request; for deletions prefer `trash` over `rm`.
23
+ - Don’t expose secrets in code/logs; use env/secret stores.
24
+ - Validate/sanitize untrusted input to prevent injection, path traversal, SSRF, and unsafe uploads.
25
+ - Enforce AuthN/AuthZ and tenant boundaries; least privilege.
26
+ - Be cautious with new dependencies; flag supply-chain/CVE risk.
17
27
 
18
- ## Selection
19
- - Select from multiple results deterministically (non-interactive filtering)
20
- - Fuzzy finder: `fzf --filter 'term' | head -n 1`
28
+ ## Git operations
29
+ - Use `gh` CLI for GitHub operations (issues/PRs/releases).
30
+ - Ask before any `git push`.
31
+ - Prefer Conventional Commits (`feat:`, `fix:`, `docs:`, `refactor:`, etc.).
21
32
 
22
- ## Guidelines
23
- - Prefer deterministic, non-interactive commands (`head`, `--filter`, `--json` + `jq`) so runs are reproducible
24
- ?
33
+ ## Pull requests
34
+ - Keep PRs short and structured: **Why** (1–2 bullets), **How** (1–3 bullets), **Tests** (commands run + results).
35
+ - Create/manage PRs via `gh pr ...`.
36
+ - Avoid noise (logs/dumps); include only key context, risks, and screenshots when UX changes.
37
+
38
+ ## When using the shell:
39
+ - Prefer built-in tools (e.g. `read_file`/`list_dir`/`grep_files`) over ad-hoc shell plumbing when available.
40
+ - For shell-based search: `fd` (files), `rg` (text), `ast-grep` (syntax-aware), `jq`/`yq` (extract/transform).
41
+ - Keep it deterministic and non-interactive; limit output (e.g. `head`) and pick a single result consistently.
@@ -42,7 +42,7 @@ approval_policy = "on-request"
42
42
  sandbox_mode = "workspace-write"
43
43
  model = "gpt-5.2-codex"
44
44
  model_reasoning_effort = "medium"
45
- model_reasoning_summary = "concise"
45
+ model_reasoning_summary = "detailed"
46
46
  [profiles.balanced.features]
47
47
  web_search_request = true
48
48
 
@@ -51,7 +51,7 @@ approval_policy = "on-failure"
51
51
  sandbox_mode = "read-only"
52
52
  model = "gpt-5.2-codex"
53
53
  model_reasoning_effort = "medium"
54
- model_reasoning_summary = "concise"
54
+ model_reasoning_summary = "detailed"
55
55
  [profiles.safe.features]
56
56
  web_search_request = false
57
57