{"_id":"@0xtiby/spawner","_rev":"8-44e895f92b082b20db471b1dd6ffc83e","name":"@0xtiby/spawner","dist-tags":{"latest":"1.3.1"},"versions":{"0.0.1":{"name":"@0xtiby/spawner","version":"0.0.1","author":{"name":"0xtiby"},"license":"MIT","_id":"@0xtiby/spawner@0.0.1","maintainers":[{"name":"0xtiby","email":"rekt2591@gmail.com"}],"homepage":"https://github.com/0xtiby/spawner#readme","bugs":{"url":"https://github.com/0xtiby/spawner/issues"},"dist":{"shasum":"3bd2bdb9ecb4c0230af0c52f22645fd2e2c59cf7","tarball":"https://registry.npmjs.org/@0xtiby/spawner/-/spawner-0.0.1.tgz","fileCount":7,"integrity":"sha512-7TtXnCH8q0W/wMldT/7mAu7ohIHY37mJtXi1ukQC5ro4oUflCCngeBD/IF2ixPuigCaR6nOLTEWtZB4Cixm5ZA==","signatures":[{"sig":"MEYCIQC5FfjhLneBxm9GSzwb0GHlN33OiWiFxm7FrgqgdmpFZAIhALlq3i617eHUTfSaYXg0jQyyCiqpZ5hO6O8vmavtJx5h","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":80719},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"b4791b099e20d49f5fc9e4c2f86e0d5dfd3d5d52","scripts":{"lint":"tsc --noEmit","test":"vitest run","build":"tsup","bootstrap":"bash scripts/bootstrap.sh","setup:branch-protection":"bash scripts/setup-branch-protection.sh"},"_npmUser":{"name":"0xtiby","email":"rekt2591@gmail.com"},"repository":{"url":"git+https://github.com/0xtiby/spawner.git","type":"git"},"_npmVersion":"10.8.2","description":"> A unified TypeScript interface to spawn and interact with AI coding CLIs.","directories":{},"_nodeVersion":"20.18.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.0","tsup":"^8.4.0","vitest":"^3.1.0","typescript":"^5.8.0","@types/node":"^25.5.0","semantic-release":"^24.2.3","@semantic-release/git":"^10.0.1","@semantic-release/npm":"^12.0.1","@semantic-release/github":"^11.0.1","@semantic-release/changelog":"^6.0.3","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.0.3"},"_npmOperationalInternal":{"tmp":"tmp/spawner_0.0.1_1773860822829_0.3672534230451774","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@0xtiby/spawner","version":"1.0.1","author":{"name":"0xtiby"},"license":"MIT","_id":"@0xtiby/spawner@1.0.1","maintainers":[{"name":"0xtiby","email":"rekt2591@gmail.com"}],"homepage":"https://github.com/0xtiby/spawner#readme","bugs":{"url":"https://github.com/0xtiby/spawner/issues"},"dist":{"shasum":"62896c04521341b7a69c4a0afd74ecc9f651a59c","tarball":"https://registry.npmjs.org/@0xtiby/spawner/-/spawner-1.0.1.tgz","fileCount":7,"integrity":"sha512-GeF5aJmDlFvSjiDoraNNqo4570FNI6QC1hYKlVMEmfvLsvSjsizDF19dZVqHGPghGdg4KahDqUaVX3/wMSFPgg==","signatures":[{"sig":"MEUCIQDoNp4c4Ahk0sAfVsMYx/ZJWiK4dKrvGXmoxHp3wpFK+wIgAvSpZ4Sjsdf7vqFOEij2T5IwUspb0A9ninZYLiLQ/hs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@0xtiby%2fspawner@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":80478},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"97041c4d1855790141d95cf0a3469c57d329cc88","scripts":{"lint":"tsc --noEmit","test":"vitest run","build":"tsup","bootstrap":"bash scripts/bootstrap.sh","setup:branch-protection":"bash scripts/setup-branch-protection.sh"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:9ac3a7ed-835d-4d93-a8da-1bef50b1ea51"}},"repository":{"url":"git+https://github.com/0xtiby/spawner.git","type":"git"},"_npmVersion":"11.12.0","description":"> A unified TypeScript interface to spawn and interact with AI coding CLIs.","directories":{},"_nodeVersion":"22.22.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@9.15.4","devDependencies":{"tsx":"^4.19.0","tsup":"^8.4.0","vitest":"^3.1.0","typescript":"^5.8.0","@types/node":"^25.5.0","semantic-release":"^25.0.2"},"_npmOperationalInternal":{"tmp":"tmp/spawner_1.0.1_1773902804272_0.8873994205433999","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@0xtiby/spawner","version":"1.0.2","author":{"name":"0xtiby"},"license":"MIT","_id":"@0xtiby/spawner@1.0.2","maintainers":[{"name":"0xtiby","email":"rekt2591@gmail.com"}],"homepage":"https://github.com/0xtiby/spawner#readme","bugs":{"url":"https://github.com/0xtiby/spawner/issues"},"dist":{"shasum":"878913394223479a80a46523ac983fd36aed8119","tarball":"https://registry.npmjs.org/@0xtiby/spawner/-/spawner-1.0.2.tgz","fileCount":7,"integrity":"sha512-6XhpjZLDSlunLU10JxE+FtazPT9uV6zggiG/G3FyxQP7X+EqqwUAinO4zMp1F0oP/p2s2NW9lVVE7/dt/4fDJA==","signatures":[{"sig":"MEUCIQCU+S0DQ+Sr2LqW40kZmr52CwoWLje0+p0eGVOq/wZgUAIgWPc2oSuDP6X+J//M4ACbkFOwK1cdehwkOZC+kgt1d1Q=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@0xtiby%2fspawner@1.0.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":80735},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"23059fe2d8e3b48457e3d98484ae7be5dee9f604","scripts":{"lint":"tsc --noEmit","test":"vitest run","build":"tsup","bootstrap":"bash scripts/bootstrap.sh","setup:branch-protection":"bash scripts/setup-branch-protection.sh"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:9ac3a7ed-835d-4d93-a8da-1bef50b1ea51"}},"repository":{"url":"git+https://github.com/0xtiby/spawner.git","type":"git"},"_npmVersion":"11.12.0","description":"> A unified TypeScript interface to spawn and interact with AI coding CLIs.","directories":{},"_nodeVersion":"22.22.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@9.15.4","devDependencies":{"tsx":"^4.19.0","tsup":"^8.4.0","vitest":"^3.1.0","typescript":"^5.8.0","@types/node":"^25.5.0","semantic-release":"^25.0.2"},"_npmOperationalInternal":{"tmp":"tmp/spawner_1.0.2_1773904419522_0.3798481841106993","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@0xtiby/spawner","version":"1.1.0","author":{"name":"0xtiby"},"license":"MIT","_id":"@0xtiby/spawner@1.1.0","maintainers":[{"name":"0xtiby","email":"rekt2591@gmail.com"}],"homepage":"https://github.com/0xtiby/spawner#readme","bugs":{"url":"https://github.com/0xtiby/spawner/issues"},"dist":{"shasum":"0da053134893b963e0c60b02599add27a1af4da6","tarball":"https://registry.npmjs.org/@0xtiby/spawner/-/spawner-1.1.0.tgz","fileCount":7,"integrity":"sha512-5w26Mu0E2Lr48aX2Md2PsAkF4bXbXPDzS2PFWaUGR/bum1MhL0CCxfXDGDJNJRr8dwNE4gChdkVtwjSFit33gA==","signatures":[{"sig":"MEQCIEzR+/EE01HhVV9FP/OcjR/InWdMq9qNvagpA2xMLGDCAiBiTmcHzlScrVmjyjydOixAtNS3NpKWbnjC5A7nKDRHvQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@0xtiby%2fspawner@1.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":89010},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"cbc162e2ec91b5487372f4db801e31213b099964","scripts":{"lint":"tsc --noEmit","test":"vitest run","build":"tsup","bootstrap":"bash scripts/bootstrap.sh","setup:branch-protection":"bash scripts/setup-branch-protection.sh"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:9ac3a7ed-835d-4d93-a8da-1bef50b1ea51"}},"repository":{"url":"git+https://github.com/0xtiby/spawner.git","type":"git"},"_npmVersion":"11.12.0","description":"> A unified TypeScript interface to spawn and interact with AI coding CLIs.","directories":{},"_nodeVersion":"22.22.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@9.15.4","devDependencies":{"tsx":"^4.19.0","tsup":"^8.4.0","vitest":"^3.1.0","typescript":"^5.8.0","@types/node":"^25.5.0","semantic-release":"^25.0.2"},"_npmOperationalInternal":{"tmp":"tmp/spawner_1.1.0_1774428406755_0.35867434613927496","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@0xtiby/spawner","version":"1.2.0","author":{"name":"0xtiby"},"license":"MIT","_id":"@0xtiby/spawner@1.2.0","maintainers":[{"name":"0xtiby","email":"rekt2591@gmail.com"}],"homepage":"https://github.com/0xtiby/spawner#readme","bugs":{"url":"https://github.com/0xtiby/spawner/issues"},"dist":{"shasum":"52a5697dcf2f19b726e2d2f1b5b46c4b0b82e19f","tarball":"https://registry.npmjs.org/@0xtiby/spawner/-/spawner-1.2.0.tgz","fileCount":7,"integrity":"sha512-kI1A4yAo7ySjgcBy6Wi+3ogSLd566179iAzS5fLwJ/bGSMPxP8DFN1yWjUREftgvYR8ixCNYA0cs/nl5YWUxMw==","signatures":[{"sig":"MEUCIQCz8Au2tYZmTuzKOIwYNKMevNae4zL+EajQqLI6pQrxOAIgeLoa6zadpWCcw0q0/DXM+MJKFn+PZKKSg3XyTZFOc2g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@0xtiby%2fspawner@1.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":96720},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"82e4cae47a905bcd70195f622166c3c56e3263f0","scripts":{"lint":"tsc --noEmit","test":"vitest run","build":"tsup","bootstrap":"bash scripts/bootstrap.sh","setup:branch-protection":"bash scripts/setup-branch-protection.sh"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:9ac3a7ed-835d-4d93-a8da-1bef50b1ea51"}},"repository":{"url":"git+https://github.com/0xtiby/spawner.git","type":"git"},"_npmVersion":"11.12.0","description":"> A unified TypeScript interface to spawn and interact with AI coding CLIs.","directories":{},"_nodeVersion":"22.22.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@9.15.4","devDependencies":{"tsx":"^4.19.0","tsup":"^8.4.0","vitest":"^3.1.0","typescript":"^5.8.0","@types/node":"^25.5.0","semantic-release":"^25.0.2"},"_npmOperationalInternal":{"tmp":"tmp/spawner_1.2.0_1774510999706_0.22526035473457284","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"@0xtiby/spawner","version":"1.2.1","author":{"name":"0xtiby"},"license":"MIT","_id":"@0xtiby/spawner@1.2.1","maintainers":[{"name":"0xtiby","email":"rekt2591@gmail.com"}],"homepage":"https://github.com/0xtiby/spawner#readme","bugs":{"url":"https://github.com/0xtiby/spawner/issues"},"dist":{"shasum":"48f5d787faab86ad55b053d1478dc7a79f0bbf86","tarball":"https://registry.npmjs.org/@0xtiby/spawner/-/spawner-1.2.1.tgz","fileCount":7,"integrity":"sha512-Ro94MjbBAEt6NrBEoqsEyQupGS/jjxQXwycjrJMwLyuF4wfafN3I0x2gMtaISvayEfyUNqToZxmp76nq+J2hiA==","signatures":[{"sig":"MEQCICQWX0bPgnuT3ftQXfvtsRTfqj1bb+L//Y1nVCsC//peAiB3srhhqdfxo2eBYetUA4k0IuB5FsDsoFz+EcBzSETsLw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@0xtiby%2fspawner@1.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":99455},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"0b3d0f1d8c91a259616cf208ecc125a7ddd09166","scripts":{"e2e":"vitest run --config vitest.e2e.config.ts","lint":"tsc --noEmit","test":"vitest run","build":"tsup","bootstrap":"bash scripts/bootstrap.sh","setup:branch-protection":"bash scripts/setup-branch-protection.sh"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:9ac3a7ed-835d-4d93-a8da-1bef50b1ea51"}},"repository":{"url":"git+https://github.com/0xtiby/spawner.git","type":"git"},"_npmVersion":"11.12.1","description":"> A unified TypeScript interface to spawn and interact with AI coding CLIs.","directories":{},"_nodeVersion":"22.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@9.15.4","devDependencies":{"tsx":"^4.19.0","tsup":"^8.4.0","vitest":"^3.1.0","typescript":"^5.8.0","@types/node":"^25.5.0","semantic-release":"^25.0.2"},"_npmOperationalInternal":{"tmp":"tmp/spawner_1.2.1_1776372911225_0.4881944159244358","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@0xtiby/spawner","version":"1.3.0","author":{"name":"0xtiby"},"license":"MIT","_id":"@0xtiby/spawner@1.3.0","maintainers":[{"name":"0xtiby","email":"rekt2591@gmail.com"}],"homepage":"https://github.com/0xtiby/spawner#readme","bugs":{"url":"https://github.com/0xtiby/spawner/issues"},"dist":{"shasum":"17294cf90d0ac4f4ad50a732bb8264bfb10090d7","tarball":"https://registry.npmjs.org/@0xtiby/spawner/-/spawner-1.3.0.tgz","fileCount":7,"integrity":"sha512-1mCc1oYs3J7xLvx/Iiy8ZGsqPou+d/q6FLcdQsk58Bpl8TJ/MSM9icVP1JV9fB7GPLbxhJjgxdcCQbYFC62j7g==","signatures":[{"sig":"MEUCIGvjJ2NlTqM30F/Qe7s+Abs/OoPjixE2mcT0yUzEFHXZAiEA2f3jF19FeGpMu2mxhT8EWH0oaUdYz2H8z19R9AuxQzE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@0xtiby%2fspawner@1.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":118292},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"f2a1aaf1e2b363debc075b7a5667d2432812ec25","scripts":{"e2e":"vitest run --config vitest.e2e.config.ts","lint":"tsc --noEmit","test":"vitest run","build":"tsup","bootstrap":"bash scripts/bootstrap.sh","setup:branch-protection":"bash scripts/setup-branch-protection.sh"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:9ac3a7ed-835d-4d93-a8da-1bef50b1ea51"}},"repository":{"url":"git+https://github.com/0xtiby/spawner.git","type":"git"},"_npmVersion":"11.13.0","description":"<div align=\"center\">   <picture>     <source media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/spawner-logo-dark.png\">     <source media=\"(prefers-color-scheme: light)\" srcset=\"./assets/spawner-logo-light.png\">     <img alt=\"spawner\" src=\"./assets/spa","directories":{},"_nodeVersion":"22.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@9.15.4","devDependencies":{"tsx":"^4.19.0","tsup":"^8.4.0","vitest":"^3.1.0","typescript":"^5.8.0","@types/node":"^25.5.0","semantic-release":"^25.0.2"},"_npmOperationalInternal":{"tmp":"tmp/spawner_1.3.0_1777376511046_0.4481303673414223","host":"s3://npm-registry-packages-npm-production"}},"1.3.1":{"name":"@0xtiby/spawner","version":"1.3.1","packageManager":"pnpm@9.15.4","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/0xtiby/spawner.git"},"bugs":{"url":"https://github.com/0xtiby/spawner/issues"},"homepage":"https://github.com/0xtiby/spawner#readme","author":{"name":"0xtiby"},"license":"MIT","scripts":{"build":"tsup","lint":"tsc --noEmit","test":"vitest run","e2e":"vitest run --config vitest.e2e.config.ts","bootstrap":"bash scripts/bootstrap.sh","setup:branch-protection":"bash scripts/setup-branch-protection.sh"},"devDependencies":{"@types/node":"^25.5.0","semantic-release":"^25.0.2","tsup":"^8.4.0","tsx":"^4.19.0","typescript":"^5.8.0","vitest":"^3.1.0"},"gitHead":"d2abacee682ccaee91c1f3902bf8c719f86041cf","_id":"@0xtiby/spawner@1.3.1","description":"<div align=\"center\">   <picture>     <source media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/spawner-logo-dark.png\">     <source media=\"(prefers-color-scheme: light)\" srcset=\"./assets/spawner-logo-light.png\">     <img alt=\"spawner\" src=\"./assets/spa","_nodeVersion":"22.14.0","_npmVersion":"11.14.0","dist":{"integrity":"sha512-3xfpgujCS319dX1+4rA3cCQIETG9uqGxD+pCD9Yv6nGVUAtqOD34de0dbr1kiv1gEZUeMTSR625toe/7nCGkmA==","shasum":"09ea04bd72f5cd6e62d51bbef9c52f2d116efa35","tarball":"https://registry.npmjs.org/@0xtiby/spawner/-/spawner-1.3.1.tgz","fileCount":7,"unpackedSize":119214,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@0xtiby%2fspawner@1.3.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICmN/+BVNJc7NRVdUnMFQFKLK1ypHstXZ4wgmFSLlRbyAiEAicf5MKx0dQUu6e4G2X92v5YS357uCVG47Yai9icypXQ="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:9ac3a7ed-835d-4d93-a8da-1bef50b1ea51"}},"directories":{},"maintainers":[{"name":"0xtiby","email":"rekt2591@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/spawner_1.3.1_1778182284502_0.8108860493933345"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-18T19:07:02.312Z","modified":"2026-05-07T19:31:25.008Z","0.0.1":"2026-03-18T19:07:02.992Z","1.0.1":"2026-03-19T06:46:44.419Z","1.0.2":"2026-03-19T07:13:39.658Z","1.1.0":"2026-03-25T08:46:46.908Z","1.2.0":"2026-03-26T07:43:19.849Z","1.2.1":"2026-04-16T20:55:11.366Z","1.3.0":"2026-04-28T11:41:51.186Z","1.3.1":"2026-05-07T19:31:24.661Z"},"bugs":{"url":"https://github.com/0xtiby/spawner/issues"},"author":{"name":"0xtiby"},"license":"MIT","homepage":"https://github.com/0xtiby/spawner#readme","repository":{"type":"git","url":"git+https://github.com/0xtiby/spawner.git"},"description":"<div align=\"center\">   <picture>     <source media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/spawner-logo-dark.png\">     <source media=\"(prefers-color-scheme: light)\" srcset=\"./assets/spawner-logo-light.png\">     <img alt=\"spawner\" src=\"./assets/spa","maintainers":[{"name":"0xtiby","email":"rekt2591@gmail.com"}],"readme":"<div align=\"center\">\n  <picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/spawner-logo-dark.png\">\n    <source media=\"(prefers-color-scheme: light)\" srcset=\"./assets/spawner-logo-light.png\">\n    <img alt=\"spawner\" src=\"./assets/spawner-logo-light.png\" height=\"140\" style=\"margin-bottom: 20px;\">\n  </picture>\n</div>\n\n<p align=\"center\">A unified TypeScript interface to spawn and interact with AI coding CLIs.</p>\n\n<p align=\"center\">\n  <a href=\"https://www.npmjs.com/package/@0xtiby/spawner\"><img src=\"https://img.shields.io/npm/v/@0xtiby/spawner\" alt=\"npm version\"></a>\n  <a href=\"./LICENSE\"><img src=\"https://img.shields.io/npm/l/@0xtiby/spawner\" alt=\"license\"></a>\n  <a href=\"https://nodejs.org\"><img src=\"https://img.shields.io/node/v/@0xtiby/spawner\" alt=\"node engine\"></a>\n  <a href=\"https://github.com/0xtiby/spawner/actions/workflows/release.yml\"><img src=\"https://github.com/0xtiby/spawner/actions/workflows/release.yml/badge.svg\" alt=\"CI status\"></a>\n</p>\n\n## What Is Spawner?\n\nA single async iterable API to drive **Claude Code**, **Codex CLI**, **OpenCode**, and **pi** programmatically:\n\n1. You pass `SpawnOptions` to `spawn()`.\n2. You iterate typed `CliEvent` objects as they stream in (text, tool use, tool result, errors).\n3. You get back a structured `CliResult` -- same shape regardless of which CLI you chose.\n\nIt handles process spawning, JSONL stream parsing, session management, error classification, and CLI detection so you can build orchestrators, CI pipelines, and editor integrations without writing per-CLI adapters.\n\n**ESM only. Zero runtime dependencies. TypeScript-first.**\n\n> Used by [**looper**](https://github.com/0xtiby/looper) as its CLI driver.\n\n## Quick Start\n\n```typescript\nimport { spawn } from '@0xtiby/spawner';\n\nconst proc = spawn({\n  cli: 'claude',\n  prompt: 'Refactor the utils module to use named exports',\n  cwd: '/path/to/project',\n});\n\nfor await (const event of proc.events) {\n  switch (event.type) {\n    case 'text':\n      console.log(event.content);\n      break;\n    case 'tool_use':\n      console.log(`Using tool: ${event.tool?.name}`);\n      break;\n    case 'error':\n      console.error(event.content);\n      break;\n    case 'done':\n      console.log('Session:', event.result?.sessionId);\n      console.log('Tokens:', event.result?.usage?.totalTokens);\n      break;\n  }\n}\n```\n\n## Installation\n\n```bash\npnpm add @0xtiby/spawner\n# or: npm install @0xtiby/spawner\n```\n\n**Prerequisites**: Node.js 18+ and at least one supported CLI installed and authenticated:\n\n- [Claude Code](https://docs.anthropic.com/en/docs/claude-code) (`claude`)\n- [Codex CLI](https://github.com/openai/codex) (`codex`)\n- [OpenCode](https://github.com/sst/opencode) (`opencode`)\n- [pi](https://github.com/badlogic/pi-mono) (`pi`)\n\n## CLI Feature Parity\n\nNot every CLI supports every `SpawnOptions` field. This table shows what each adapter passes through and what it silently ignores.\n\n| Feature | Claude | Codex | OpenCode | pi |\n|---|---|---|---|---|\n| `model` | Yes | Yes | Yes | Yes |\n| `sessionId` | Yes | Yes | Yes | Yes |\n| `continueSession` | Yes | Yes | Yes | Yes |\n| `forkSession` | Yes | Yes | Yes | Yes |\n| `autoApprove` | Yes | Yes | -- | No-op |\n| `effort` | Yes | Yes | -- | Yes |\n| `addDirs` | Yes | Yes | -- | -- |\n| `ephemeral` | Yes | Yes | -- | Yes |\n| `allowInteractiveTools` | Yes | -- | -- | -- |\n| `extraArgs` | Yes | Yes | Yes | Yes |\n\n**Legend:** \"Yes\" = passed to the CLI. \"--\" = silently ignored. \"No-op\" = accepted but has no effect (the CLI is already non-interactive).\n\n### Pi-specific notes\n\n- `autoApprove` is a no-op: `pi --mode json` is already a headless print mode with no approval prompts.\n- `addDirs` and `allowInteractiveTools` are silently ignored so existing `SpawnOptions` work without crashing.\n- `effort` is mapped to `--thinking <level>`. Pi accepts `off`, `minimal`, `low`, `medium`, `high`, `xhigh` natively, so all values pass through; `max` collapses to `xhigh`.\n- `detect()` reports `authenticated: true` whenever the `pi` binary exists. Pi resolves credentials per provider at runtime (env vars, config file), so this signal is non-authoritative — real auth failures surface via `classifyError` when you actually spawn.\n\n## Core Concepts\n\n### Streaming Events\n\n`spawn()` returns a `CliProcess` whose `events` property is an `AsyncIterable<CliEvent>`. Each event carries a `type` field that tells you what happened. Iterate with `for await...of` to process events as they stream in.\n\n| Type | When It Fires | Key Fields |\n|---|---|---|\n| `text` | The CLI emits a chunk of assistant text | `content` |\n| `tool_use` | The CLI invokes a tool | `tool.name`, `tool.input` |\n| `tool_result` | A tool call completes | `toolResult.name`, `toolResult.output`, `toolResult.error` |\n| `error` | The CLI reports an inline error | `content` |\n| `system` | Internal lifecycle signals (session start, step boundaries) | `content` |\n| `done` | The process exits | `result` (contains `CliResult`) |\n\nEvery event also includes `timestamp` (Unix ms) and `raw` (the original JSONL line).\n\n### Session Management\n\nUse these `SpawnOptions` fields to control session behavior:\n\n| Goal | Options to Set |\n|---|---|\n| Start a new session | *(none -- this is the default)* |\n| Resume a session by ID | `sessionId: '<id>'` |\n| Resume the most recent session | `continueSession: true` |\n| Fork from a specific session | `sessionId: '<id>'`, `forkSession: true` |\n| Fork from the most recent session | `continueSession: true`, `forkSession: true` |\n\n`forkSession` is additive -- it only takes effect when you also set `sessionId` or `continueSession`. A fork creates a new session branched from the specified point, leaving the original session unchanged.\n\n### Error Classification\n\nWhen a CLI process exits with a non-zero code, spawner runs the output through `classifyError()` and attaches a structured `CliError` to the result. Each error has a `code`, a human-readable `message`, a `retryable` flag, and an optional `retryAfterMs` hint. You can use the `retryable` flag to build automatic retry logic. See the [Error Codes](#error-codes) section for the full list.\n\n## Usage\n\n### Spawn a Process\n\n`spawn()` is the main entry point. It returns a `CliProcess` with an async iterable of events and a promise that resolves when the process exits.\n\n```typescript\nimport { spawn } from '@0xtiby/spawner';\n\nconst proc = spawn({\n  cli: 'codex',\n  prompt: 'Add input validation to the signup handler',\n  cwd: '/path/to/repo',\n  model: 'o4-mini',\n  autoApprove: true,\n});\n\n// Stream events as they arrive\nfor await (const event of proc.events) {\n  if (event.type === 'text') {\n    process.stdout.write(event.content ?? '');\n  }\n}\n\n// Or just await the final result\nconst result = await proc.done;\n```\n\n### Resume or Fork a Session\n\nPass `sessionId` to continue a previous conversation, or combine it with `forkSession` to branch off:\n\n```typescript\n// Resume an existing session\nconst proc = spawn({\n  cli: 'claude',\n  prompt: 'Now add tests for the changes you just made',\n  cwd: '/path/to/repo',\n  sessionId: previousResult.sessionId!,\n});\n\n// Fork from an existing session (creates a new branch)\nconst forked = spawn({\n  cli: 'claude',\n  prompt: 'Try a different approach to the refactor',\n  cwd: '/path/to/repo',\n  sessionId: previousResult.sessionId!,\n  forkSession: true,\n});\n\n// Resume the most recent session (no ID needed)\nconst continued = spawn({\n  cli: 'claude',\n  prompt: 'What was I working on?',\n  cwd: '/path/to/repo',\n  continueSession: true,\n});\n```\n\n### Cancel or Interrupt\n\nUse `AbortSignal` for external cancellation, or call `interrupt()` for a graceful shutdown:\n\n```typescript\nconst controller = new AbortController();\n\nconst proc = spawn({\n  cli: 'claude',\n  prompt: 'Perform a large refactor',\n  cwd: '/path/to/repo',\n  abortSignal: controller.signal,\n});\n\n// Cancel after 30 seconds\nsetTimeout(() => controller.abort(), 30_000);\n\n// Or interrupt gracefully (SIGTERM, then SIGKILL after grace period)\nconst result = await proc.interrupt(5000); // 5s grace period (default)\n```\n\n### Detect Installed CLIs\n\n```typescript\nimport { detect, detectAll } from '@0xtiby/spawner';\n\n// Check a single CLI\nconst claude = await detect('claude');\n// { installed: true, version: '1.2.3', authenticated: true, binaryPath: '/usr/local/bin/claude' }\n\n// Check all CLIs concurrently\nconst all = await detectAll();\n// { claude: DetectResult, codex: DetectResult, opencode: DetectResult }\n```\n\n### Extract Results from Raw Output\n\nIf you have captured JSONL output from a previous CLI run, parse it without spawning a process:\n\n```typescript\nimport { extract } from '@0xtiby/spawner';\n\nconst result = extract({\n  cli: 'claude',\n  rawOutput: capturedJsonlString,\n});\n\nconsole.log(result.sessionId);\nconsole.log(result.usage);\n```\n\n### Query the Model Registry\n\nModels are fetched dynamically from [models.dev](https://models.dev) and cached for 24 hours.\n\n```typescript\nimport { listModels, getKnownModels, refreshModels } from '@0xtiby/spawner';\n\n// All models from all providers\nconst all = await listModels();\n\n// Models for a specific CLI\nconst claudeModels = await getKnownModels('claude');\n\n// Filter by provider\nconst openaiModels = await listModels({ provider: 'openai' });\n\n// With offline fallback\nconst models = await listModels({\n  cli: 'claude',\n  fallback: [{ id: 'claude-sonnet-4-20250514', name: 'Claude Sonnet 4', provider: 'anthropic', contextWindow: 200_000, supportsEffort: true }],\n});\n\n// Force-refresh the cache\nawait refreshModels();\n```\n\n## API Reference\n\n### `spawn(options: SpawnOptions): CliProcess`\n\nSpawns a CLI process and returns a handle for streaming events and awaiting the result.\n\n#### `SpawnOptions`\n\n| Option | Type | Default | Description |\n|---|---|---|---|\n| `cli` | `CliName` | *required* | Which CLI to spawn: `'claude'`, `'codex'`, `'opencode'`, or `'pi'` |\n| `prompt` | `string` | *required* | The prompt to send to the CLI |\n| `cwd` | `string` | *required* | Working directory for the process |\n| `model` | `string` | CLI default | Model identifier to use |\n| `sessionId` | `string` | -- | Resume an existing session |\n| `effort` | `'off' \\| 'minimal' \\| 'low' \\| 'medium' \\| 'high' \\| 'max' \\| 'xhigh'` | -- | Effort/reasoning level (supported by some models) |\n| `autoApprove` | `boolean` | -- | Skip tool confirmation prompts. Maps to full permission/sandbox bypass on claude (`--dangerously-skip-permissions`) and codex (`--dangerously-bypass-approvals-and-sandbox`). No effect on opencode. |\n| `forkSession` | `boolean` | -- | Fork from an existing session |\n| `continueSession` | `boolean` | -- | Continue the most recent session |\n| `addDirs` | `string[]` | -- | Additional directories to include |\n| `ephemeral` | `boolean` | -- | Run without persisting session |\n| `verbose` | `boolean` | -- | Enable debug logging to stderr |\n| `allowInteractiveTools` | `boolean` | -- | Allow tools that prompt the user for input (Claude only) |\n| `abortSignal` | `AbortSignal` | -- | Signal to abort the process |\n| `extraArgs` | `string[]` | -- | Additional CLI arguments passed through |\n\n#### `CliProcess`\n\n| Property / Method | Type | Description |\n|---|---|---|\n| `events` | `AsyncIterable<CliEvent>` | Stream of parsed events |\n| `pid` | `number` | OS process ID |\n| `interrupt(graceMs?)` | `(graceMs?: number) => Promise<CliResult>` | Gracefully stop the process (SIGTERM, then SIGKILL after `graceMs`) |\n| `done` | `Promise<CliResult>` | Resolves when the process exits |\n\n#### `CliEvent`\n\n| Field | Type | Description |\n|---|---|---|\n| `type` | `CliEventType` | `'text'`, `'tool_use'`, `'tool_result'`, `'error'`, `'system'`, or `'done'` |\n| `timestamp` | `number` | Unix timestamp (ms) |\n| `content` | `string?` | Text content (for `text`, `error`, `system` events) |\n| `tool` | `{ name: string; input?: Record<string, unknown> }?` | Tool invocation details (for `tool_use` events) |\n| `toolResult` | `{ name: string; output?: string; error?: string }?` | Tool result (for `tool_result` events) |\n| `result` | `CliResult?` | Final result (only on `done` events) |\n| `raw` | `string` | Original JSONL line |\n\n#### `CliResult`\n\n| Field | Type | Description |\n|---|---|---|\n| `exitCode` | `number` | Process exit code |\n| `sessionId` | `string \\| null` | Session ID for resumption |\n| `usage` | `TokenUsage \\| null` | Token usage and cost |\n| `model` | `string \\| null` | Model that was used |\n| `error` | `CliError \\| null` | Structured error (if non-zero exit) |\n| `durationMs` | `number` | Wall-clock duration in milliseconds |\n\n#### `TokenUsage`\n\n| Field | Type |\n|---|---|\n| `inputTokens` | `number \\| null` |\n| `outputTokens` | `number \\| null` |\n| `totalTokens` | `number \\| null` |\n| `cost` | `number \\| null` |\n\n### `detect(cli: CliName): Promise<DetectResult>`\n\nChecks whether a CLI is installed, its version, and authentication status.\n\n### `detectAll(): Promise<Record<CliName, DetectResult>>`\n\nRuns `detect()` for all four CLIs concurrently.\n\n### `extract(options: ExtractOptions): CliResult`\n\nParses captured JSONL output into a `CliResult` without spawning a process. Useful for processing saved output or testing.\n\n### `classifyError(cli, exitCode, stderr, stdout): CliError`\n\nClassifies raw process output into a structured `CliError` using CLI-specific adapters.\n\n### `classifyErrorDefault(exitCode, stderr, stdout): CliError`\n\nDefault error classifier using shared pattern matching. Useful for building custom adapters.\n\n### `matchSharedPatterns(stderr, stdout)`\n\nLow-level pattern matching against the shared error pattern table. Returns `{ code, retryable, matchedLine }` or `null`.\n\n### `parseRetryAfterMs(text): number`\n\nExtracts a retry-after duration (in ms) from error text. Returns `60000` as a default fallback.\n\n### `listModels(options?: ListModelsOptions): Promise<KnownModel[]>`\n\nReturns models fetched from models.dev, filtered by CLI and/or provider. Results are sorted alphabetically by `id`. When both `cli` and `provider` are set, `provider` takes precedence.\n\n### `getKnownModels(cli?: CliName, fallback?: KnownModel[]): Promise<KnownModel[]>`\n\nConvenience wrapper over `listModels()`. Returns models optionally filtered by CLI, with optional fallback on fetch failure.\n\n### `refreshModels(): Promise<void>`\n\nForce-refreshes the in-memory model cache from models.dev. On failure, the existing cache is preserved.\n\n## Error Codes\n\nSpawner classifies CLI errors into typed error codes so you can handle them programmatically:\n\n| Error Code | Retryable | Description |\n|---|---|---|\n| `rate_limit` | Yes | Rate limited or overloaded -- check `retryAfterMs` |\n| `auth` | No | Not authenticated or invalid credentials |\n| `session_not_found` | No | Session ID does not exist |\n| `model_not_found` | No | Specified model is invalid |\n| `context_overflow` | No | Input exceeds model context window |\n| `permission_denied` | No | Tool use requires confirmation |\n| `binary_not_found` | No | CLI binary not found on PATH |\n| `fatal` | No | Non-recoverable process error |\n| `unknown` | No | Unrecognized error |\n\n### Retry Example\n\n```typescript\nimport { spawn, type CliResult } from '@0xtiby/spawner';\n\nasync function spawnWithRetry(options: Parameters<typeof spawn>[0], maxRetries = 3): Promise<CliResult> {\n  for (let attempt = 0; attempt <= maxRetries; attempt++) {\n    const proc = spawn(options);\n    const result = await proc.done;\n\n    if (!result.error?.retryable || attempt === maxRetries) {\n      return result;\n    }\n\n    const delay = result.error.retryAfterMs ?? 60_000;\n    console.log(`Rate limited, retrying in ${delay}ms (attempt ${attempt + 1}/${maxRetries})`);\n    await new Promise((r) => setTimeout(r, delay));\n  }\n\n  throw new Error('unreachable');\n}\n```\n\n## Models\n\nModels are fetched dynamically from [models.dev](https://models.dev) and cached in memory for 24 hours. There is no static model list -- call `listModels()` or `getKnownModels()` to get the current catalog. Use `refreshModels()` to force a cache refresh.\n\n## Architecture\n\nSpawner uses an **adapter pattern** to normalize differences between CLIs. Each CLI has an adapter that implements:\n\n- **`buildCommand()`** -- Translates `SpawnOptions` into binary name, arguments, and optional stdin\n- **`parseLine()`** -- Parses a JSONL line into normalized `CliEvent` objects\n- **`detect()`** -- Checks installation and authentication\n- **`classifyError()`** -- CLI-specific error classification with fallback to shared patterns\n\nThe `spawn()` function orchestrates the full lifecycle: adapter selection, child process spawning, readline-based stream parsing, event queuing via async iterable, accumulator tracking (session ID, token usage, model), and result construction on exit.\n\n## Examples\n\n### Interactive Chat TUI\n\n`examples/chat.ts` is a fully working terminal chat app built on spawner. It auto-detects installed CLIs, lets you pick one, then drops you into a streaming chat loop with session continuity.\n\n```bash\npnpm tsx examples/chat.ts\n```\n\nFeatures:\n- **CLI selection** -- detects installed CLIs, shows versions and auth status, prompts you to pick one\n- **Streaming responses** -- text streams to stdout in real-time with colored labels\n- **Tool-use indicators** -- shows which tools the CLI invokes during a response\n- **Session continuity** -- captures `sessionId` so follow-up messages continue the conversation\n- **Ctrl+C interrupt** -- interrupts a streaming response without killing the app\n- **Slash commands** -- `/exit` to quit, `/new` to start a fresh session with a different CLI\n- **Error handling** -- rate limits, auth failures, and CLI crashes are caught and displayed cleanly\n\n## Development\n\n```bash\n# Install dependencies\npnpm install\n\n# Build\npnpm build\n\n# Run tests (334 tests across 20 files)\npnpm test\n\n# Type-check without emitting\npnpm lint\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}