{"_id":"aicontainer","_rev":"34-a30edd2f04afa2ead44630d1b182053c","name":"aicontainer","dist-tags":{"latest":"0.9.1"},"versions":{"0.0.1":{"name":"aicontainer","version":"0.0.1","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.0.1","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"64da08658110b86b034e6eecaf46464f7f9bf970","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.0.1.tgz","fileCount":15,"integrity":"sha512-Qkyz/C06d0RUhy8+pv4+29f+B2eg2Tn5GL6jyGC1Uv9bQ5Se+CygnhfzYrtE2wFxmfdLJJ4sL8r6LEiddpdKmA==","signatures":[{"sig":"MEYCIQCghLEanrfCeLu166J2KHIyQdGgt65V0YLafwaEsOewrQIhAOm2aTRQaoRU43zIRKdhvsWTdGieFWwu3c5Nxagw4S1E","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":114926},"engines":{"node":">=18"},"gitHead":"e1a85fec8f7ca480e4dabbc78aac5f4164d34809","_npmUser":{"name":"stefanoginella","email":"stefano@stefanoginella.com"},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.12.1","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"26.0.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.0.1_1779463581566_0.641950678896962","host":"s3://npm-registry-packages-npm-production"}},"0.0.3":{"name":"aicontainer","version":"0.0.3","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.0.3","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"f749a88e8345ff2e68f1e14e12cc41229e1de547","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.0.3.tgz","fileCount":15,"integrity":"sha512-dPGDkH2y9jMD6zfhQDNDDozO0w/Jk1gQ5ArEQS5f/XpkrRY85+toaMLsyRQw6Sm4vLcqBN7ICQwDSABhHX5gtw==","signatures":[{"sig":"MEQCICZPsmlCuta6zo3dJmFeoyOw1B3ElIQQQDgMv/dWGYayAiAEllgLjupw5DVkNB2ONS4YMouj47kLo+cQeVfy7DqoqQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.0.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":114926},"engines":{"node":">=18"},"gitHead":"e5a9aa45cd7d10ab44fbac22143771a39503c040","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.15.0","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.0.3_1779464606291_0.5638582070346503","host":"s3://npm-registry-packages-npm-production"}},"0.0.4":{"name":"aicontainer","version":"0.0.4","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.0.4","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"f2bee706c2a841cedd791249cee7703d4517cc55","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.0.4.tgz","fileCount":15,"integrity":"sha512-in37cQE4RzAjow2cFz049lxWQ46QRDg0DY0OerHDdk4BF871ITA8FN903zmWTXRXih7DQaXLxBpaKV3wh/IWnQ==","signatures":[{"sig":"MEUCIQCguKRHk4d8tH9cQpwwBMTgJ/Uig2pWZrtOU6iORWyp7gIgKDjznQFuIgry0K9kJs79pbVSepg8OmAs2zPft1WV3Fk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.0.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":115138},"engines":{"node":">=18"},"gitHead":"d065c608135dff34e41fa6c58b85928aa3bf96fb","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.12.1","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.0.4_1779467552842_0.30008506953482494","host":"s3://npm-registry-packages-npm-production"}},"0.0.5":{"name":"aicontainer","version":"0.0.5","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.0.5","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"4f6d1b27c92ee71d07d7565878d07b484a514523","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.0.5.tgz","fileCount":15,"integrity":"sha512-yYNEXhcIbqA1u/YPzri1pE6mL8weNkgP7wIO19wXJQJ815/7a2eMjoODMBmfajcJm7T5lU5PGg/KCUf7CA+KYw==","signatures":[{"sig":"MEQCIBHTyOltQY4wXzeAC5fnm6LPtF7sfKTZ81CnZEeFlnDZAiAwtXbxqWXfu+JWjmfHjh50Uue+ylAT9wcHdEcpWT4ANw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.0.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":115468},"engines":{"node":">=18"},"gitHead":"92f02181a0707c2667e3d9bae60278914bb5fd01","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.12.1","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.0.5_1779475509034_0.37992186171766185","host":"s3://npm-registry-packages-npm-production"}},"0.0.6":{"name":"aicontainer","version":"0.0.6","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.0.6","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"ed55b3800fe3d8adb4b70c8e010889114236a586","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.0.6.tgz","fileCount":15,"integrity":"sha512-IkdnbBh98t97fwgx/2ZdrgJw9U9VH9ElkG/ZbszcfiEN9rcHs02Ydsmy9/b+JEwk9Is48eA2z/1L4in1efUxiw==","signatures":[{"sig":"MEUCIDfToGXJPdFGaM34cZUcyx+jAYU5P12yEYOryOQeCR5NAiEA8oyvBysYg60xcn6Ixf4kRB2AWZJkoG6ZwH2OwZo6EHQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.0.6","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":121508},"engines":{"node":">=18"},"gitHead":"4b3550cf3c793be0e3a7b89b21df745fd0f3a53e","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.12.1","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.0.6_1779702299667_0.8865430262627894","host":"s3://npm-registry-packages-npm-production"}},"0.0.7":{"name":"aicontainer","version":"0.0.7","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.0.7","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"d7dc09eb520ad47591aca5d884ab33e3e0dd9d77","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.0.7.tgz","fileCount":15,"integrity":"sha512-NNRXaDgBwsq8Dbb5H0uLVrMmEv4cM0exGNexoctKXmPgDjinUUm46mp9xv7bR5AIFUXvbf9cbtylb9EK8KtTNQ==","signatures":[{"sig":"MEUCIQCqXEYGum7P2DpBaejOiKppjadbKDSSmNwlwLDs9KsrewIge2scQWhqNlxNIzZE5NiBcn9zOWHiMMjsB9wWUJcoJsI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.0.7","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":127504},"engines":{"node":">=18"},"gitHead":"41f42858ee43bfa0c8abaf4d8f49428ad269d175","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.12.1","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.0.7_1779716478634_0.6646061404247992","host":"s3://npm-registry-packages-npm-production"}},"0.0.8":{"name":"aicontainer","version":"0.0.8","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.0.8","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"6c97c89f0b4b746ce6ec037189c9f0086ff37986","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.0.8.tgz","fileCount":16,"integrity":"sha512-NsLo5Us8/NjECF80cAGMuhSacd+ztlMgkr1OIDJjVResK41DmDPKD2ZmR80dSy4q+ZmQsgDP9kn8SaSd6nhqQA==","signatures":[{"sig":"MEQCIGX79m/khXURYivckilnDJ1sg5BOG+HvdYxIY68Few2JAiBk2pAUWOawyAF/RcxLO17/wVluD6CpsqbugEZmt8qSUQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.0.8","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":136967},"engines":{"node":">=18"},"gitHead":"0a092b44f135cd7d92054a617cc862b373be769f","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.12.1","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.0.8_1779727048446_0.3032053737094291","host":"s3://npm-registry-packages-npm-production"}},"0.0.9":{"name":"aicontainer","version":"0.0.9","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.0.9","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"7340f88960ab497e90eda5d5be837c99b6f71160","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.0.9.tgz","fileCount":16,"integrity":"sha512-sG1NZTDp6KVYAO5OrPmyo9NWh5x8KgAY+woxIpGZw/BBvWpmVvV83kp2ndkeqef7/DDDArXwmOujuq2NRSLHLw==","signatures":[{"sig":"MEQCIG4IkvhXiR8/CC/zCOZg50Di8Emixd0qlXwre92CkyjHAiAn5FrWlpVyB1p3Ga2AGU2v5yJ7IzqoFIE6cCYluc9kLg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.0.9","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":141171},"engines":{"node":">=18"},"gitHead":"b16738e7c58640d376cf54074d773bed72463490","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.12.1","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.0.9_1779733899298_0.460237667975979","host":"s3://npm-registry-packages-npm-production"}},"0.0.10":{"name":"aicontainer","version":"0.0.10","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.0.10","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"4ea990ea4c202938bb3e0950957e4fcc4eabb193","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.0.10.tgz","fileCount":16,"integrity":"sha512-7KbEH0y7Alb8n8B17F7N0d0o1IZZJxHGpTKWWMyp73yRX0BxRs61l7VX8SMezYruxlfbLaqZ+SLg2w+p66uFDQ==","signatures":[{"sig":"MEQCIEaP+9xFBElbEqjsQ3iNHFuKEDeTIUW1G6Y7YXXw+N2FAiATIpdNB66o2W8FIVfaLG7VqOIns5Ok3Zj4PYMvyq0H1A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.0.10","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":146906},"engines":{"node":">=18"},"gitHead":"3308079644a72364c1eb3a886e5d0425759ecd22","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.12.1","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.0.10_1779742339746_0.9025031536718047","host":"s3://npm-registry-packages-npm-production"}},"0.0.11":{"name":"aicontainer","version":"0.0.11","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.0.11","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"9b1e6f1ad784efcf124f7aded825b8a067e4f0ef","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.0.11.tgz","fileCount":16,"integrity":"sha512-BdAz23WHodpvjslZgTXI+K51xEfCIyHwkRQxdG0zBK6FhpRIviSBRlr8WRSYOztWOL8/86LJg87K+3fZId2eEA==","signatures":[{"sig":"MEYCIQCFspJ/6hqwxvE7zv/0dBY+jUPtVCoAnwfJktYRWFNTOAIhAIwUWnNrad045GMSJ8FVRuelSN0d7MIe6HPv+f99TOMG","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.0.11","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":147388},"engines":{"node":">=18"},"gitHead":"9eac8a82577fb03dd114cf8d9a7f877529df4d57","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.12.1","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.0.11_1779744452449_0.21085404387394435","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"aicontainer","version":"0.1.0","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.1.0","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"f4a2233919b1811961fe279c9af4c500a5475e7d","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.1.0.tgz","fileCount":16,"integrity":"sha512-tV0cDHuwBSY7fO3HgUV2htVJh8hw0fiDki8SNgigGjZUbgzON/KqIZ2FkQc0/ZqvDgUcdiLd1ST9nj/ja+w9zA==","signatures":[{"sig":"MEYCIQDUmO5DLvnzulc1IPo54iu6h0p8a5KGfYZyvMRvXd411AIhALvtFbyFAFtlBYmIDKOBPGReFNIS79D9JFNRFwO0Y+l2","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":159745},"engines":{"node":">=18"},"gitHead":"7a773bbe68d68a6a2b41f86ef818db28548ffa43","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.12.1","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.1.0_1779780695531_0.6770471765030575","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"aicontainer","version":"0.1.1","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.1.1","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"b40036f154b0466e0626f93dccc7a53437e2e177","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.1.1.tgz","fileCount":16,"integrity":"sha512-Ytgv4XujMjZpKjWXMdNH5rVjDzSnnd0B68+KGwtgF7y7lqgfNz1ZnlMmwvLZbrZsdRvxbC0juGex2RrOJl3k1Q==","signatures":[{"sig":"MEUCIQDQrHlcYdbgrjVNZuebVVqXaElxTjlQJxkttluDPXmxxgIgfeObjC02lko5oi3aQInaNnvUZ9meopstxHDAGleoDXk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":161806},"engines":{"node":">=18"},"gitHead":"17b0bad7ce36e5df6af3fbd9a65dac346b25cf1a","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.12.1","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.1.1_1779799732275_0.41195896482370187","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"aicontainer","version":"0.1.2","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.1.2","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"38209bb117faa4a583189bfeac1c88d2aa09b6ad","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.1.2.tgz","fileCount":16,"integrity":"sha512-VCp7hm73C0snjs+zSd9qpls87DtTmhE8/i7A1csZZWR7iSOkD8gxtF0zW8p4ogidLkr/QdEiMWYvZHQEe8CzQw==","signatures":[{"sig":"MEQCIAEFoELjJkft2C5y0qlQ1YfLY7aQ66KNyhyzWIaoW21PAiBPVnB3eFp/7DRBGqsVJS52L8LIWjvjMICZws3ZRSi/Kw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.1.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":174720},"engines":{"node":">=18"},"gitHead":"e9c50349faf984de693a7ebb4823daf50f6a7297","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.12.1","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.1.2_1779876252187_0.4775402561747357","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"aicontainer","version":"0.1.3","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.1.3","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"71164a2da00be8757105bbb479bc4730dbfcbb22","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.1.3.tgz","fileCount":16,"integrity":"sha512-EJRI7RgFnD06iZ+sL/Ieckqn3stYRE/6rSo8p5ZUzE2fZwCXdsUpcL6fca3aNjkjnvlNwHyZCdc0lB5cRcAPmQ==","signatures":[{"sig":"MEQCIHEffnuyqMARHPskXiC5T5C1Z7MMWjN9jcgjLrKohf7RAiA5H72UMBBZIeIb0WFvAHS1KKYlwdV+i1jkLoDjUaydCQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.1.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":176217},"engines":{"node":">=18"},"gitHead":"2d930415d68f57b8bbf4fedcc0cb38e32cd87b13","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.12.1","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.1.3_1779885729807_0.13092757375416553","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"aicontainer","version":"0.1.4","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.1.4","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"030576395afb53efd2f7c21569bf74b193bc7baa","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.1.4.tgz","fileCount":16,"integrity":"sha512-6oYf8mfs9M0gCeaBdDJYDeIYFH/7OkqahUDFFp8S5whLer1ytnZje217SzDkJ3772ya5fS50W8DN9sw/enFShg==","signatures":[{"sig":"MEUCIQDFfZHZvCp5iUbL5IYOBNk7m77Z643l3DGCjoH91IKeEAIgC1MLHEi0iCWJ9cM5WcmltKI1Ora7TvrpDW9TohgZU5I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.1.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":177639},"engines":{"node":">=18"},"gitHead":"3af60f04ad6f3d0000bb66434929991915d390be","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.13.0","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.1.4_1780176024621_0.8136665489012176","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"aicontainer","version":"0.2.0","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.2.0","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"a1dcb3e3de5e57be36349ebe5cd454e05b063b0a","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.2.0.tgz","fileCount":16,"integrity":"sha512-NhkVy6ZzBRwcneASnK4/ouwsNuA+kAbifFmiIvdjXUBYRq8hQLIeJegRlmP66lom2PS6YPJQCqHvvQ0blLWojA==","signatures":[{"sig":"MEUCIF5VsFyd0YcLQi45wxyl5INj6wuSgldJwiLAITtHMhI0AiEAwHrsDqpAV7IqxImNNKr3J/p1QqliZuI7iBIYRW7SFiw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":196064},"engines":{"node":">=18"},"gitHead":"bb80fca9927425667ddf85b417861c1e951a35e1","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.13.0","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.2.0_1780239244137_0.8385602724628864","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"aicontainer","version":"0.2.1","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.2.1","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"9b4b5b9a73971a4655ba36b6a702cd8431796044","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.2.1.tgz","fileCount":16,"integrity":"sha512-gxJ6lOrp2gbCGTItxozyroDYkc9c4hoz7EJKocvZt1Qz0ubHLwgp+cLOTls4OMVRHmPjyT6jpyoSPlJq6QZmhw==","signatures":[{"sig":"MEYCIQCeYeOIk9qh1647hdnuAPUUq3h9d1//1k3CVEcBotWdGwIhAJsSoXmIAP8fBFuBNMklgTO02UJTfltORs8b4ogAhwzD","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":200033},"engines":{"node":">=18"},"gitHead":"b561f6f622ca92c5f7023b2f1a0e10f3e841675e","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.13.0","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.2.1_1780305684364_0.9183192870956836","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"aicontainer","version":"0.2.2","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.2.2","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"5d46bc7de73a23c3db8628843c6f8c9d64f707cf","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.2.2.tgz","fileCount":16,"integrity":"sha512-kaxZM3yyP+4t553PFGmtR0IF9Q384wPxNxtgBxggr23rOQyDER2XzW4R+Smn7xVVk+YCse7UNsAmNUxMujekdQ==","signatures":[{"sig":"MEUCIQCIqFYky7ebWWQjSECZ7DBNWqVEFpXo9+elQ0NoImpguQIgK9KcD45eKJcmJSYb+dQucf/eAmzwyuK02LjEXJaEnnk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.2.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":204116},"engines":{"node":">=18"},"gitHead":"d9b0078a0c4679364413dc772bf5ce488ee88d33","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.13.0","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.2.2_1780344598147_0.8079199417651108","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"aicontainer","version":"0.2.3","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.2.3","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"335b5ff25ed594513cd25fe0e765d1b247b528bc","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.2.3.tgz","fileCount":16,"integrity":"sha512-nzpEHnPE4/aJP6mWbQbZ8lVJXRufA0bLzaxg2Y4/wzuezYffAiHOTZPaiaEPKy/cThXsPofQkNvgs/47CIdGyA==","signatures":[{"sig":"MEUCIE3GmsQC7L0a9CZAkuJYSUjd4iWxxjkao3Q1FYs0ybWpAiEAxRFmhtZcOpAvMob1M82EFAbcCrVYggpOD80Ee3SzoWY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.2.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":206890},"engines":{"node":">=18"},"gitHead":"65670786ddc6812c9dbce231177f044229ad09da","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.13.0","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.2.3_1780476021507_0.10240401535620247","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"aicontainer","version":"0.3.0","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.3.0","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"64e23da959567511711501700967d7cc03b82c37","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.3.0.tgz","fileCount":17,"integrity":"sha512-9g3I18TsdFG61JujWEGx/JV888gOlg4lRtfIaDsIF4hn98LgHVVgM5m/WtVyAABZKc6heHKzaFU2accLLevdHQ==","signatures":[{"sig":"MEUCIQDC2z0TOkifWn7jtNeMfmpHiRw1cDPS6M9d82F+ddIXyQIgFZYWXuxKvEa8OxMGqtGc30TPl6zw4MJqDcEYhSoZ+tc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":221270},"engines":{"node":">=18"},"gitHead":"dd9ad9bd3c97e1209a1a18b06b2669cf15064563","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.13.0","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.3.0_1780490762390_0.1434515535985601","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"name":"aicontainer","version":"0.3.1","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.3.1","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"70f5357bf43404a4fcbaa21c17364d662d45b06d","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.3.1.tgz","fileCount":17,"integrity":"sha512-ywzk3+M0tQKgnv8gVSNIawDuI9RB7eyki7c9GgpGBRSmwvJ2DPkfOt1D1GUqf9McfqSIpgoh7JF9QzdEEGmdFA==","signatures":[{"sig":"MEQCICk+Fpzp01VXXvEef0wh7REUe/AbpYu4eJZ9WdvOSteiAiANFE6AZq7hu02dqIMbHwcmLQgsSGZdVc5gPboemcE3Wg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.3.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":221550},"engines":{"node":">=18"},"gitHead":"5713c07a460d2661989f08d2752c549edcb5c6f7","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.13.0","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.3.1_1780991856201_0.22481064718376342","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"aicontainer","version":"0.4.0","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.4.0","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"6ba123db595d9bef04c0be66fa4e98cb2474599f","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.4.0.tgz","fileCount":18,"integrity":"sha512-+9RwpDHKRSTn4unEh5IVJP+6zoxwKnaJWlgXsxkYerAVVFgZT/xKXeRoAkGch6sxrXwqRWiLyLs3DcQNQzDLNw==","signatures":[{"sig":"MEUCIQDBstCsIxg0Kyv/8CkCiIoVAG/iKA8gWMl7yJU/RX2rsAIgYAoXJRQQ5SdhKCYvEJtaiMUS53rMyBk0FbgFALVf1tE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":239135},"engines":{"node":">=18"},"gitHead":"0a54ac185805f383b4923194fa2edddd20ae2cfb","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.13.0","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.4.0_1780999345410_0.976227996741249","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"aicontainer","version":"0.4.1","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.4.1","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"4c636a2645dafc19e75a18ad1046175220fdfa94","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.4.1.tgz","fileCount":18,"integrity":"sha512-Yea6VWOqqVRqS4UK0cGHZZYMo9pV5rZWVeZCYVlVQ5RL49gbgAaE0rxIpuA/Tp3pU9XuLQJf+T3xprxCUvYG/Q==","signatures":[{"sig":"MEQCIEFMyxhEXyNlXN4DFZ8wlm7teDjsEv7XNIfk9EiK3WA3AiAejB0T2aNcZ+4KJLCTFFT3lguz316Tx5YGVPaHi0jS2g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.4.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":247466},"engines":{"node":">=18"},"gitHead":"f8e2dad239adf37a89db059ce497b7c0dc3375c4","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.13.0","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.4.1_1781013436668_0.21753834852621612","host":"s3://npm-registry-packages-npm-production"}},"0.4.2":{"name":"aicontainer","version":"0.4.2","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.4.2","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"53c8efe2873337c864e6bc637181b006ba15bed4","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.4.2.tgz","fileCount":18,"integrity":"sha512-FVQIBriuyP7JlFdn0NyL6FO7ROqObWfld0bPnTK7mpLv5EwKgbYZ4rzQXTbAA06yUwmeJkXAa/KUEE+8nPZqug==","signatures":[{"sig":"MEQCIFO6Ft58R5jAC7yKiGtjs6jAYl00RiWMPUFdVtNdG0H2AiBa8tOiDP6Ywp87vOvTTrm6Bq6WOrPp1Xx/BSPrh0iaqA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.4.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":249523},"engines":{"node":">=18"},"gitHead":"7c99c5603ef0c240a25f0f0071968f63c21157da","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.13.0","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.4.2_1781017535361_0.24787966822923546","host":"s3://npm-registry-packages-npm-production"}},"0.4.3":{"name":"aicontainer","version":"0.4.3","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.4.3","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"a54c1d821fdfc07391fbc44a3d87db7e5c508b03","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.4.3.tgz","fileCount":18,"integrity":"sha512-2B+W+H4yulX25JgmI26uV73emVMKMsx5490hXxKRUua5W9HffUqxuOMcwOI20gXMd/CDkgNPONyleG4OerXG8Q==","signatures":[{"sig":"MEQCIA/A0Sr/fSNpFvKjYJMctmoaV9L+uSwZIH066suQRw+wAiARHGYHbfW3fsLyttZOb88WshKmOlepWTqWWfOO4fbikw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.4.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":252650},"engines":{"node":">=18"},"gitHead":"1affa65f52da33c1ded2e3c23d30ee2d37729b46","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.16.0","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.18.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.4.3_1782850210465_0.7473066319750536","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"aicontainer","version":"0.5.0","keywords":["devcontainer","claude-code","codex","ai","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.5.0","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"2f1a400cd357020c688bb5402beec4c3461b3a37","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.5.0.tgz","fileCount":18,"integrity":"sha512-9TT2xFS4vT/lFCEMRqpCnUc1zAyhPS3dVWH/k0GWubjxFxVypenS5aCt3rHqLpJcRkG0sGnf1FiXlAlvWRzblg==","signatures":[{"sig":"MEUCIQCbbYSkkP8O4cAVPFEz+LpmleF9oCOfDFAH6cpM8CiyHQIgWT05dQIohkz0vWA1mLiuMRcWIt5ZuW+gJCYcAtss4VE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.5.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":271776},"engines":{"node":">=18"},"gitHead":"2b7c2b19a69aa5dea39757d4b62fdb9d3f9a351d","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.16.0","description":"Sandboxed devcontainer for running Claude Code and Codex in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.18.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.5.0_1783346054126_0.2709724664718005","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"aicontainer","version":"0.6.0","keywords":["devcontainer","claude-code","codex","opencode","ai","ai-agent","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.6.0","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"df7605b60a8e9f094da530e8ad09fa28a4e6fdca","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.6.0.tgz","fileCount":19,"integrity":"sha512-QjfiR1rSJLURzUE7HKmJIav3WObHgWIBC5EtHPX55szbvCplT/0vjz1KpFog6z5Vdvk94/o1U2IWBUo3WTmcUQ==","signatures":[{"sig":"MEUCIQDJliAci6QmG/kv9AmC2l+L0dzkwPiZpSeqllLT46oCjAIgJ+cJsm6RwbCaizMnrOOU9j0lZ0+phAWk6cHotPVBM9s=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.6.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":445794},"engines":{"node":">=18"},"gitHead":"5f69e9172294ddf2fb12190fa03108a8024becf5","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.16.0","description":"Sandboxed devcontainer for running Claude Code, Codex, and OpenCode in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.18.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.6.0_1783950871172_0.8681383195958481","host":"s3://npm-registry-packages-npm-production"}},"0.6.1":{"name":"aicontainer","version":"0.6.1","keywords":["devcontainer","claude-code","codex","opencode","ai","ai-agent","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.6.1","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"a2f9d90cef5d5665793a7368e48c10c2be323be7","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.6.1.tgz","fileCount":19,"integrity":"sha512-DJGEnsVqFO1+UkgEUduUapq6247vkzonTumD+4NUGoKsLu/ZJvoSEisAs5oi/F9h+o4Rt/fvzxI1iQs5oV35Ew==","signatures":[{"sig":"MEUCIF6KW43kof1p1Do2WrLx3r4U9G3S/5apGjVUEPTn/ag7AiEAw+gOwndhHPiB+p0kRXKEfUpCSYrjlT3FyKqAR/x4G+A=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.6.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":446757},"engines":{"node":">=18"},"gitHead":"d73faf5c5d2158a2a964ffa8ae343d9bc5352fb5","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.16.0","description":"Sandboxed devcontainer for running Claude Code, Codex, and OpenCode in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.18.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.6.1_1784582265203_0.38706121160419826","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"name":"aicontainer","version":"0.7.0","keywords":["devcontainer","claude-code","codex","opencode","ai","ai-agent","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.7.0","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"26585798b87dadd44bf35a958c8cddc8283ce14e","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.7.0.tgz","fileCount":19,"integrity":"sha512-rlZ5waduIdPdbNnI+/1aIi+KhpUevFVYkFcVdvyIliuIOhqqXFcHL3Rz223efwdEfb0ki2Vqfvx/+B82v0cpIA==","signatures":[{"sig":"MEUCIQDXIXzDpIi5Ikez/pw1mUxXwMwEKQl3eDk2AbkCUJ7btgIgZxZD+hfCY3KjhWEgsQ/Ji0BAS0M8TEHPh17UX8W2r+I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.7.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":461367},"engines":{"node":">=18"},"gitHead":"1908feaf55487aed28ece2e7ee81f940e06d8190","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.16.0","description":"Sandboxed devcontainer for running Claude Code, Codex, and OpenCode in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.18.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.7.0_1784752123026_0.32003763960735987","host":"s3://npm-registry-packages-npm-production"}},"0.7.1":{"name":"aicontainer","version":"0.7.1","keywords":["devcontainer","claude-code","codex","opencode","ai","ai-agent","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.7.1","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"4c6c89652996a861beea0ea43cdb6a906aa70c55","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.7.1.tgz","fileCount":19,"integrity":"sha512-VRYglK6y0eq5F9rzMqdQBbRmoeRxWrro/HAWvqonUztbpilIFxsQxaARFE0TuqCtBLzYfCvCnru54uLTG43yig==","signatures":[{"sig":"MEUCIDh2qbC7Tf1XCP6IPi4mPg4drs90mUaSmZgK2ODatEGBAiEA8F/XWypj2vyXi95vp/8QtZWR4QN/HTsP63g/CC3UDDs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.7.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":462446},"engines":{"node":">=18"},"gitHead":"6e3b253bf96905da335027ef86b161116fd47a17","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.16.0","description":"Sandboxed devcontainer for running Claude Code, Codex, and OpenCode in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.18.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.7.1_1785491487662_0.6234744818029521","host":"s3://npm-registry-packages-npm-production"}},"0.8.0":{"name":"aicontainer","version":"0.8.0","keywords":["devcontainer","claude-code","codex","opencode","ai","ai-agent","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.8.0","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"84eb6c41912855fb67deda96329a34de34b07937","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.8.0.tgz","fileCount":19,"integrity":"sha512-Zp/FNB7pRSOX8yJ6mnDYKX8fiveCnNxyOxXLm/AhPz58f5R6Kpd28IIDWsoZbW68UF8SlUao/j6XfwjdFj5PDQ==","signatures":[{"sig":"MEYCIQDW1pRHd63YOFIqCUe5SkAkR3wsQjl3ycGO3frT9qBRTwIhAL17hUrBm2JHZsf4OK6JcJILGBeN5KYEm1nAhFQZe9PD","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.8.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":476694},"engines":{"node":">=18"},"gitHead":"a10102787f37bdb2198c09b19c1fccff0360e7ef","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.16.0","description":"Sandboxed devcontainer for running Claude Code, Codex, and OpenCode in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.18.0","dependencies":{"@devcontainers/cli":"^0.87.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.8.0_1785502374026_0.05497698912907767","host":"s3://npm-registry-packages-npm-production"}},"0.8.1":{"name":"aicontainer","version":"0.8.1","keywords":["devcontainer","claude-code","codex","opencode","ai","ai-agent","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.8.1","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"c588e6530583593b08f34b4f29d28a0511f21adc","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.8.1.tgz","fileCount":19,"integrity":"sha512-bTWYS1gAODcV/YRXHR/pfrPRSvJHg8hXV5KhaK6GNulY+w6UbhUkJY6r+J3n8KWouanjBZZVC7VHQRgyYWNGWw==","signatures":[{"sig":"MEUCIQCI/EXVcQumIAiLX+Z4YhVm2B6u0NKuZtbmEWrkc/g82gIgYT+YdmygaSgqZliif2lAF8qRwP4V994qLqQa0jJ4ft0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.8.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":477660},"engines":{"node":">=18"},"gitHead":"299d1afa79ab11436a9037e8240b0cd60afee2fb","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.17.0","description":"Sandboxed devcontainer for running Claude Code, Codex, and OpenCode in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.19.0","dependencies":{"@devcontainers/cli":"^0.88.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.8.1_1787587185035_0.847888062558348","host":"s3://npm-registry-packages-npm-production"}},"0.9.0":{"name":"aicontainer","version":"0.9.0","keywords":["devcontainer","claude-code","codex","opencode","ai","ai-agent","sandbox","docker","vibecoding","vibe-coding"],"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","_id":"aicontainer@0.9.0","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"homepage":"https://github.com/stefanoginella/aicontainer#readme","bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"os":["darwin","linux"],"bin":{"aic":"aic","aicontainer":"aic"},"dist":{"shasum":"ac18e782d44aefc4e485688b0700f0993e5331be","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.9.0.tgz","fileCount":20,"integrity":"sha512-QxUsJn4VQGT29GsPyeHr5DVmu2iSRXhJ7BrJj4xh5xC0ogZrdNkyTUjGFym5JzRaK2RPu/um8rxZR3Td6Qh+lQ==","signatures":[{"sig":"MEYCIQCAc7oQJqyz5Uu3LdhGMFnzJ0zgJWTrplak/4mYG1TJ0wIhAOf7Wque5fUcNw0tnbXzIl1IkMlWCW7F/caZ/On7p6n2","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.9.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":502010},"engines":{"node":">=18"},"gitHead":"03a708b8de8959b10ad37ec00a68a43b8ee2e526","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eeb06162-08eb-48d0-93a3-e33965168137"}},"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.17.0","description":"Sandboxed devcontainer for running Claude Code, Codex, and OpenCode in bypass / auto-approve mode.","directories":{},"_nodeVersion":"24.19.0","dependencies":{"@devcontainers/cli":"^0.88.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aicontainer_0.9.0_1787597544731_0.8209859165788098","host":"s3://npm-registry-packages-npm-production"}},"0.9.1":{"os":["darwin","linux"],"_id":"aicontainer@0.9.1","bin":{"aic":"aic","aicontainer":"aic"},"bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"dist":{"shasum":"c8535d3cc5355c59708f0a92cc89b51ac1de51cf","tarball":"https://registry.npmjs.org/aicontainer/-/aicontainer-0.9.1.tgz","fileCount":20,"integrity":"sha512-QoaV828Z8RYRXingZmyBabnBrt8bYzcNlhHA1PmBpt8Mj5DLvMQkFKWE9bY3dsne4LFgUNjB9t8yFQS3dAq6ew==","signatures":[{"sig":"MEQCIBYPS0xMsg7aDCIgebKgS4w5gV5R9HIhjcNjCcXCupTpAiB9jPzTUaoa5BUH0VAYahOxOp+OSRsKYBhvneHpzlMbUA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDGwEuq6hWQhuOJT0mOlB8w66CLw/hKpeeMXC/3+WivmAIgdTLFiYDPb4GFWH/1OOBsbauMaVpFEh1NdRPmLWRxdxM="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/aicontainer@0.9.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":502590},"name":"aicontainer","author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"engines":{"node":">=18"},"gitHead":"bcd759b5d758e5648511d38a7121d845ddf14c80","license":"MIT","scripts":{"version":"node scripts/promote-changelog.mjs && git add CHANGELOG.md","preversion":"node scripts/promote-changelog.mjs --check"},"version":"0.9.1","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"eeb06162-08eb-48d0-93a3-e33965168137"}},"homepage":"https://github.com/stefanoginella/aicontainer#readme","keywords":["devcontainer","claude-code","codex","opencode","ai","ai-agent","sandbox","docker","vibecoding","vibe-coding"],"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"_npmVersion":"11.19.0","description":"Sandboxed devcontainer for running Claude Code, Codex, and OpenCode in bypass / auto-approve mode.","directories":{},"maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"_nodeVersion":"24.21.0","dependencies":{"@devcontainers/cli":"^0.89.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/aicontainer_0.9.1_1791203688224_0.5151498498176563"}}},"time":{"created":"2026-05-22T15:26:21.304Z","modified":"2026-10-05T12:34:48.680Z","0.0.1":"2026-05-22T15:26:21.708Z","0.0.3":"2026-05-22T15:43:26.467Z","0.0.4":"2026-05-22T16:32:32.977Z","0.0.5":"2026-05-22T18:45:09.185Z","0.0.6":"2026-05-25T09:44:59.854Z","0.0.7":"2026-05-25T13:41:18.796Z","0.0.8":"2026-05-25T16:37:28.587Z","0.0.9":"2026-05-25T18:31:39.482Z","0.0.10":"2026-05-25T20:52:19.883Z","0.0.11":"2026-05-25T21:27:32.572Z","0.1.0":"2026-05-26T07:31:35.684Z","0.1.1":"2026-05-26T12:48:52.412Z","0.1.2":"2026-05-27T10:04:12.402Z","0.1.3":"2026-05-27T12:42:09.964Z","0.1.4":"2026-05-30T21:20:24.801Z","0.2.0":"2026-05-31T14:54:04.329Z","0.2.1":"2026-06-01T09:21:24.513Z","0.2.2":"2026-06-01T20:09:58.294Z","0.2.3":"2026-06-03T08:40:21.642Z","0.3.0":"2026-06-03T12:46:02.519Z","0.3.1":"2026-06-09T07:57:36.350Z","0.4.0":"2026-06-09T10:02:25.651Z","0.4.1":"2026-06-09T13:57:16.848Z","0.4.2":"2026-06-09T15:05:35.692Z","0.4.3":"2026-06-30T20:10:10.617Z","0.5.0":"2026-07-06T13:54:14.294Z","0.6.0":"2026-07-13T13:54:31.316Z","0.6.1":"2026-07-20T21:17:45.401Z","0.7.0":"2026-07-22T20:28:43.230Z","0.7.1":"2026-07-31T09:51:27.815Z","0.8.0":"2026-07-31T12:52:54.234Z","0.8.1":"2026-08-24T15:59:45.210Z","0.9.0":"2026-08-24T18:52:24.930Z","0.9.1":"2026-10-05T12:34:48.324Z"},"bugs":{"url":"https://github.com/stefanoginella/aicontainer/issues"},"author":{"url":"https://github.com/stefanoginella","name":"Stefano Ginella"},"license":"MIT","homepage":"https://github.com/stefanoginella/aicontainer#readme","keywords":["devcontainer","claude-code","codex","opencode","ai","ai-agent","sandbox","docker","vibecoding","vibe-coding"],"repository":{"url":"git+https://github.com/stefanoginella/aicontainer.git","type":"git"},"description":"Sandboxed devcontainer for running Claude Code, Codex, and OpenCode in bypass / auto-approve mode.","maintainers":[{"name":"stefanoginella","email":"stefano@stefanoginella.com"}],"readme":"# aicontainer\n\n[![npm version](https://img.shields.io/npm/v/aicontainer?logo=npm)](https://www.npmjs.com/package/aicontainer)\n[![release](https://github.com/stefanoginella/aicontainer/actions/workflows/release.yml/badge.svg)](https://github.com/stefanoginella/aicontainer/actions/workflows/release.yml)\n[![rebuild](https://github.com/stefanoginella/aicontainer/actions/workflows/rebuild.yml/badge.svg)](https://github.com/stefanoginella/aicontainer/actions/workflows/rebuild.yml)\n[![License: MIT](https://img.shields.io/npm/l/aicontainer?color=yellow)](LICENSE)\n[![Container: GHCR](https://img.shields.io/badge/container-ghcr.io-2188ff?logo=github)](https://github.com/stefanoginella/aicontainer/pkgs/container/aicontainer)\n[![Devcontainer spec](https://img.shields.io/badge/devcontainer-spec-blue?logo=visualstudiocode)](https://containers.dev/)\n\nA sandboxed devcontainer for running [Claude Code](https://claude.ai/code), [Codex](https://github.com/openai/codex), and [OpenCode](https://opencode.ai) in bypass / auto-approve mode safely across multiple projects.\n\n**Why?** Auto-approve is the only way these CLIs actually fly — but pointed at your real `$HOME` it also lets a prompt-injected dependency read `.env`, exfiltrate shell history, or push through your `gh` token. `aicontainer` puts the AI behind a devcontainer boundary so you can keep auto-approve on without rebuilding your machine each time.\n\n**What you get:** filesystem isolation, **no Docker object access by default**\nthrough a digest-pinned [socket proxy](https://github.com/Tecnativa/docker-socket-proxy),\na minimal shared tool hook, an always-on cloud-metadata/link-local block, and an\n**opt-in** outbound allowlist. Host preferences are reduced to fixed safe fields\nbefore the agent sees them; logins still carry across projects. Defaults are\nlisted in [What's in the box](#whats-in-the-box) so you know exactly what you're\nadopting.\n\n> Adjacent work: same shape as the [Trail of Bits devcontainer](https://github.com/trailofbits/claude-code-devcontainer), with Codex and OpenCode added, three explicit Docker-access modes, and managed shell/config startup.\n\n## What crosses the boundary\n\nAt a glance, what the in-container agent can touch on your host. Run `aic\npreflight` in any project to print this for your *actual* config (it's also\nshown automatically at the end of every `aic up`).\n\n| Surface | Crosses the boundary? |\n|---|---|\n| Project directory | **Yes, read-write** (`/workspace`) — the one writable host path. |\n| Host Git / Claude / Codex / OpenCode config | The raw files are visible only to a fixed, root-only, networkless one-shot sanitizer. The agent receives root-owned JSON containing allowlisted preferences; executable Git config, inline credentials, MCP env/header secrets, and security-policy fields are removed. See [Config seeding](#config-seeding-from-the-host). |\n| Host shell startup files (`.zshrc`, `.bashrc`, fish config, p10k) and Claude `statusLine` | **Not automatically.** Shells start from root-managed aicontainer profiles and the host `statusLine` command is dropped, so nothing host-side plants startup code. You can opt in per file by copying it into `~/.config/aicontainer/` (`rc.zsh`, `p10k.zsh`, `statusline.*`); those cross verbatim and land root-locked. See [Personal shell config](#personal-shell-config) and [statusline](#personal-claude-code-statusline). |\n| Host home, `~/.ssh`, SSH-agent socket | **No** — not mounted, not forwarded. |\n| Host credentials (API keys, `gh` token, keychain) | **No** — nothing auto-forwarded; you log in once *inside* the container. |\n| Host agent-status receiver | **No by default.** A host-global marker opts all projects into metadata-only Claude/Codex lifecycle callbacks at one fixed local URL. Repositories cannot enable or redirect it. See [Agent status relay](#agent-status-relay). |\n| Package-manager caches | **No** — container-local volumes, not your host caches. |\n| Clipboard / browser | **No** — nothing bridged. |\n| `.env*` files | Blocked from the agent by the [PreToolUse hook](#whats-in-the-box). Your project's own `.env` is physically in `/workspace`, but the hook stops the agent from reading it — defense-in-depth at the tool layer, not a missing file. |\n| Session transcripts, prompt history, user-level skills/plugins/instructions | Persist in a **path-unique per-project volume**, never written back to your host home or shared with another checkout. See [Multi-project model](#multi-project-model). |\n| Host Docker daemon | **Object APIs off by default**: only proxy ping/version remain. `--docker-read` opts into sensitive object/inspect/log/file APIs; `--docker` opts into read-write host-daemon control for testcontainers / in-container Compose. See [Threat model](#threat-model). |\n| **Outbound network** | **Mostly open by default.** Reaches the internet and your LAN; IPv4/IPv6 link-local and common cloud-provider metadata endpoints are blocked on every create. Opt in to the [allowlist](#opt-in-network-allowlist) to restrict the rest. |\n\nThe full reasoning is in [Threat model](#threat-model); the network row is the\none most worth your attention.\n\n## Prerequisites\n\n- Docker Engine 25+ with Compose 2.24+ (volume-subpath support): [Docker\n  Desktop](https://docker.com/products/docker-desktop),\n  [OrbStack](https://orbstack.dev/), or\n  [Colima](https://github.com/abiosoft/colima), or rootless Docker Engine,\n  using a local Unix socket. aic discovers the selected context automatically.\n- Node.js 18+ (for npm and the bundled `@devcontainers/cli`).\n- A conventional Git checkout opened at its repository root (`.git` must be a\n  directory so its config/hooks can be protected with exact read-only mounts).\n\nRun `aic doctor` for an exact, non-mutating compatibility check.\n\n## One-time install\n\n```bash\nnpm install -g aicontainer\n```\n\nThat puts `aic` on your PATH and pulls `@devcontainers/cli` in as a dependency. To upgrade later: `npm update -g aicontainer`.\n\n**Try-before-install:** `npx aicontainer init` works too, but `aic up` / `aic shell` / etc. are repeated commands — install globally once and you won't pay the npx download tax every time.\n\nPrefer a git checkout? `git clone https://github.com/stefanoginella/aicontainer ~/.aicontainer && ~/.aicontainer/install.sh` still works — `aic` resolves its templates relative to its own location, so both layouts behave the same. With a checkout you'll also need `npm install -g @devcontainers/cli` separately, and `aic upgrade` does the `git pull`.\n\n### Shell completion\n\nOptional but recommended. `aic completion <shell>` emits a completion script for **bash**, **zsh**, or **fish** — pick the line for your shell:\n\n```bash\necho 'eval \"$(aic completion bash)\"' >> ~/.bashrc\necho 'eval \"$(aic completion zsh)\"'  >> ~/.zshrc\naic completion fish > ~/.config/fish/completions/aic.fish\n```\n\nThen reopen your shell. You'll get tab-completion for subcommands (`init`,\n`sync`, `up`, `trust`, …), Docker modes (`--no-docker`, `--docker-read`,\n`--docker`), and the `--with` / `--shell` values.\n\n## First-time auth\n\nAuthenticate once. A networkless credential bridge synchronizes only the four\nknown tool credential JSON files into fixed subpaths of the global\n`aic-auth-global` volume; GitHub, npm, signing, and Semgrep use their own fixed\nsubpaths. Prompt-bearing config, instructions, skills, plugins, and transcripts\nstay in the current project's volume, so login convenience does not turn one\nproject's persistent instructions into another project's.\n\n```bash\nmkdir -p ~/sandbox/scratch && cd ~/sandbox/scratch\naic init\naic up\naic shell\n\n# Inside the container:\nclaude /login           # OAuth flow in your host browser\ncodex auth login        # OpenAI auth\nopencode auth login     # pick a provider (Anthropic, OpenAI, OpenCode Zen, …)\ngh auth login           # GitHub (use a fine-grained PAT if you can)\nnpm login               # only if you publish packages — token persists too\n```\n\nAfter this, every `aic up` in any project picks up the same credentials. You do not need to re-log in.\n\n## Per-project usage\n\n```bash\ncd my-project\naic init           # writes a small managed .devcontainer/ that pulls the GHCR image\naic up             # pulls the version-pinned image, validates config, then starts the sandbox\naic shell          # opens the configured interactive shell (zsh by default)\nclaude             # runs in bypass mode (permissions skip)\ncodex              # runs in auto-approve mode (sandbox off)\nopencode           # runs with permissions set to allow (guardrail still on)\n```\n\n`aic init` defaults to **pull mode**: it writes `devcontainer.json`,\n`docker-compose.yml`, a managed guide/ignore file, and a gitignored `.env` with\nthe selected host socket, runtime UID/GID, project identity, and host-owned\nstatus-relay mode. `aic initialize` refreshes that host-only file automatically,\nso rootless Docker, Docker Desktop, Colima, and OrbStack need no\naicontainer-specific flags. `aic up` pulls the prebuilt image\nfrom GHCR (≈30s on a warm runtime, vs. several minutes to build from scratch).\nEverything else — the Dockerfile, `post-create.py`, firewall, and hooks — is\nbaked into the image.\n\nIf you want to own the build (custom apt packages, air-gapped environments, hacking on the base image), run `aic init --build` instead. That copies the full template — `Dockerfile`, `post-create.py`, hooks, helper scripts — into `.devcontainer/`, and `aic up` builds the image locally.\n\nOther commands: `aic run CMD ...` runs a one-shot inside the container without opening a shell, and `aic down` stops the container without removing its volumes (resume with `aic up`). Full list in `aic help`.\n\nEvery aic-launched startup validates the managed control files and fully\nresolved Compose model before handing them to Dev Containers. The generated VS\nCode initializer repeats the gate before Compose creates anything. Normal\ngenerated projects stay silent. If a project intentionally adds a custom image,\nhost bind, device, capability, or namespace, review the findings and run `aic\ntrust` once; the exact-config approval lives outside the repository and expires\nwhen the relevant config changes. For a single reviewed run, use `aic up\n--allow-unsafe` or `aic rebuild --allow-unsafe`. Docker daemon visibility is a\nseparate opt-in: use `aic init --docker-read` / `aic sync --docker-read` or the\ncorresponding `--docker` form; matching consent also lives outside the\nrepository.\n\n> **Direct VS Code bootstrap caveat:** Dev Containers must read the repository's\n> `devcontainer.json` and execute its host-side `initializeCommand` before `aic\n> initialize` can validate it. Never click **Reopen in Container** on an\n> arbitrary repository-supplied `.devcontainer/`. Run `aic init --force` (or\n> `aic sync` for an existing aicontainer project), inspect the resulting diff\n> and project-owned override files, then use `aic up` or reopen in VS Code.\n\n### Diagnostics and review\n\nThree read-only commands make the boundary inspectable without starting or\nchanging the project:\n\n```bash\naic doctor     # host prerequisites + project wiring, concise OK/WARN/FAIL\naic status     # identity, modes, runtime, credential bridge, and volumes\naic validate   # managed provenance + fully resolved Compose security model\n```\n\n`doctor` can run before `init`; it checks Node 18+, Docker Engine 25+ and\nCompose 2.24+ (needed for volume subpaths), the selected local Unix socket,\nthe Dev Container CLI, Git/project-root shape, install integrity, and\ncontrol-path safety. Warnings remain exit 0; blockers exit nonzero. Standard,\nrootless, Colima, OrbStack, and Docker Desktop Unix-socket contexts are\ndiscovered automatically; remote TCP/SSH contexts, subdirectories below the\nGit root, and worktree-style checkouts are reported explicitly rather than\nfailing later with an opaque Compose error.\n\n`status` is a quick factual snapshot (including credential-bridge health) and\ntolerates a stopped daemon. `validate` is suitable for CI: it never prompts or\nrecords trust, honors an existing exact approval, and exits nonzero for managed\ndrift or an untrusted boundary expansion.\n\n### Choosing tools per project\n\nBy default `aic init` enables Claude Code, Codex, and OpenCode. To pick a subset, either answer the interactive checkbox prompt (↑/↓ move, space toggles, enter confirms) or pass `--with`:\n\n```bash\naic init --with claude-code                  # claude only\naic init --with codex                        # codex only\naic init --with opencode                     # opencode only\naic init --with claude-code,codex,opencode   # all three (same as the default)\n```\n\nThe selection is persisted as `containerEnv.AIC_TOOLS` in `.devcontainer/devcontainer.json`. `post-create.py` reads it to decide which tool's settings to seed, and the VS Code extensions list is filtered to match (the `anthropic.claude-code`, `openai.chatgpt`, and `sst-dev.opencode` extensions are dropped when their tool isn't selected). All three CLIs are still present in the image either way — you can re-enable a tool later with `aic sync --with claude-code,codex,opencode`. When stdin isn't a TTY (CI, piped installers), the prompt is skipped and all tools default to on.\n\n### Choosing a shell per project\n\n`aic init` also asks which interactive shell to use (or pass `--shell`). All three are pre-installed in the image:\n\n```bash\naic init --shell zsh                # default: oh-my-zsh + powerlevel10k + MesloLGS NF\naic init --shell bash               # barebones bash, history + fnm\naic init --shell fish               # barebones fish, fnm\n```\n\nThe choice is stored as `containerEnv.AIC_SHELL` in `.devcontainer/devcontainer.json`. `aic shell` launches that shell, and the VS Code terminal's default profile + font family are patched to match (zsh keeps `'MesloLGS NF', monospace` for p10k icons; bash/fish use plain `monospace` so you don't need a nerd font on the host). Change it later with `aic sync --shell bash`. When stdin isn't a TTY, the prompt is skipped and `zsh` is used.\n\n### VS Code\n\nIf you work in VS Code, you can skip `aic up` and `aic shell` after aic has\ngenerated the control files — the editor handles both:\n\n1. Install the **Dev Containers** extension `ms-vscode-remote.remote-containers`\n2. `aic init` in your project (one time).\n3. Open the project folder in the editor.\n4. `Cmd+Shift+P` → **Dev Containers: Reopen in Container**.\n\nThe generated initializer runs the same host validation and volume migration as\n`aic up`, sanitizes the host preference seeds in a networkless one-shot service,\nbrings up the devcontainer and socket-proxy, and drops you into an integrated\nterminal. `claude`, `codex`, and `opencode` are available immediately. The host\n`aic` CLI is required; the initializer checks common npm/Node-manager paths and\nprints one install command if a GUI-launched editor cannot find it. Step 2 is\nthe host-control-plane boundary: do not directly reopen a devcontainer supplied\nby an untrusted repository before aic has replaced and you have reviewed it.\n\nYou can still use `aic` from a separate terminal at the same time — `aic rebuild`, `aic destroy`, etc. operate on the same compose project as the editor, so the two paths don't conflict.\n\n## Claude Code plugin\n\nWiring aicontainer to a specific project is a handful of project-owned files — an\nLSP server on `PATH`, a writable `.venv` volume, a `Dockerfile.project` for\nPlaywright, host-service env (see [Per-project overrides](#per-project-overrides-that-survive-aic-sync)).\nThe optional **aicontainer** Claude Code plugin does that conversationally:\nit detects your stack, checks whether a headless Linux devcontainer even fits,\nthen proposes and writes those files for you — and offers to install the `aic`\nCLI first if it's missing. It also handles re-setup, auditing an existing\n`.devcontainer/` and updating only what's missing, stale, or drifted. It's a\nconvenience layer over `aic init` / `aic sync`, not a requirement.\n\nInstall it from inside Claude Code:\n\n```text\n/plugin marketplace add stefanoginella/aicontainer\n/plugin install aicontainer@aicontainer\n```\n\nThen run it from a Claude Code session **on your host** — not inside the sandbox,\nwhich mounts `.devcontainer/` read-only:\n\n```text\n/aicontainer:setup\n```\n\nIt shows you the plan, writes the files once you approve, and stops *before*\npulling the multi-gigabyte image — you run `aic up` (or \"Reopen in Container\")\nyourself.\n\nUninstall the plugin and drop the marketplace:\n\n```text\n/plugin uninstall aicontainer@aicontainer\n/plugin marketplace remove aicontainer\n```\n\n## What's in the box\n\n`aic init` ships an opinionated image. Knowing the defaults up front beats discovering them by surprise.\n\n**Security-driven defaults** (don't change casually — many are the actual sandbox boundary):\n\n- **npm hardening**: `NPM_CONFIG_IGNORE_SCRIPTS=true` blocks `postinstall` RCE, the most common supply-chain vector. `NPM_CONFIG_MIN_RELEASE_AGE=1` rejects any package published in the last 24h (mitigates fast-moving malicious releases — npm interprets the value in days). `audit=true`, `fund=false`.\n- **Root-managed Git and shell startup**: a networkless sanitizer extracts only\n  fixed, non-executable preferences (identity, line-ending, pull/push behavior,\n  and signing intent) from the host Git config. A narrow helper validates the\n  generated config and installs it once at `/etc/aic/user-config/gitconfig` as\n  `root:root 0444`; credential helpers, aliases, includes, hooks, remotes, and\n  command/path-bearing settings never cross. Zsh, Bash, and fish likewise start\n  from root-owned aicontainer profiles, never writable user or host rc files.\n- **PreToolUse hook** (Claude, Codex + OpenCode, fires even with bypass/auto-approve/allow on) blocks:\n  - reads of `.env*` files — via `Read`/`Edit`/`Write`/`Grep`/`Glob` and in Bash commands (allowing `.env.example|.sample|.template|.defaults`),\n  - `curl|sh` / `wget|bash` fetch-and-execute in Bash (including `| sudo bash`, `| tee | sh`, and `bash -c \"$(curl …)\"` variants),\n  - writes to `/etc/aic/`, `/workspace/.devcontainer/`, and the login-shell rc files (`~/.zshrc` / `~/.bashrc` / fish config + their `.local` includes) — defense-in-depth on top of the RO mounts and root-locks above.\n\n  One script (`/etc/aic/hooks/pre-tool-use.sh`) is the single source of truth for all three tools: Claude registers it in `settings.json`, Codex via a managed hook, and OpenCode via a small plugin (`opencode-guardrail.js`) that translates its tool calls and shells out to the same script.\n- **Forced AI sandbox settings** — root-managed policy, not writable user\n  config, enforces Claude `permissions.defaultMode=bypassPermissions` + hook,\n  Codex `approval_policy=never` + `sandbox_mode=danger-full-access` + managed\n  hook, and OpenCode `permission.\"*\"=allow` + guardrail plugin. See [Config\n  seeding](#config-seeding-from-the-host) for the preference allowlist.\n- **Reduced runtime privilege**: the devcontainer starts with every Linux\n  capability dropped, then receives only the small set required by UID/GID\n  startup, the fixed ownership helper, and its own network firewall. The raw\n  Docker socket is hidden behind a root-only path used solely to verify named\n  volumes; the agent talks only to the socket proxy.\n- **Container global gitignore** covers `.env*`, `.claude/`, `.codex/`, `node_modules/`, `.venv/`, `__pycache__/`, `.DS_Store` — fewer ways to accidentally commit a secret.\n- **No host credential forwarding**: no SSH-agent socket, API-key passthrough,\n  host `gh` token, or literal secrets from seeded tool/MCP config. You log in\n  once *inside* the container; tokens persist in hardened subpaths of\n  `aic-auth-global`. Because the SSH agent and `~/.ssh` are absent, use [`aic\n  signing`](#commit-signing) for a sandbox-only signing key.\n\n**Developer-experience defaults** (personal taste; override in `Dockerfile.project` if you disagree):\n\n- **Shell**: defaults to `zsh` + `oh-my-zsh` + `powerlevel10k` + `zsh-autosuggestions` + `zsh-syntax-highlighting`. `bash` and `fish` are also baked into the image (barebones, with history + fnm) — pick one at init time via `--shell zsh|bash|fish` (see [Choosing a shell per project](#choosing-a-shell-per-project)). When using zsh, p10k expects [MesloLGS NF](https://github.com/romkatv/powerlevel10k#meslo-nerd-font-patched-for-powerlevel10k) on your terminal (see Troubleshooting); bash/fish use plain `monospace`.\n- **Editor**: `$EDITOR=nano`, `$VISUAL=nano`. `vim` is installed but isn't default.\n- **Runtimes**: Python 3.13 via [`uv`](https://github.com/astral-sh/uv); Node 24 LTS via [`fnm`](https://github.com/Schniz/fnm) (so projects can override per-`.nvmrc`).\n- **CLI utilities**: `ripgrep`, `fd-find`, `fzf`, `tmux`, `jq`, `gh`, `docker` CLI (+ buildx, compose), `semgrep`, [`git-delta`](https://github.com/dandavison/delta) (wired in as `core.pager` and `interactive.diffFilter`).\n- **VS Code extensions** auto-installed when you open in the editor: `anthropic.claude-code`, `openai.chatgpt`, `sst-dev.opencode` (each gated by `AIC_TOOLS`), `eamodio.gitlens`, `pflannery.vscode-versionlens`, `BracketPairColorDLW.bracket-pair-color-dlw`, `vincaslt.highlight-matching-tag`, `yzhang.markdown-all-in-one`. Add your own per project (e.g. the Python or TypeScript editor stack) via [`.devcontainer/vscode-extensions` and `vscode-settings.json`](#project-specific-vs-code-extensions--settings).\n- **VS Code terminal settings**: default profile + font family follow the project's `AIC_SHELL` (zsh → `MesloLGS NF`; bash/fish → `monospace`), right-click pastes, only `http/https/mailto/vscode` link schemes opened (`file://` OSC 8 links suppressed to dodge [microsoft/vscode#211443](https://github.com/microsoft/vscode/issues/211443)).\n- **Misc env**: `PYTHONDONTWRITEBYTECODE=1`,\n  `PIP_DISABLE_PIP_VERSION_CHECK=1`, and\n  `GIT_CONFIG_GLOBAL=/etc/aic/user-config/gitconfig` (the validated root-managed\n  config).\n\nIf you want a different baseline, see [Installing extra tools](#installing-extra-tools) for the project-Dockerfile pattern — most of the dev-experience choices can be flipped in 2-3 lines there.\n\n## Installing extra tools\n\nTwo ways, depending on whether the tool is throwaway or part of the project.\n\n### (a) Ad-hoc inside the running container\n\nFor things you'll need for an hour:\n\n```bash\naic shell\nuv tool install <python-cli>      # ruff, semgrep, ...\nnpm install -g <node-cli>\n```\n\nThese are **wiped on `aic destroy` or `aic rebuild`**. Fine for exploration; not for things your project depends on.\n\n> Note: `sudo` inside the container is scoped to three fixed-purpose wrappers\n> (`aic-chown-volumes`, `aic-lock-user-config`, `aic-firewall`) — bare\n> `apt-get`, `chown`, etc. are denied. To install apt packages, use a reviewed\n> project Dockerfile (below) and `aic rebuild`.\n\n### (b) Persistent, in a project Dockerfile\n\nFor tools your project depends on — language runtimes, DB clients, linters teammates need too.\n\nCreate `.devcontainer/Dockerfile.project`:\n\n```dockerfile\n# Match the tag your .devcontainer/docker-compose.yml pins (set by `aic init`\n# to your installed aic version). This tag is project-owned, so `aic sync`\n# never rewrites it — after `npm update -g aicontainer`, sync re-pins\n# docker-compose.yml and WARNS that this FROM has drifted; run\n# `aic sync --bump-base` to rewrite it to match. (If it drifts and an override\n# build: points here, the stale base is what actually runs — see below.)\nFROM ghcr.io/stefanoginella/aicontainer:vX.Y.Z\n\nUSER root\nRUN apt-get update && apt-get install -y --no-install-recommends \\\n      postgresql-client redis-tools terraform \\\n    && rm -rf /var/lib/apt/lists/*\n\nUSER vscode\nRUN uv tool install ruff \\\n    && uv tool install pre-commit\n```\n\nPoint at it from the sync-safe\n`.devcontainer/docker-compose.override.yml`; never edit the managed Compose\nfile:\n\n```yaml\nservices:\n  devcontainer:\n    # Required: give the build its own tag. Compose names a build's output\n    # after whatever `image:` resolves to, and the managed Compose file\n    # resolves it to the SHARED ghcr.io/stefanoginella/aicontainer:vX.Y.Z —\n    # so without this line the build silently re-tags the base image on your\n    # machine and hands this project's image to every other aic project.\n    image: myproject-devcontainer:vX.Y.Z\n    build:\n      context: .\n      dockerfile: Dockerfile.project\n```\n\nRun `aic sync`, inspect the resolved warning, then `aic trust` once and `aic\nrebuild`. **`aic up` is not enough here:** it reuses the cached image\n(`pull_policy: missing`) and never runs the build, so the container comes up on\nthe plain base image with none of your additions. A project Dockerfile executes\nas root while the image is built and can\nreplace any sandbox helper, so aic intentionally treats every custom build as a\nhost-boundary expansion even when its `FROM` is the official base. The trust is\nfor the exact relevant config hash; changing the Dockerfile or override asks for\nreview again. The tools then survive rebuilds and are versioned with the project.\n\nThe example's `context: .` is deliberately bounded to `.devcontainer/`, so its\ncontents fit the persistent trust hash. A build context outside that directory\n(for example `context: ..`) can change through arbitrary project files; `aic\ntrust` therefore refuses to persist it, and each reviewed `aic up`/`rebuild`\nmust use `--allow-unsafe`.\n\n> If you ran `aic init --build`, use `FROM aicontainer-base:latest` and put only\n> `build.dockerfile: Dockerfile.project` in the override; the same explicit\n> trust step applies.\n\n**Rule of thumb:** if you'd be annoyed to reinstall it after every container rebuild, put it in `Dockerfile.project`. If you're just trying something, install ad-hoc.\n\n#### Recipe: Playwright (browser tests / automation / MCP)\n\nA browser is the one tool you *can't* add ad-hoc here: Chromium needs apt system libraries (and runtime `sudo apt` is blocked), and if you've enabled the [firewall](#opt-in-network-allowlist) the browser-download CDN isn't on the allowlist. `Dockerfile.project` sidesteps both — image builds run with full network, so Chromium is baked into the image and works offline afterward, even with the firewall on.\n\n```dockerfile\n# .devcontainer/Dockerfile.project\nFROM ghcr.io/stefanoginella/aicontainer:vX.Y.Z   # match your pinned tag\n\n# Pin to the Playwright version your project uses (the @playwright/test in\n# package.json), so the baked browser revision matches what resolves at runtime.\nARG PLAYWRIGHT_VERSION=1.50.0\n\nUSER root\n# Chromium's system libraries. apt is root-only and runtime `sudo apt` is\n# blocked, so this step has to live in the image.\nRUN export PATH=\"$FNM_DIR:$PATH\" && eval \"$(fnm env)\" \\\n    && npx --yes playwright@${PLAYWRIGHT_VERSION} install-deps chromium\n\nUSER vscode\n# Download Chromium into ~/.cache/ms-playwright, baked into the image layer.\n# This explicit step is REQUIRED: the base image sets NPM_CONFIG_IGNORE_SCRIPTS\n# =true, so `npm i @playwright/test` won't auto-download the browser via its\n# postinstall — you have to run `playwright install` yourself.\nRUN export PATH=\"$FNM_DIR:$PATH\" && eval \"$(fnm env)\" \\\n    && npx --yes playwright@${PLAYWRIGHT_VERSION} install chromium\n```\n\nUse the project-owned override `build:` block shown above, then `aic sync`,\n`aic trust`, and `aic rebuild`.\n\n- **If Chromium won't launch, disable its sandbox.** Depending on your Docker runtime's capability/seccomp setup, Chromium's own sandbox may fail to start inside the container. If you hit launch errors, set `chromiumSandbox: false` in `playwright.config.ts` (or pass `--no-sandbox` for ad-hoc launches) — the standard Chromium-in-Docker fix.\n- **Testing `localhost` needs no firewall change** — loopback is always allowed, so driving your own dev server works even with the allowlist enabled. Only pointing the browser at the public internet (with the firewall on) means adding hosts to `.devcontainer/firewall-allowlist`.\n- **Playwright [MCP](https://github.com/microsoft/playwright-mcp)** (`@playwright/mcp`) reuses the same baked Chromium — just add it to `mcpServers` (it's seeded from your host config like any other MCP). One recipe covers both `playwright test` and MCP-driven browsing.\n\n## Per-project overrides that survive `aic sync`\n\n`devcontainer.json` and `docker-compose.yml` are **template-managed** — `aic\ninit` writes them and `aic sync` overwrites them. Tool, shell, and explicitly\nconsented Docker modes are re-applied; hand edits are not.\n\n> `aic` also drops a **`.devcontainer/README.md`** into every project spelling out this exact managed-vs-project-owned split — it's there mostly so an AI agent poking at the devcontainer edits the right files (and learns it can't edit `devcontainer.json`) instead of fighting the sync. That README is itself template-managed, so don't edit it either; the project-owned files below are where customization lives.\n\nInstead, drop a **`.devcontainer/docker-compose.override.yml`**. It's\nproject-owned: aic never overwrites it, automatically re-wires it on sync, and\nvalidates the fully resolved result before any startup command. Ordinary env\nand named-volume data mounts under `/workspace` or `/home/vscode/.cache` remain\nfrictionless. Host binds, bounded custom images/builds, devices, capabilities,\nnamespaces, external resources, or non-loopback published ports require an\nexact-config `aic trust` approval stored outside the repo. A build context\noutside `.devcontainer/` is unbounded and instead requires `--allow-unsafe` on\neach reviewed `up`/`rebuild`.\n\nLiteral application environment values remain prompt-free. Active Compose\n`$HOST_VAR` / `${HOST_VAR}` expressions and bare pass-through entries such as\n`environment: [HOST_TOKEN]` require the same one-time trust because they forward\ndata from the host shell; validation names the variable but never prints its\nresolved value. Use `$${VAR}` when the container should receive literal template\ntext. Overrides of managed startup variables (`PATH`, tool homes, Git/shell\nconfig, loader variables, or `DOCKER_HOST`) also require review because they can\nbypass the sandbox's startup and isolation wiring.\n\nThis is the right home for anything you'd otherwise have put in `containerEnv` or the compose service — env vars, `extra_hosts`, extra mounts, ports:\n\n```yaml\n# .devcontainer/docker-compose.override.yml\nservices:\n  devcontainer:\n    environment:\n      # Reach a dev stack running on the HOST (Compose env outranks the mounted\n      # .env for libraries like pydantic-settings, so these win in-container\n      # while the host keeps using .env's localhost).\n      DATABASE_URL: postgresql://user:pass@host.docker.internal:5432/mydb\n      VALKEY_URL: redis://host.docker.internal:6379/0\n    # Docker Desktop (macOS/Windows) resolves host.docker.internal automatically.\n    # On a Linux host, add it explicitly:\n    # extra_hosts:\n    #   - \"host.docker.internal:host-gateway\"\n```\n\nRun `aic sync` after first creating the override, inspect `git diff`, then `aic\nrebuild`. If the validator reports a deliberate boundary expansion, run `aic\ntrust` after reviewing it.\n\n> The same file is also the sync-safe place to point at a [`Dockerfile.project`](#b-persistent-in-a-project-dockerfile): put the `build:` block in the override instead of editing `docker-compose.yml`. Compose merges `build:` onto the base service; `aic rebuild` refreshes the base image, then rebuilds your layer on top.\n\n### Persisting a named volume (and fixing its ownership)\n\nA common override is a **named volume** over a build artifact you don't want on the bind-mounted workspace — a Python `.venv`, `node_modules`, a language cache — so it persists across rebuilds and dodges the macOS bind-mount performance hit:\n\n```yaml\n# .devcontainer/docker-compose.override.yml\nservices:\n  devcontainer:\n    volumes:\n      - myproject-venv:/workspace/.venv\n      - myproject-uv-cache:/home/vscode/.cache/uv\nvolumes:\n  myproject-venv:\n  myproject-uv-cache:\n```\n\nThere's a catch: Docker initializes a **fresh named volume as `root:root`**, and `updateRemoteUserUID` only remaps the user *inside* the container, not the daemon's volume-init UID. So `vscode` can't write into the mount and your `uv` / `npm` install fails. (You can't fix this with `sudo chown` from inside — in-container sudo is scoped to three aic helper scripts, not general `chown`.)\n\nThe sync-safe fix is a project-owned **`.devcontainer/chown-paths`** — one mountpoint per line; `aic-chown-volumes` re-owns each to `vscode` on container creation:\n\n```\n# .devcontainer/chown-paths — re-owned to vscode on container create.\n# Only paths under /workspace/ or /home/vscode/.cache/ are honored.\n/workspace/.venv\n/home/vscode/.cache/uv\n```\n\nLike `firewall-allowlist`, this file is opt-in, survives sync, and is read-only\ninside the container. The privileged helper accepts only canonical, exact\nDocker named-volume mountpoints under `/workspace/` or\n`/home/vscode/.cache/`; it asks the daemon through a root-only socket for the\ncurrent container's mount metadata and rejects host binds, symlinks, nested\nbinds, external/custom drivers, and `local` volumes with bind-capable options.\nKeep tool caches under `~/.cache/` so they fit this boundary.\n\n> Already created the volume root-owned from an earlier run? `aic-chown-volumes` fixes it on the next `aic rebuild`. If it was populated by a partial install, `docker volume rm <name>` once and let it re-init clean.\n\n### Project-specific post-create steps\n\nNeed to run something on every container creation — `lefthook install`, `pre-commit install`, `npm ci`, seeding a local DB? Don't edit `devcontainer.json`'s `postCreateCommand` (clobbered every sync) or `post-create.py` (it's baked into the image and isn't even in your repo in pull mode). Drop a **`.devcontainer/post-create.project.sh`**:\n\n```bash\n# .devcontainer/post-create.project.sh — runs as `vscode`, cwd /workspace,\n# after all aic setup, on every container create. Opt-in by presence.\n#!/usr/bin/env bash\nset -euo pipefail\nlefthook install\n```\n\nThe base `post-create.py` runs it last, after the AI tools, git config, and volume ownership are all wired up, so your steps see a fully configured environment. Like `firewall-allowlist` and `chown-paths`, it's opt-in (run only if present), never touched by `aic sync`, and read-only inside the container — the [PreToolUse hook](#threat-model) blocks an in-container tool from editing anything under `.devcontainer/`, so the script stays host-only-editable. It's invoked via `bash <file>` (no executable bit needed), runs with no privilege the in-container agent doesn't already have, and a non-zero exit is logged as a warning during `aic up` without failing container creation — its output streams through so you can see what happened.\n\n### Personal shell config\n\nWant your familiar zsh prompt and aliases inside the sandbox? The container's `~/.zshrc` is deliberately root-managed (so an in-container agent can't tamper with shell startup), so you don't edit it directly — you drop an **overlay** that's installed root-owned and **sourced last**, so your prompt/aliases win over the managed baseline (history, `fnm`, `PATH` still run first). zsh only.\n\nTwo files, both opt-in by presence, both never touched by `aic sync`:\n\n- **`.devcontainer/shell-rc.zsh`** — personal zsh startup: aliases, functions, exports, prompt tweaks.\n- **`.devcontainer/p10k.zsh`** — a [powerlevel10k](https://github.com/romkatv/powerlevel10k) config (the output of `p10k configure`).\n\n```zsh\n# .devcontainer/shell-rc.zsh\nalias gs='git status'\nalias ll='ls -lah'\nexport EDITOR=nvim\n```\n\nPrefer your **host** config instead of committing one per repo? Copy it into the aic-owned seed dir once and every project picks it up:\n\n```bash\nmkdir -p ~/.config/aicontainer\ncp ~/.p10k.zsh ~/.config/aicontainer/p10k.zsh     # your host p10k prompt\ncp ~/.zsh_aliases ~/.config/aicontainer/rc.zsh    # or any personal rc snippet\n```\n\nThe host seed is read **read-only** by the seed sanitizer and copied verbatim; a project-owned `.devcontainer/` file wins over it when both exist. Run `aic sync` (host-side) then `aic rebuild`.\n\n> ⚠️ **These files are copied verbatim — they can't be sanitized like the JSON configs.** They're shell *code*, executed inside a sandbox an autonomous agent can read. **Don't put secrets in them** (no tokens, no `export API_KEY=…`). Keep them to prompt/alias cosmetics. They run only as the unprivileged `vscode` user and, once installed, are root-locked so the agent can't modify them.\n\n### Personal Claude Code statusline\n\nYour host `statusLine` setting is **not** seeded — it's an arbitrary command string pointing at a host path that doesn't exist in the container (see [threat model](#threat-model)). Bringing your statusline in works like the shell overlay above: you hand aicontainer the **script**, and aicontainer supplies the command.\n\nDrop one file, named by the interpreter you want:\n\n| File | Run as |\n| --- | --- |\n| `statusline.sh` | `bash` |\n| `statusline.mjs` | `node` (ESM) |\n| `statusline.js` | `node` (CommonJS) |\n| `statusline.py` | `python3` |\n\nHost-global (every project on this machine):\n\n```bash\nmkdir -p ~/.config/aicontainer\ncp ~/.claude/statusline/statusline.mjs ~/.config/aicontainer/statusline.mjs\naic rebuild\n```\n\nOr per-project, as `.devcontainer/statusline.mjs` — the project file wins when both exist. Same filename in both places (unlike `rc.zsh` / `shell-rc.zsh`).\n\nOn the next create, post-create installs the script `root:root 0444` at `/etc/aic/user-config/statusline/`, and sets Claude's `statusLine.command` to the fixed managed launcher `/usr/local/bin/aic-statusline`, which picks the interpreter from that filename. **No string from your host settings is ever executed** — only your script file crosses, and the command aic writes is its own constant.\n\nNotes that matter in practice:\n\n- **One file, no bundle.** A statusline that `import`s sibling modules won't find them; vendor it into a single file (your script may still read/write its own state under `~/.claude/statusline/`, which is precreated and per-project).\n- **`node` and `python3` are the container's.** Anything your script shells out to must exist in the sandbox — `git` and the usual CLI tools do; host-only binaries don't.\n- **The single source of truth trick:** keep the real script at `~/.config/aicontainer/statusline.mjs` on the host and point your *host* `~/.claude/settings.json` at that same path, so host and sandbox never drift.\n- Claude Code only — Codex and OpenCode have no equivalent.\n\n> ⚠️ Same rule as the shell overlay: **copied verbatim, readable by the agent, no secrets.** It runs as the unprivileged `vscode` user, and once installed it's root-locked so the agent can't modify it — but its bytes (including any host paths or usernames baked into it) are visible inside the sandbox.\n\n### Agent status relay\n\nWant a Mac dashboard, Stream Deck-style controller, or spare-tablet service\nscreen to show which Claude Code and Codex sessions are working or waiting?\naicontainer can emit lifecycle hints from sessions started in a terminal **or\nthe VS Code sidebars**. The integration uses each tool's managed hooks\n([Claude Code hooks](https://code.claude.com/docs/en/hooks), [Codex\nhooks](https://learn.chatgpt.com/docs/hooks)), so the editor location does not\nchange the event source.\n\nRun a receiver on the Mac that accepts `POST /events` on port `8787`, then opt\nin globally on that host:\n\n```bash\nmkdir -p ~/.config/aicontainer\nprintf 'enabled\\n' > ~/.config/aicontainer/status-relay\naic rebuild\n```\n\nExisting projects need a recreate once; future `aic init`, `aic sync`, and VS\nCode initialization refresh the mode automatically. To opt out, delete the\nmarker and rebuild. The marker must be a regular, non-symlinked file containing\nexactly `enabled` plus a newline. A repository `.env` or Compose override cannot\nsilently turn the relay on, change its identity, or redirect it. `aic status`\nreports the host marker and the value the project actually runs with, so a\nmarker written but not yet applied shows as `pending aic rebuild`.\n\nEvery callback goes to the non-configurable URL\n`http://host.docker.internal:8787/events`, ignores proxy environment variables\nand redirects, and fails open: no listener, malformed hook input, DNS failure,\nor HTTP error is swallowed and never changes agent behavior. The 500 ms\ntimeout covers the connection itself, not the preceding name lookup — a host\nresolver that blackholes `host.docker.internal` instead of answering is\nbounded by each tool's own hook timeout (a couple of seconds), so keep the\nname either resolvable or absent.\n\nOn Docker Desktop for macOS/Windows, `host.docker.internal` is built in. Linux\nusers must expose the host gateway (usually an `extra_hosts` entry for\n`host.docker.internal:host-gateway`, reviewed with `aic trust`). If the opt-in\nnetwork allowlist is active, aic permits only TCP 8787 to that resolved\nhost-gateway address — it does not add the host to the general allowlist. When\nthe name does not resolve, the firewall warns and simply omits that one rule;\nan unreachable dashboard never costs the project its outbound allowlist.\n\nThe JSON contract is deliberately small:\n\n```json\n{\n  \"schema_version\": 1,\n  \"source\": \"aicontainer\",\n  \"provider\": \"codex\",\n  \"project\": \"my-api\",\n  \"project_id\": \"aic-my-api-0123456789ab\",\n  \"session_id\": \"session-uuid\",\n  \"event\": \"UserPromptSubmit\",\n  \"state\": \"working\",\n  \"occurred_at\": \"2026-08-24T10:00:00.000Z\",\n  \"model\": \"optional-model-name\"\n}\n```\n\n`UserPromptSubmit` maps to `working`; start, permission/input notifications,\nelicitation, and normal stop map to `waiting`; a mid-turn compaction or\nelicitation response returns to `working`; Claude `StopFailure` maps to `error`;\n`SessionEnd` maps to `ended`. Claude notification events may also add\n`notification_type`. The allowlist above is exhaustive: **prompt and response\ntext, tool names/inputs/results, working directory, transcript path, error\ndetails, and credentials are never forwarded.**\n\nTreat these events as untrusted display hints: code running inside the\ncontainer can forge a POST to any reachable status listener. Keep ingestion\nwrite-only and harmless. In particular, do not put macro execution, shell\ncommands, or Spotify credentials behind this same unauthenticated route; serve\ntablet controls through a separate authenticated host-side API. Hooks run in\nthe background where the tool permits it, so the receiver should apply events\nby `occurred_at`, treat `ended` as terminal for that session ID, and expire\nstale sessions after a reasonable idle period.\n\n### Project-specific VS Code extensions & settings\n\n`devcontainer.json` is the only place that auto-installs editor extensions and applies machine-scope settings, but it's **regenerated wholesale on every `aic init`/`aic sync`** — so hand-editing its `customizations.vscode` block doesn't survive (and an in-container agent can't edit anything under `.devcontainer/` at all). Two project-owned files are merged in instead, both opt-in by presence and never touched by sync:\n\n- **`.devcontainer/vscode-extensions`** — one [extension id](https://marketplace.visualstudio.com/) (`publisher.name`) per line, `#` comments allowed. Merged into `customizations.vscode.extensions`, so they auto-install when you reopen in the container.\n- **`.devcontainer/vscode-settings.json`** — a strict JSON object, parsed and\n  re-serialized before merging. Invalid input is warned and skipped, and keys\n  owned by aic are ignored with a warning; put intentional overrides in the repo's\n  `.vscode/settings.json`, whose workspace scope wins.\n\n```\n# .devcontainer/vscode-extensions\nms-python.python\nms-python.vscode-pylance\n```\n\n```jsonc\n// .devcontainer/vscode-settings.json\n{\n  \"python.defaultInterpreterPath\": \"/workspace/.venv/bin/python\"\n}\n```\n\nRun `aic sync` (host-side) then `aic rebuild`; verify with `grep ms-python .devcontainer/devcontainer.json`. Invalid extension lines (anything that isn't a `publisher.name` id) are warned about and skipped, so a stray line can't smuggle JSON into `devcontainer.json`.\n\n> **Conflict rule:** the merge lands your entries *before* aic's own, so on a key collision aic's default wins *inside `devcontainer.json`*. The common case (adding new keys like `python.*`) never collides. To override a key aic sets (e.g. a `terminal.integrated.*` value), use a standard workspace **`.vscode/settings.json`** — workspace settings beat devcontainer machine-scope settings, survive sync on their own, and aren't aic-managed.\n\n#### Recipe: Python LSP (editor **and** agent)\n\nThere are two LSP surfaces. The **editor's** IntelliSense comes from the extensions + settings below. The **agent's** LSP tool (Claude Code's go-to-def / find-refs) is separate: it needs the `pyright-langserver` binary on `PATH`, which you install from [`post-create.project.sh`](#project-specific-post-create-steps) so it survives rebuilds:\n\n```\n# .devcontainer/vscode-extensions\nms-python.python\nms-python.vscode-pylance      # editor IntelliSense / LSP\ncharliermarsh.ruff            # if the project uses ruff\nms-python.mypy-type-checker   # if mypy is your type gate\n```\n\n```jsonc\n// .devcontainer/vscode-settings.json\n{\n  \"python.defaultInterpreterPath\": \"/workspace/.venv/bin/python\",\n  \"ruff.importStrategy\": \"fromEnvironment\",\n  \"mypy-type-checker.importStrategy\": \"fromEnvironment\",\n  \"python.analysis.typeCheckingMode\": \"off\"  // mypy is the type gate; Pylance for nav only\n}\n```\n\n```bash\n# .devcontainer/post-create.project.sh — give the agent's LSP tool a Python server\ncommand -v pyright-langserver >/dev/null || npm i -g pyright || echo \"[post-create] pyright install failed\"\n```\n\n> Install `pyright`, **not** `basedpyright` — Claude Code's LSP tool looks for the `pyright-langserver` binary, which the `pyright` package provides (`basedpyright` ships `basedpyright-langserver`).\n\n#### Recipe: Stop VS Code auto-activating a `.venv` in the terminal\n\nWith the Python extension installed (e.g. from the recipe above) **and** a project `.venv`, VS Code auto-activates it by *typing and running* `source /workspace/.venv/bin/activate` in every new integrated terminal. In this container the terminal mostly exists to launch AI CLIs, so that injected line lands at the prompt and clobbers the command you're starting (`claude`, `opencode`, `codex`). Turn it off — the first key covers the classic `ms-python.python`, the second the newer **Python Environments** extension (whose default `command` mode is the usual culprit):\n\n```jsonc\n// .devcontainer/vscode-settings.json\n{\n  \"python.terminal.activateEnvironment\": false,\n  \"python-envs.terminal.autoActivationType\": \"off\"\n}\n```\n\nThen `aic sync` (host-side) and `aic rebuild`. This is the editor injecting *and running* the line — distinct from the harmless Claude Code prompt *pre-fill* covered in [Troubleshooting](#troubleshooting), which never executes.\n\n#### Recipe: TypeScript / JavaScript LSP (editor **and** agent)\n\nVS Code bundles the TypeScript language service with the editor, so the editor half is mostly lint/format extensions. The agent's LSP tool wants the `typescript-language-server` binary on `PATH`:\n\n```\n# .devcontainer/vscode-extensions\ndbaeumer.vscode-eslint\nesbenp.prettier-vscode\n```\n\n```jsonc\n// .devcontainer/vscode-settings.json\n{\n  \"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n  \"editor.formatOnSave\": true,\n  \"eslint.format.enable\": true\n}\n```\n\n```bash\n# .devcontainer/post-create.project.sh — give the agent's LSP tool a TS server\ncommand -v typescript-language-server >/dev/null || npm i -g typescript typescript-language-server || echo \"[post-create] ts language server install failed\"\n```\n\n> Claude Code's built-in LSP tool reads the binary off `PATH` (on older Claude releases it's gated behind `ENABLE_LSP_TOOL=1`). The baked Node toolchain plus a global `npm i -g` is enough — no Dockerfile change needed.\n\n## Updating AI tools\n\nClaude Code, Codex and OpenCode refresh to their latest release **on every `aic\nrebuild`**, in both pull and build mode: `post-create.py` runs `claude update`,\nreruns Codex's official unattended installer, and runs `opencode upgrade` each\ntime the container is (re)created. The pinned image is just the baseline they're\nlayered on.\n\n```bash\naic rebuild   # in a project: recreate the container → all enabled CLIs update to latest\n```\n\nThe refresh is fail-soft — with no network it keeps the version baked into the image\nand the container still comes up. For a fully reproducible sandbox, pin the tools too\nby setting `AIC_FREEZE_TOOLS=1` in `.devcontainer/docker-compose.override.yml`.\n\n> Codex and OpenCode install via their official standalone installers (not npm),\n> mirroring Claude's native installer. Codex refreshes by rerunning its installer\n> noninteractively; OpenCode uses `opencode upgrade`. Neither CLI is subject to\n> the `NPM_CONFIG_MIN_RELEASE_AGE` npm quarantine (which still governs npx-based\n> MCP servers).\n\nTo update **aicontainer itself** — the `aic` CLI, the template, and the pinned base\nimage (base OS, Node, semgrep, hooks, …):\n\n```bash\nnpm update -g aicontainer   # latest aic + template\naic sync                    # in each project: re-pin compose to the new aic version\naic rebuild                 # in each project: pull the new image\n```\n\nThe pull-mode compose file pins `ghcr.io/stefanoginella/aicontainer:vX.Y.Z` to whatever aic version did `aic init` (or the last `aic sync`) — not `:latest`. This keeps the CLI and the in-container filesystem layout (hooks, sudoers, helper scripts) from drifting apart. To pick up a new image, bump aic and `aic sync` first; `aic rebuild` alone won't change the pinned tag.\n\naic nudges you when those versions drift, so a stale container doesn't go unnoticed:\n\n- **`aic up` / `aic shell` / `aic rebuild`** print a warning (offline, no network) when this project's pinned image tag and your installed `aic` disagree — exactly the state you land in after `npm update -g aicontainer` before you've re-synced. The fix it points at is `aic sync && aic rebuild`. On `aic rebuild` it fires *before* the pull — handy, because `rebuild` re-pulls the currently pinned tag, so you can abort and `aic sync` first instead of re-fetching the stale image. (Build-mode projects have no pinned tag, so they aren't checked.)\n- **VS Code \"Reopen / Rebuild in Container\"** uses the aic-generated host-side\n  initializer for the same drift check, fail-closed config validation, seed\n  preparation, and legacy-session migration. Output lands in the **Dev\n  Containers output channel**. A missing host CLI stops with an actionable\n  install command because silently skipping it would also skip the security\n  boundary. The direct-bootstrap caveat above still applies to repo-supplied\n  control files.\n- **`aic version` / `aic upgrade`** tell you when a newer `aicontainer` has been published to npm. This check is cached for a day, fails silently when offline, and is skipped in CI.\n\nSet `AIC_NO_UPDATE_CHECK=1` to silence both.\n\n`:vX.Y.Z` tags are immutable once published — they capture the exact image\nbuilt at release time. CI separately rebuilds the floating `:latest` and a\nweekly tag with refreshed base layers and no stale build cache; managed\nprojects stay on immutable version tags. If you consciously prefer the floating\ntrack, use a reviewed `Dockerfile.project` based on `:latest` rather than\nediting the managed Compose file. In `--build` mode `aic rebuild` performs a\nno-cache local build too.\n\nThe managed files under `.devcontainer/` are not refreshed by `aic rebuild`\nalone. After upgrading, run `aic sync` and review the diff, then rebuild. Sync\npreserves tool/shell selections and a previously consented Docker mode, leaves\nall project-owned files untouched, and switches modes cleanly without stale\nbuild artifacts.\n\nThe same sync migrates old basename-scoped projects to a deterministic Compose\nname derived from the canonical project path. On the next sync/up/VS Code open,\naic automatically copies the legacy transcript volume only when an existing\ncontainer's exact workspace/project labels and session mount prove ownership,\nwith no differently owned container also mounting it; it likewise stops only a\nlegacy stack with an exact owned primary and no conflicting owner or unknown\nservice (known unlabeled aic sidecars are allowed; arbitrary orphans are never\nremoved). If no container remains to disambiguate a historically shared\nbasename volume, sync leaves it untouched and the next interactive `aic up`\nasks once whether to import it (default no starts fresh and preserves the old\nvolume). A direct VS Code or other non-interactive start stops with that same\n`aic up` hint rather than risking cross-project transcript disclosure.\nOwnership-proven upgrades need no re-login or manual volume command, and two\ncheckouts with the same folder name no longer collide. The legacy container-side\n`~/.claude-sessions` layout is likewise migrated to the tool-neutral\n`~/.aic-sessions` volume path.\n\n> **Upgrade friction:** for an ordinary or ownership-proven project the whole\n> migration is still\n> `npm update -g aicontainer && aic sync && aic rebuild`. Existing logins,\n> transcripts, and tool/shell choices carry forward. Older releases had no\n> outside-repository Docker consent record, so their inherited Docker exposure\n> resets once to `none`; only users who need it re-enable it with `aic sync\n> --docker-read` or `aic sync --docker`. An ambiguous historical basename\n> volume adds the other one-time decision; clean generated projects add no\n> prompt.\n\n## Multi-project model\n\n> **Your work survives without crossing projects.** Claude/Codex transcripts and\n> prompt history, OpenCode's database/checkpoints, and user-level instruction,\n> skill, command, rule, prompt, and plugin surfaces live in a path-unique\n> **per-project named volume** (`aic-<folder>-<path-hash>_aic-sessions`). They\n> survive `up`/`rebuild`, are never written into the host home, and are removed\n> only by the explicitly confirmed `aic destroy`.\n\n| Data | Scope | Storage |\n|---|---|---|\n| Claude/Codex/OpenCode login state; `gh`, npm and Semgrep login; sandbox signing key | **Global** | Fixed subpaths of `aic-auth-global` |\n| Shell command history entered inside aicontainer | **Global** | `aic-shell-history` (host history is never mounted) |\n| Claude/Codex transcripts and prompt history | **Per-project** | `<path-unique-project>_aic-sessions` |\n| Claude/Codex user config, memory, skills, agents/commands, rules/prompts, plugins | **Per-project** | Whole tool homes below the same sessions volume |\n| OpenCode config/instructions, session db, storage, and snapshots | **Per-project** | Same sessions volume; its two credential files are synchronized globally |\n| Sanitized host preferences | **Per-project, regenerated** | `<path-unique-project>_aic-sanitized-seed`, read-only to the agent |\n| Project source | Host bind | The current canonical project root at `/workspace` |\n\nThe unrestricted devcontainer never mounts the global Claude, Codex, or\nOpenCode directories. Instead, each canonical tool home is a symlink into\n`~/.aic-sessions/tool-homes/` in the current project's volume. A dedicated\nnetworkless, capability-free sidecar is the only service that sees both those\nhomes and the three global tool-auth subpaths. It continuously reconciles four\nexact files — Claude `.credentials.json`, Codex `auth.json`, and OpenCode\n`auth.json` / `account.json` — so login, logout, and token refresh propagate\nwithout sharing any other filename.\n\nThe bridge accepts only owner-matched, single-link, bounded JSON objects,\ncopies them atomically as mode `0600`, and ignores unsafe/malformed paths. Its\ninitial newer-wins reconciliation completes before the devcontainer starts.\nGitHub/npm/signing/Semgrep use their own fixed global subpath mounts; the broad\nauth-volume root is never exposed.\n\nThis preserves the easy part — log in once, work on twenty projects — while\nremoving cross-project prompt and transcript bleed. The deliberate remaining\ntrade-off is credentials: a compromised session in any project can use the\nshared tokens you logged into inside aicontainer. Prefer least-privilege OAuth\ngrants and a fine-grained `gh` PAT. Global shell history is also readable by\nevery project; do not type secrets into shell commands.\n\n### Config seeding from the host\n\nRaw host config is never mounted into the unrestricted devcontainer. Before it\nstarts, a fixed root-only service with no network, no workspace, a read-only\nroot filesystem, and no auth/session mounts reads exactly four files:\n`~/.gitconfig`, `~/.claude/settings.json`, `~/.codex/config.toml`, and\n`~/.config/opencode/opencode.json`. It emits four root-owned JSON objects into a\nper-project volume; the long-running agent receives that volume read-only.\n\nIt also reads the opt-in `~/.config/aicontainer/` directory, whose fixed\nfilenames (`rc.zsh`, `p10k.zsh`, `statusline.{sh,mjs,js,py}`) are *code* and so\nare copied verbatim rather than allowlisted — they exist only because you put\nthem there, and they land root-owned and read-only. The host `aic` CLI separately\nrecognizes the exact `status-relay` enable marker in that directory; its bytes\nare not copied into the container. The sanitizer reads no other filename.\n\nThe sanitizer copies only known preference fields and recursively removes\nliteral credential-bearing keys such as `env`, `headers`, `authorization`, API\nkeys, tokens, secrets, and passwords. Security-critical behavior is enforced\nseparately at root-managed precedence:\n\n| Field | Container always sets |\n|---|---|\n| Claude `permissions.defaultMode` | `bypassPermissions` |\n| Claude hook/policy | `/etc/claude-code/managed-settings.json` |\n| Codex `approval_policy` | `never` |\n| Codex `sandbox_mode` | `danger-full-access` |\n| OpenCode `permission` | `{ \"*\": \"allow\" }` |\n| OpenCode policy/plugin | `/etc/opencode/opencode.json` + the shared guardrail |\n\nCodex's guardrail and lifecycle hooks live in `/etc/codex/requirements.toml`\nwith a root-managed hook directory; a user hook would be trust-gated and\nskipped in autonomous mode. Claude and OpenCode use their supported\nsystem-managed configuration. All three tools dispatch guardrail events to the\nsame root-owned policy script; Claude and Codex separately dispatch their\nopt-in status events to the metadata-only relay.\n\nSeeded preferences include Claude model/theme/editor/effort and MCP/plugin\nmetadata; Codex model/personality plus `[features]`, `[notice]`, `[projects.*]`,\nand `[mcp_servers.*]`; OpenCode provider/model/MCP/agent/instruction/theme/\nkeybind/formatter/LSP definitions; and a fixed non-executable set of Git\nidentity/workflow preferences.\n\nDropped fields include Claude permissions/hooks/auth helpers; Codex approval,\nsandbox, and hooks; OpenCode permission/plugin and inline provider secrets; MCP\nliteral env/header credentials across all three; and every executable or\npath-bearing Git key (`include`, aliases, credential helpers, hooks paths,\nSSH commands, remotes, pagers/editors, signing-key paths). Git identity and safe\npreferences are validated again before a fixed helper installs them once as\n`root:root 0444`.\n\n**MCPs:** metadata is seeded for all three tools. Host-only binaries will not\nexist in Linux; URL-based and npm-installed servers generally work. Literal MCP\nenv/header credentials are deliberately removed, so authenticate inside the\nsandbox or reference an in-container environment variable. Claude, Codex, and\nOpenCode user config is project-scoped and reconciled from the sanitized seed\non recreate; root-managed policy remains separate from those writable homes.\n\n**Providers (OpenCode):** custom provider/model definitions carry over, but\nsecret-looking provider keys are stripped recursively. Run `opencode auth\nlogin` inside once; that credential persists globally.\n\n**Command-bearing config is never seeded:** Claude's `statusLine`, tool `hooks`,\n`apiKeyHelper`, and the gitconfig `credential.helper` / aliases / includes are\nall dropped rather than rewritten — an allowlist that admits one arbitrary\ncommand string is not an allowlist. A personal statusline comes in through the\nopt-in verbatim overlay instead (see [Personal Claude Code\nstatusline](#personal-claude-code-statusline)): you provide the script, aic\ninstalls it root-locked and supplies its own fixed command.\n\n**Host paths not exposed to the agent:** none of the raw config files above,\nhost tool history/transcripts/credentials, shell rc files, `~/.ssh`, or the SSH\nagent. The container creates its own login state and project data in Docker\nvolumes. The only host files that cross verbatim are the ones you deliberately\nplace in `~/.config/aicontainer/` (`rc.zsh`, `p10k.zsh`, `statusline.*`), which\nland root-owned and read-only.\n\n## Commit signing\n\nIf you sign commits on your host (`commit.gpgsign=true`, SSH or GPG), that won't work inside the sandbox out of the box: your signing key lives on the host, and aicontainer deliberately does **not** forward `~/.ssh` or the SSH agent (see the [threat model](#threat-model)). Git would otherwise fail every commit with `Couldn't find key in agent`.\n\nSo when a signing host has no sandbox key set up, aicontainer turns signing **off inside the container** (commits succeed, unsigned) and prints a one-line notice — rather than letting `git commit` fail cryptically.\n\nTo get signed commits *without* weakening the boundary, provision a **sandbox-only signing key** with `aic signing`:\n\n```bash\naic up                 # the container must be running\naic signing auto       # mint an ed25519 signing key in the aic-auth-global volume\n                       #   (add --register to push its pubkey to GitHub via gh)\naic rebuild            # apply — post-create wires the key into the container gitconfig\n```\n\n`aic signing auto` prints the public key; register it on GitHub as a **Signing Key** (Settings → SSH and GPG keys → New → *Signing Key*, **not** Authentication), or pass `--register` to have `gh` do it (needs the `write:ssh_signing_key` scope). Other modes:\n\n- `aic signing byok` — install a *separate* signing key you provide (`aic signing byok < your_key`, or drop it at `~/.config/aic-auth/signing/id_ed25519`).\n- `aic signing disable` — keep commits unsigned in the sandbox (silences the notice).\n- `aic signing status` — show the current state.\n\nThe key lives only in the `aic-auth-global` volume (never on your host), is\nshared across all your projects (register once), and survives rebuilds. The\nchoice is applied on the next `aic rebuild`, when\n`/etc/aic/user-config/gitconfig` is validated and created as root-owned 0444 —\nthere is no live unlock/update primitive.\n\n> **What this means for \"Verified\".** The signing key lives where the AI runs, so commits the agent makes will show as **Verified** on GitHub. That's exactly right if your goal is satisfying a branch-protection *\"require signed commits\"* rule — but it is *not* a statement that a human reviewed the commit. If you want sandbox commits to stay distinguishable and independently revocable, use a distinct signing key (and optionally a distinct committer identity) for it.\n\n## Threat model\n\n**Sandboxed:**\n- **Filesystem**: the project is the only writable host path. Raw host tool/Git\n  config appears only in the isolated one-shot sanitizer; the agent sees its\n  fixed allowlisted JSON output read-only. Host home, shell startup files,\n  `~/.ssh`, agent sockets, package caches, and tool history are absent.\n- **Process namespace**: container processes don't see host processes.\n- **Runaway limit**: the devcontainer runs with `pids_limit: 4096` so a fork bomb or a stuck agent loop can't exhaust host PIDs. Raise it (or add `mem_limit` / `cpus`) in `docker-compose.override.yml` if a workload needs more.\n- **Docker daemon**: by default the digest-pinned proxy exposes only ping and\n  version — no container/image/network/volume list, inspect, logs, archive\n  reads, create, or build. `--docker-read` deliberately exposes object read\n  APIs (which can reveal unrelated container metadata, logs, and files);\n  `--docker` adds write/build and therefore permits host escape through a\n  privileged sibling. Both opt-ins require matching consent stored outside the\n  repository and survive sync until `--no-docker` revokes them.\n- **Runtime privilege**: all Linux capabilities are dropped before adding the\n  narrow helper/firewall set; `NET_RAW` stays absent. The raw Docker socket is\n  reachable only below a root-owned `0700` directory and is used by the fixed\n  ownership helper for bounded GET-only mount/volume inspection. The\n  unrestricted user uses the proxy, never that socket.\n- **Control plane**: `.devcontainer/`, `.git/config`, and `.git/hooks` are\n  read-only inside. Managed hooks, tool policy, Git config, and shell startup\n  live under root-owned system paths. Scoped sudo exposes only fixed-purpose\n  wrappers with hardcoded destinations; the volume helper additionally proves\n  each target is an ordinary named volume on the current container.\n- **Cloud metadata / link-local**: every create adds strengthen-only drops for\n  IPv4 link-local (`169.254.0.0/16`), Alibaba metadata\n  (`100.100.100.200`), IPv6 link-local (`fe80::/10`), and AWS IMDSv6\n  (`fd00:ec2::254`). These apply independently of the optional full allowlist.\n- **Untrusted-repo guard**: aic-launched paths reject symlinked control inputs,\n  verify every managed artifact, resolve all Compose layers without trusting a\n  grep, and check services, mounts, builds, capabilities, namespaces, devices,\n  ports, networks/volumes, includes/providers, ","readmeFilename":"README.md"}