{"_id":"@agenttrail/guardrails","_rev":"9-2b31c5ea8a19cc44ea79fbd8c58fda2c","name":"@agenttrail/guardrails","dist-tags":{"next":"0.0.1-rc.1","latest":"0.2.1"},"versions":{"0.0.1-rc.1":{"name":"@agenttrail/guardrails","version":"0.0.1-rc.1","license":"Apache-2.0","_id":"@agenttrail/guardrails@0.0.1-rc.1","maintainers":[{"name":"akarsh_a_s","email":"akarsh@techsuite.io"},{"name":"samc621","email":"samcorso10@gmail.com"}],"homepage":"https://github.com/agenttrailhq/guardrails#readme","bugs":{"url":"https://github.com/agenttrailhq/guardrails/issues"},"dist":{"shasum":"ad9f3dc03082d3abe46e2f6fd00ce3dc4f45c331","tarball":"https://registry.npmjs.org/@agenttrail/guardrails/-/guardrails-0.0.1-rc.1.tgz","fileCount":25,"integrity":"sha512-mW833PaGpHcpJQMNcCgKn6J6q873p1+43nEgQqWdJtlHoyuBqHPNOdq1N6QgrlqIAqLIdeEv3VoP8jS9N1OGKw==","signatures":[{"sig":"MEQCIFIxMKXZpIP4piPjsFtoloOvYANZuMOVgToaJo7R5+tFAiBeqPA62SLr9MYhQGXbe+PVYNP/LHGJ4LYhKMsPAuPpkQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@agenttrail%2fguardrails@0.0.1-rc.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1294474},"main":"./dist/index.cjs","type":"module","_from":"file:/tmp/pack/agenttrail-guardrails-0.0.1-rc.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.13"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./schema":{"types":"./dist/schema.d.ts","import":"./dist/schema.js","require":"./dist/schema.cjs"},"./guardrails":{"types":"./dist/guardrails.d.ts","import":"./dist/guardrails.js","require":"./dist/guardrails.cjs"}},"scripts":{"lint":"biome check .","test":"vitest run","build":"tsup","spell":"cspell --no-progress .","typecheck":"tsc --noEmit"},"_npmUser":{"name":"akarsh_a_s","email":"akarsh@techsuite.io"},"_resolved":"/tmp/pack/agenttrail-guardrails-0.0.1-rc.1.tgz","_integrity":"sha512-mW833PaGpHcpJQMNcCgKn6J6q873p1+43nEgQqWdJtlHoyuBqHPNOdq1N6QgrlqIAqLIdeEv3VoP8jS9N1OGKw==","deprecated":"Superseded by 0.0.2","repository":{"url":"git+https://github.com/agenttrailhq/guardrails.git","type":"git"},"_npmVersion":"10.9.8","description":"The agenttrail guard rule corpus, its self-contained schema, and its fixtures.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^3.25.17"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","cspell":"^8.19.4","vitest":"^4.1.7","typescript":"^6.0.3","@types/node":"^25.9.1","@biomejs/biome":"2.4.15"},"_npmOperationalInternal":{"tmp":"tmp/guardrails_0.0.1-rc.1_1789099138113_0.4398976539995929","host":"s3://npm-registry-packages-npm-production"}},"0.0.1":{"name":"@agenttrail/guardrails","version":"0.0.1","license":"Apache-2.0","_id":"@agenttrail/guardrails@0.0.1","maintainers":[{"name":"akarsh_a_s","email":"akarsh@techsuite.io"},{"name":"samc621","email":"samcorso10@gmail.com"}],"homepage":"https://github.com/agenttrailhq/guardrails#readme","bugs":{"url":"https://github.com/agenttrailhq/guardrails/issues"},"dist":{"shasum":"a2d4d102bb7707dbaa8f761f1eb2833166ace4eb","tarball":"https://registry.npmjs.org/@agenttrail/guardrails/-/guardrails-0.0.1.tgz","fileCount":25,"integrity":"sha512-XjQtO558QOq+6r9x8tJ+QLt2uJ02rJeWBArdIdp4aMbp1WZDnQRgAOKPzoLv5yNbkIzCubJcepy+LQm4hpGSnQ==","signatures":[{"sig":"MEUCIQDh6Ocy3hpAx2cvuELtiqBCtO2VPztl5s1Sbez/clQkhQIgQBTpL/8Z9TCg1wz7NAYCgRqUNrdOvhNXqaNretlcTZE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@agenttrail%2fguardrails@0.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1294429},"main":"./dist/index.cjs","type":"module","_from":"file:/tmp/pack/agenttrail-guardrails-0.0.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.13"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./schema":{"types":"./dist/schema.d.ts","import":"./dist/schema.js","require":"./dist/schema.cjs"},"./guardrails":{"types":"./dist/guardrails.d.ts","import":"./dist/guardrails.js","require":"./dist/guardrails.cjs"}},"scripts":{"lint":"biome check .","test":"vitest run","build":"tsup","spell":"cspell --no-progress .","typecheck":"tsc --noEmit"},"_npmUser":{"name":"akarsh_a_s","email":"akarsh@techsuite.io"},"_resolved":"/tmp/pack/agenttrail-guardrails-0.0.1.tgz","_integrity":"sha512-XjQtO558QOq+6r9x8tJ+QLt2uJ02rJeWBArdIdp4aMbp1WZDnQRgAOKPzoLv5yNbkIzCubJcepy+LQm4hpGSnQ==","deprecated":"Superseded by 0.0.2","repository":{"url":"git+https://github.com/agenttrailhq/guardrails.git","type":"git"},"_npmVersion":"10.9.8","description":"The agenttrail guard rule corpus, its self-contained schema, and its fixtures.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^3.25.17"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","cspell":"^8.19.4","vitest":"^4.1.7","typescript":"^6.0.3","@types/node":"^25.9.1","@biomejs/biome":"2.4.15"},"_npmOperationalInternal":{"tmp":"tmp/guardrails_0.0.1_1789099665558_0.03167899605548441","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@agenttrail/guardrails","version":"0.0.2","license":"Apache-2.0","_id":"@agenttrail/guardrails@0.0.2","maintainers":[{"name":"akarsh_a_s","email":"akarsh@techsuite.io"},{"name":"samc621","email":"samcorso10@gmail.com"}],"homepage":"https://github.com/agenttrailhq/guardrails#readme","bugs":{"url":"https://github.com/agenttrailhq/guardrails/issues"},"dist":{"shasum":"945c0e15b0039a9f26ccaee084e5f4eb05dd60e6","tarball":"https://registry.npmjs.org/@agenttrail/guardrails/-/guardrails-0.0.2.tgz","fileCount":25,"integrity":"sha512-meHd9XaPtceLEKJvVpb9SkO565HIPj5mZAgqfH7XSwe1kdauDxGoxCuUA6TxMA3zw/UpUbYOJP0OjmzYKc0tiA==","signatures":[{"sig":"MEQCIHIv3YsY427+p59GWGV4Pyn7J736eAu2NvocjMl76X9xAiAbEVYg8JolJZqgnf8OeojzfOJNa0U5/RZ+HSZbZSupbA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@agenttrail%2fguardrails@0.0.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1240012},"main":"./dist/index.cjs","type":"module","_from":"file:/tmp/pack/agenttrail-guardrails-0.0.2.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.13"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./schema":{"types":"./dist/schema.d.ts","import":"./dist/schema.js","require":"./dist/schema.cjs"},"./guardrails":{"types":"./dist/guardrails.d.ts","import":"./dist/guardrails.js","require":"./dist/guardrails.cjs"}},"scripts":{"lint":"biome check .","test":"vitest run","build":"tsup","spell":"cspell --no-progress .","typecheck":"tsc --noEmit"},"_npmUser":{"name":"akarsh_a_s","email":"akarsh@techsuite.io"},"_resolved":"/tmp/pack/agenttrail-guardrails-0.0.2.tgz","_integrity":"sha512-meHd9XaPtceLEKJvVpb9SkO565HIPj5mZAgqfH7XSwe1kdauDxGoxCuUA6TxMA3zw/UpUbYOJP0OjmzYKc0tiA==","repository":{"url":"git+https://github.com/agenttrailhq/guardrails.git","type":"git"},"_npmVersion":"10.9.8","description":"The agenttrail guard rule corpus, its self-contained schema, and its fixtures.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^3.25.17"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","cspell":"^8.19.4","vitest":"^4.1.7","typescript":"^6.0.3","@types/node":"^25.9.1","@biomejs/biome":"2.4.15"},"_npmOperationalInternal":{"tmp":"tmp/guardrails_0.0.2_1789372751942_0.10260202769535298","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"@agenttrail/guardrails","version":"0.1.0","license":"Apache-2.0","_id":"@agenttrail/guardrails@0.1.0","maintainers":[{"name":"akarsh_a_s","email":"akarsh@techsuite.io"},{"name":"samc621","email":"samcorso10@gmail.com"}],"homepage":"https://github.com/agenttrailhq/guardrails#readme","bugs":{"url":"https://github.com/agenttrailhq/guardrails/issues"},"dist":{"shasum":"e511e8ffa58dfe13151ee79ef4a840bb575be7b3","tarball":"https://registry.npmjs.org/@agenttrail/guardrails/-/guardrails-0.1.0.tgz","fileCount":25,"integrity":"sha512-nQ5GBL9lCVFFMNhTmmwxg16vbtOE/YWedGP2qDmSGZAj3JF03iymhL+9X6KIIvg9H7aZPnNY4OBItku1QlJ8ZQ==","signatures":[{"sig":"MEUCIQDw/iWwh9n4cS3uaDnQGspIO40bsHnj7ngtfKbWJZe7cgIgdL1RcVeAESNbFafNrHWH/aq7aOKoj9Bteoo/QFYGOuI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@agenttrail%2fguardrails@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1718848},"main":"./dist/index.cjs","type":"module","_from":"file:/tmp/pack/agenttrail-guardrails-0.1.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.13"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./schema":{"types":"./dist/schema.d.ts","import":"./dist/schema.js","require":"./dist/schema.cjs"},"./guardrails":{"types":"./dist/guardrails.d.ts","import":"./dist/guardrails.js","require":"./dist/guardrails.cjs"}},"scripts":{"lint":"biome check .","test":"vitest run","build":"tsup","spell":"cspell --no-progress .","typecheck":"tsc --noEmit"},"_npmUser":{"name":"akarsh_a_s","email":"akarsh@techsuite.io"},"_resolved":"/tmp/pack/agenttrail-guardrails-0.1.0.tgz","_integrity":"sha512-nQ5GBL9lCVFFMNhTmmwxg16vbtOE/YWedGP2qDmSGZAj3JF03iymhL+9X6KIIvg9H7aZPnNY4OBItku1QlJ8ZQ==","repository":{"url":"git+https://github.com/agenttrailhq/guardrails.git","type":"git"},"_npmVersion":"10.9.8","description":"The agenttrail guard rule corpus, its self-contained schema, and its fixtures.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^3.25.17"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","cspell":"^8.19.4","vitest":"^4.1.7","typescript":"^6.0.3","@types/node":"^25.9.1","@biomejs/biome":"2.4.15"},"_npmOperationalInternal":{"tmp":"tmp/guardrails_0.1.0_1789459596269_0.30936695989802865","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@agenttrail/guardrails","version":"0.2.0","keywords":["guardrails","ai-agent","agent-security","claude-code","cursor","security-rules","policy"],"license":"Apache-2.0","_id":"@agenttrail/guardrails@0.2.0","maintainers":[{"name":"akarsh_a_s","email":"akarsh@techsuite.io"},{"name":"samc621","email":"samcorso10@gmail.com"}],"homepage":"https://github.com/agenttrailhq/guardrails#readme","bugs":{"url":"https://github.com/agenttrailhq/guardrails/issues"},"dist":{"shasum":"187cf0789bc549db2fd4b862570cfb7ca90cf07e","tarball":"https://registry.npmjs.org/@agenttrail/guardrails/-/guardrails-0.2.0.tgz","fileCount":25,"integrity":"sha512-eAQsIITayLbJqGb7z0JQ62kQVl5V+EbxburQBqgFbKxhClgGcu84oOKz64CBKYhhnX1jC8TnE8OoecJeL3pY9Q==","signatures":[{"sig":"MEQCIBb5g4O1Q/XJBojqgzl9B0FXf5clKTJZ8RSPptC3eS+3AiAx7lEfCjidhffj+9TZLCaRTI6jwK8L/gmBNjGYL3MRpQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDREVjsIRCH0+VYJHiHhgIQi/VH3HgdHrYxAVWu+5s4dgIgH8SqOQ6Q3Bo9wbhs2lBAvBi1SKJeyh5EXO6hU++1kww=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@agenttrail%2fguardrails@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1857126},"main":"./dist/index.cjs","type":"module","_from":"file:/tmp/pack/agenttrail-guardrails-0.2.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.13"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./schema":{"types":"./dist/schema.d.ts","import":"./dist/schema.js","require":"./dist/schema.cjs"},"./guardrails":{"types":"./dist/guardrails.d.ts","import":"./dist/guardrails.js","require":"./dist/guardrails.cjs"}},"scripts":{"lint":"biome check .","test":"vitest run","build":"tsup","spell":"cspell --no-progress .","typecheck":"tsc --noEmit"},"_npmUser":{"name":"akarsh_a_s","email":"akarsh@techsuite.io"},"_resolved":"/tmp/pack/agenttrail-guardrails-0.2.0.tgz","_integrity":"sha512-eAQsIITayLbJqGb7z0JQ62kQVl5V+EbxburQBqgFbKxhClgGcu84oOKz64CBKYhhnX1jC8TnE8OoecJeL3pY9Q==","repository":{"url":"git+https://github.com/agenttrailhq/guardrails.git","type":"git"},"_npmVersion":"10.9.8","description":"The agenttrail guard rule corpus, its self-contained schema, and its fixtures.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^3.25.17"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","cspell":"^8.19.4","vitest":"^4.1.7","typescript":"^6.0.3","@types/node":"^25.9.1","@biomejs/biome":"2.4.15"},"_npmOperationalInternal":{"tmp":"tmp/guardrails_0.2.0_1789738680282_0.12745565086801736","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"_id":"@agenttrail/guardrails@0.2.1","bugs":{"url":"https://github.com/agenttrailhq/guardrails/issues"},"dist":{"shasum":"0c5f16f87c1a269de24d9dc00471d9b96acc5707","tarball":"https://registry.npmjs.org/@agenttrail/guardrails/-/guardrails-0.2.1.tgz","fileCount":25,"integrity":"sha512-YlsPN52ZWPnosW60wZEvwbpQIWBYfLuF60s1SrEQuIv0uyTNXVoX+PGfcg6WTwJnOhh25vpg3bTkauSjMNe2cw==","signatures":[{"sig":"MEQCIFF3nWWoBgCkoXXCDqFPX9gG2EqmbLLJVx6qpE9R/opXAiA8ond6OPx5zblOOsVkxOhCNE1hVL/sARdwfK7kzJJKzw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGQHPBN1NhshJKkx+neajKkm2U2RD/y8tvnBD3R0xKZVAiEAxdh6WaEImrMg4ZfsZJ1u3wIT8PEHl7be4q/NmGys/t0="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@agenttrail%2fguardrails@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1897740},"main":"./src/index.ts","name":"@agenttrail/guardrails","type":"module","engines":{"node":">=22.13"},"exports":{".":"./src/index.ts","./schema":"./src/schema.ts","./guardrails":"./src/rules.ts"},"gitHead":"32578ad188b4ab84c154eba8c4bb4c9f71681bb1","license":"Apache-2.0","scripts":{"lint":"biome check .","test":"vitest run","build":"tsup","spell":"cspell --no-progress .","prepack":"tsup","typecheck":"tsc --noEmit"},"version":"0.2.1","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"b57c323c-5dcd-4932-925e-71b41c80eaf7"}},"homepage":"https://github.com/agenttrailhq/guardrails#readme","keywords":["guardrails","ai-agent","agent-security","claude-code","cursor","security-rules","policy"],"repository":{"url":"git+https://github.com/agenttrailhq/guardrails.git","type":"git"},"_npmVersion":"12.1.0","description":"The agenttrail guard rule corpus, its self-contained schema, and its fixtures.","directories":{},"maintainers":[{"name":"akarsh_a_s","email":"akarsh@techsuite.io"},{"name":"samc621","email":"samcorso10@gmail.com"},{"name":"kashyap-techsuite","email":"kashyap@techsuite.io"}],"_nodeVersion":"22.23.2","dependencies":{"zod":"^3.25.17"},"publishConfig":{"main":"./dist/index.cjs","types":"./dist/index.d.ts","access":"public","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./schema":{"types":"./dist/schema.d.ts","import":"./dist/schema.js","require":"./dist/schema.cjs"},"./guardrails":{"types":"./dist/guardrails.d.ts","import":"./dist/guardrails.js","require":"./dist/guardrails.cjs"}}},"_hasShrinkwrap":false,"packageManager":"pnpm@11.5.2","devDependencies":{"tsup":"^8.3.5","cspell":"^8.19.4","vitest":"^4.1.7","typescript":"^6.0.3","@types/node":"^25.9.1","@biomejs/biome":"2.4.15","@commitlint/cli":"^21.2.3","semantic-release":"^25.0.9","@semantic-release/git":"^11.0.1","@semantic-release/exec":"^7.1.0","@semantic-release/changelog":"^7.0.0","@commitlint/config-conventional":"^21.2.3","conventional-changelog-conventionalcommits":"^9.1.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/guardrails_0.2.1_1790655180899_0.9788019440767919"}}},"time":{"created":"2026-09-11T03:58:57.845Z","modified":"2026-09-29T04:13:01.337Z","0.0.1-rc.1":"2026-09-11T03:58:58.249Z","0.0.1":"2026-09-11T04:07:45.718Z","0.0.2":"2026-09-14T07:59:12.112Z","0.1.0":"2026-09-15T08:06:36.409Z","0.2.0":"2026-09-18T13:38:00.391Z","0.2.1":"2026-09-29T04:13:01.001Z"},"bugs":{"url":"https://github.com/agenttrailhq/guardrails/issues"},"license":"Apache-2.0","homepage":"https://github.com/agenttrailhq/guardrails#readme","keywords":["guardrails","ai-agent","agent-security","claude-code","cursor","security-rules","policy"],"repository":{"url":"git+https://github.com/agenttrailhq/guardrails.git","type":"git"},"description":"The agenttrail guard rule corpus, its self-contained schema, and its fixtures.","maintainers":[{"name":"akarsh_a_s","email":"akarsh@techsuite.io"},{"name":"samc621","email":"samcorso10@gmail.com"},{"name":"kashyap-techsuite","email":"kashyap@techsuite.io"}],"readme":"<!-- cspell:words exfiltration kubeconfig -->\n\n# @agenttrail/guardrails\n\n**A library of rules that spot dangerous commands before an AI coding agent runs them.**\n\n74 rules, grouped into 11 packs. Apache-2.0.\n\n---\n\n## What this is, in plain terms\n\nWhen you let an AI coding agent work in your terminal, it eventually proposes something you would\nnot have typed yourself — `git reset --hard` over a day's work, `rm -rf` on the wrong path, a\n`terraform apply` against production.\n\nThis package is the **list of things worth stopping**, written as data. Each entry says what to look\nfor, how serious it is, and what should happen — allow it, ask a human first, or refuse.\n\n**That is all this package does.** It contains no code that watches your machine and nothing that\ntalks to the network. It is a list. Something else has to read it and act on it — normally\n[`agenttrail-guard`](https://github.com/agenttrailhq/guard), which runs on your laptop and checks each\ncommand an agent proposes against these rules.\n\nSeparating the two is deliberate. You can read every rule here, disagree with one, and change it,\nwithout trusting anything about the tool that enforces them.\n\n## Who this is for\n\n- **You use an AI coding agent** and want a sensible default set of guardrails rather than writing\n  your own from scratch.\n- **You want to see exactly what is being blocked and why.** Every rule is plain data with a written\n  explanation, including what it *misses*.\n- **You want to contribute a rule** you wish had existed. See [Contributing](#contributing-a-rule).\n\n## Install\n\n```bash\nnpm install @agenttrail/guardrails\n```\n\nMost people never install this directly — `agenttrail-guard` bundles it. Install it yourself if you\nare writing rules, or building your own tool on top of the list.\n\n## A rule, start to finish\n\nHere is a complete rule. Nothing is hidden; this is the actual shape.\n\n```jsonc\n{\n  \"id\": \"wt.reset-hard\",\n  \"category\": \"working-tree\",\n  \"severity\": \"high\",\n  \"defaultAction\": \"block\",\n  \"title\": \"git reset --hard discards uncommitted work\",\n  \"description\": \"Discards all uncommitted changes. Does not match `git restore` — see wt.restore-path.\",\n\n  // What to look for. This one matches a Bash command against a regular expression.\n  \"match\": {\n    \"any_of\": [\n      { \"kind\": \"execute_tool\", \"label\": \"Bash\", \"detail_matches\": [\"\\\\bgit\\\\s+reset\\\\s+--hard\\\\b\"] }\n    ]\n  },\n\n  // Proof it works, in both directions — see \"Every rule proves both directions\" below.\n  \"fixtures\": {\n    \"block\": [\"git reset --hard\"],\n    \"allow\": [\"git reset src/api.ts\"]\n  }\n}\n```\n\nReading the fields:\n\n| Field | What it means |\n|---|---|\n| `id` | A stable name. Users type it to disable or change a rule, so it never changes. |\n| `severity` | How bad the thing being caught is: `critical`, `high`, `medium`, `low`, `info`. **It is not a price** — this package ships no mapping from severity to money. |\n| `defaultAction` | What should happen: `block` (refuse), `require_approval` (ask a human), or `warn` (allow, but say so). A user can override it. |\n| `description` | What the rule catches **and what it misses**. The honest limits are part of the rule, not a footnote. |\n| `match` | The condition. `any_of` means \"any one of these is enough\". |\n| `fixtures` | Examples that must match, and examples that must not. |\n\n## The eleven packs\n\nA rule is filed by **the harm it prevents**, never by the technique it uses to spot it.\n\nThat sounds like a detail and is not. The three rules about production config, `.env` files and API\nendpoints all work by matching file paths — but they are *not* in `file-scope`. Someone who turned\nthat pack off to stop path noise would otherwise silently lose their production and secret\nprotection, which they never asked to turn off and would not know they had.\n\n| Pack | Rules | What it is about |\n|---|---:|---|\n| `working-tree` | 9 | Destroying uncommitted work or published history — `git reset --hard`, `git clean -fd`, force-push, `rm -rf`. |\n| `destructive-data` | 8 | Data git cannot bring back — a dropped volume, a dropped database, destructive DDL, a deleted shadow copy. |\n| `prod-infra` | 8 | Changing running infrastructure — Terraform, Kubernetes, Helm, cloud deletes, a deploy that names production. |\n| `secret-exposure` | 10 | Credentials and sensitive data leaving where they live. Mostly `warn`: reading a secret is a normal part of a normal day. |\n| `rce-supply-chain` | 6 | Running code nobody reviewed — pipe-to-shell, a remote runner, a redirected registry, TLS verification off. |\n| `safety-bypass` | 7 | Turning off a check somebody installed on purpose, or erasing the record of it — `--no-verify`, `--admin` merge, hooks disabled, host-key checking off, history and log purges, forged terminal output. |\n| `privilege-supply-chain` | 6 | Gaining reach or handing it out — `sudo` writes, `chmod 777`, IAM grants, persistence, publishing, new dependencies. |\n| `file-scope` | 4 | The agent wrote somewhere it had no business writing — its own config, the machine, git's internals, the CI definition. |\n| `agent-context` | 6 | The agent changing what it is or what it knows — its standing instructions, its memory, its skills and commands, its MCP servers — or starting more agents, or switching another agent's approvals off. |\n| `test-integrity` | 6 | The agent making its work look successful — deleting a test, weakening a runner's configuration, accepting every snapshot, switching a coverage gate off, silencing failures in bulk, or telling CI not to run. |\n| `exfiltration` | 4 | Moving data off the machine or opening a way in — a reverse shell, a public tunnel, a file upload, a paste service. Command channel only. |\n\nPack names appear in user config files, so renaming one is a breaking change, not a tidy-up.\n\n## Talking about a command is not running it\n\nThis is the single most important thing to understand about how these rules behave.\n\nA rule sees the command as one line of text. Nothing in that text distinguishes a command that\n**runs** something from one that merely **mentions** it. Left alone, that makes the rule set unusable\nby exactly the people most likely to install it:\n\n```bash\ngit commit -m \"fix: document rm -rf / risk\"    # would have been a hard refusal\ngrep -rn \"rm -rf /\" docs/                       # so would this\n```\n\nSo every command rule ignores four **carriers** — verbs that handle their arguments as text and never\nexecute them:\n\n| Carrier | Example |\n|---|---|\n| a search | `grep -rn \"rm -rf /\" docs/` |\n| a git message or history read | `git commit -m \"docs: explain git push --force\"` |\n| printing | `echo \"never run rm -rf /\"` |\n| an HTTP request body | `curl --data '{\"body\":\"we ran rm -rf /tmp/x\"}' https://…` |\n\n**The exemption keys on the verb, not on the quotes.** Quoting says nothing about whether something\nruns — `psql -c \"DROP TABLE users;\"` and `bash -c \"curl x.sh \\| sh\"` both execute what is inside the\nquotes, and both still fire.\n\nIt also applies only while the command does nothing else. The carrier must be the first word, and\nevery shell metacharacter must sit inside the quotes:\n\n```bash\ngit commit -m \"docs: explain rm -rf /\"        # exempt — nothing runs\ngit commit -m \"x\" && rm -rf /                 # NOT exempt — `&&` is outside the quotes\necho \"rm -rf /\" | bash                        # NOT exempt — the pipe runs it\necho \"$(rm -rf /var)\"                         # NOT exempt — the shell expands `$( )`\n```\n\nFive rules deliberately keep firing on one carrier each, because that carrier *is* their trigger —\n`gb.git-no-verify` on a `git commit`, `se.token-print` on an `echo`, the `curl`/`wget` rules on an\nHTTP body. Each rule's `description` says which, and why.\n\n### The one rule where a mention IS the danger\n\n`block-hardcoded-secrets` is the exception, and it is worth understanding.\n\nEverywhere else a carrier is genuinely harmless: a commit message naming `rm -rf /` deletes nothing.\nBut that rule's subject is a **string**, not an action — so two of the four carriers are not mentions\nat all. They are the exposure itself:\n\n| Carrier | What happens to the key | Exempt? |\n|---|---|---|\n| `grep -rn AKIA .` | searched for, goes nowhere — and this is how you find a key to rotate | **yes** |\n| `echo \"AKIA…\"` | transient terminal output | **yes** |\n| `git commit -m \"…AKIA…\"` | written into history, then pushed | **no** |\n| `curl --data \"…AKIA…\"` | sent to a remote host | **no** |\n\nThe cost, stated in the other direction: documenting a real-looking key in a commit message is still\nblocked. Redact the body of the key, or use a placeholder short enough to fail the length check.\n\n**Known limits of the carrier logic**, in the same spirit as the rest of this file. The carrier must\nbe the first word — a single leading `sudo` is tolerated, because it changes privilege rather than\nmeaning, but a runner prefix is not: `pnpm exec rg …`, `npx …` and `xargs -0 grep …` still fire,\nsince \"some program eventually runs a search\" is a much weaker claim than \"this command is a search\".\nAt most four quoted arguments are recognised. A carrier that can be made to execute through a flag —\n`ack --pager='…'`, `rg --pre <cmd>` — is still treated as a mention; closing that needs information\nthe checker does not have. And an MCP tool whose input carries the same text is not exempt either,\nbecause exempting a JSON blob would exempt a shell-running MCP server along with it.\n\n**MCP coverage.** A command rule fires on `Bash`, `PowerShell` *and* any `mcp__*` tool: the guard hands\nthe checker an MCP call's serialized `tool_input` as the same command text every command rule reads, so\na command shape run through an MCP server — `{\"command\":\"rm -rf /\"}` — is caught, not ignored. Two\nhonest limits follow from that. First, a rule whose pattern is anchored to the start of the command\n(`^…` or a command-position class) may not fire inside the JSON, where the shape sits after a `\"`\nrather than at a command boundary; the `\\b`-anchored rules — most of the corpus — do fire. Second, the\nquoted-mention exemptions are shell-only, so an MCP payload that merely *names* a command in a text\nfield (`{\"title\":\"fix the rm -rf / bug\"}`) is matched the same as one that runs it — a JSON blob cannot\nbe told apart from a shell-running MCP server. File rules match by path on whichever file tool a client\nuses. No rule is shell-only by design; a rule that does not reach the MCP channel does so because its\npattern, not its label, does not match the serialized shape.\n\n## What these rules deliberately do not catch\n\nStated here rather than discovered later. Every one is a real limit of the format, not something\nsomebody forgot.\n\n- **Nothing about the web.** Pages an agent fetches are not checked, and there are no URL rules.\n- **Nothing inside a file.** The checker sees a file's *path*, never its contents. A secret typed into\n  a source file, SQL built by string concatenation, a missing auth check — none of it is visible.\n  Rules that would need it are absent rather than approximated.\n- **Nothing about where you are.** No working directory, no project root, no git branch, no cloud\n  profile reaches the checker — it gets one command and nothing else. So \"the agent wrote outside the\n  project\" **cannot be written as a rule**, and `file-scope` is limited to well-known absolute paths\n  for good. For the same reason, a rule cannot tell a scratch database from a production one.\n- **Nothing hidden inside a quoted payload.** Where the danger is inside a quoted argument —\n  `psql -c \"<sql>\"`, `python -c \"<code>\"` — a text rule can only guess. In a long script, a match says\n  very little about what the script actually does.\n- **Nothing a wrapper hides.** `./deploy.sh` that runs `terraform apply -auto-approve` inside it is\n  just a shell script from the outside.\n- **Nothing recurring.** There is no counting. \"The same mistake three times this week\" needs memory\n  across commands, and a single command has none.\n\nEach rule's own `description` names its specific misses. Read those before trusting a rule to cover a\ncase — they are written to be believed, not to sell.\n\n## Every rule proves both directions\n\nEvery rule ships at least one **`block`** example and at least one **`allow`** example. A rule missing\neither does not build.\n\n- **`block` means \"this rule must match.\"** It does *not* mean the agent is refused — most packs\n  default to asking or warning.\n- **`allow` means \"this rule must NOT match.\"** *This is the half that matters.* Anyone can write a\n  rule that catches `rm -rf /`. The hard part is not firing on `rm -rf ./node_modules` forty times a\n  day, and a rule with no negative example has not shown it can tell them apart.\n\nExamples come in two kinds, and each must use the right one:\n\n| Kind | Used for |\n|---|---|\n| a command | `Bash`, `PowerShell`, a search query, an MCP tool's input |\n| a file path | `Edit`, `Write`, `Read`, `MultiEdit`, `NotebookEdit` |\n\nGiving a path-matching rule a command example makes it pass **without testing anything** — it matches\nnothing, which reads as proof of quietness and proves only that the path never reached the rule. CI\nrejects that.\n\n## Contributing a rule\n\nRules are meant to be contributed. The bar is not \"clever regex\" — it is **does it fire on the real\nthing, and stay quiet on the near-miss**.\n\n**1. Write it**, following the shape above. Give it a `description` that says what it misses.\n\n**2. Check the shape locally:**\n\n```ts\nimport { parseRule } from \"@agenttrail/guardrails\";\n\nconst result = parseRule(myRule);\nif (!result.success) console.error(result.error.issues);\n```\n\nOr, if you have the guard installed:\n\n```bash\nagenttrail-guard guardrails validate ./my-rule.json\n```\n\n**3. Understand what that does and does not tell you.** It answers *\"is this a well-formed rule?\"* It\ndoes **not** answer *\"does it actually fire on the command I think it does?\"* That needs the real\nchecker, which is not part of this package.\n\n**So the real test runs in CI, on your pull request** — the same check, on the same machine, for\neveryone. You get the shape check instantly here and the real answer there, which is where it has to\nrun to be trusted anyway.\n\nYour rule is also run against a **quiet corpus**: 328 everyday commands and paths that no rule may\nmatch at all. Your own negative example only proves your rule is quiet on the near-miss *you* thought\nof. The quiet corpus is what catches a Terraform rule firing on `pnpm test`.\n\n### Shapes that will not validate\n\nThree are rejected outright, each because it produces a rule that *looks* enforced and is not — the\nworst failure a security tool can have.\n\n| Rejected | Why |\n|---|---|\n| `scope` | It compares against ids that are always UUIDs, never a vendor name — so a scoped rule matches nothing, forever, silently. |\n| Numeric conditions | Token counts and durations are all zero *before* a command runs. \"Greater than\" can never fire; \"less than\" fires on everything. |\n| A command matcher and a file matcher in one condition | No real command carries both, so the condition can never be true. Split it into two under `any_of`. |\n\nA regular expression is also rejected if it nests unbounded repetition (`(a+)+`). The guard fails\n**open** under a time limit, so a pattern that backtracks does not merely run slowly — it lets the\ncommand through.\n\nOne more is caught in CI rather than by the shape check, because it cannot be caught earlier: **a\nsingle-item brace list in a tool name.** `\"{Bash}\"` is a glob pattern, and it does not match `Bash` —\nso the rule matches nothing, forever, with no error anywhere. Write a single tool plainly as\n`\"Bash\"`; braces are for real alternatives, `\"{Bash,PowerShell}\"`.\n\n## Two ways to import it\n\n```ts\nimport { RULES, getRule } from \"@agenttrail/guardrails/guardrails\";  // just the rules\nimport { parseRule } from \"@agenttrail/guardrails\";                  // rules + the shape checker\n```\n\nUse the first when you want to *apply* rules, and the second when you want to *validate* one you are\nwriting.\n\nThey are separate because the guard starts a fresh process on **every single command** an agent runs,\nunder a ten-second ceiling. It cannot afford to load a validator it never calls, or to re-check 74\nrules that were already checked before release.\n\n## Where these rules came from\n\nIndependently authored. No block list, pattern or wording is copied from any other project.\n\nWhere a rule's shape follows an obvious convention — an `rm -rf` pattern looks like an `rm -rf`\npattern — that is two people meeting the same shell, not one copying the other.\n\nFour vendors' own tools inspired specific rules through their *documented failure modes*, not their\ncode.\n\n## License\n\nApache-2.0. See [LICENSE](./LICENSE).\n","readmeFilename":"README.md"}