[{"data":1,"prerenderedAt":1359},["ShallowReactive",2],{"navigation_docs":3,"-guides-harnesses-worker-kit":504,"-guides-harnesses-worker-kit-surround":1354},[4,28,51,187,214,469],{"title":5,"path":6,"stem":7,"children":8},"Get started","\u002Fget-started","1.get-started",[9,12,16,20,24],{"title":10,"path":6,"stem":11},"Overview","1.get-started\u002Findex",{"title":13,"path":14,"stem":15},"Why Kraft","\u002Fget-started\u002Fwhy-kraft","1.get-started\u002F0.why-kraft",{"title":17,"path":18,"stem":19},"Install","\u002Fget-started\u002Finstall","1.get-started\u002F1.install",{"title":21,"path":22,"stem":23},"Your first work item","\u002Fget-started\u002Ffirst-work-item","1.get-started\u002F2.first-work-item",{"title":25,"path":26,"stem":27},"FAQ","\u002Fget-started\u002Ffaq","1.get-started\u002F3.faq",{"title":29,"path":30,"stem":31,"children":32},"Concepts","\u002Fconcepts","2.concepts",[33,35,39,43,47],{"title":10,"path":30,"stem":34},"2.concepts\u002Findex",{"title":36,"path":37,"stem":38},"How a work item runs","\u002Fconcepts\u002Fhow-a-work-item-runs","2.concepts\u002F1.how-a-work-item-runs",{"title":40,"path":41,"stem":42},"Caps and budgets","\u002Fconcepts\u002Fcaps-and-budgets","2.concepts\u002F2.caps-and-budgets",{"title":44,"path":45,"stem":46},"Why a permission gate","\u002Fconcepts\u002Fpermission-gate","2.concepts\u002F3.permission-gate",{"title":48,"path":49,"stem":50},"Vocabulary","\u002Fconcepts\u002Fvocabulary","2.concepts\u002F4.vocabulary",{"title":52,"path":53,"stem":54,"children":55},"Guides","\u002Fguides","3.guides",[56,58,96,113,134,183],{"title":10,"path":53,"stem":57},"3.guides\u002Findex",{"title":59,"path":60,"stem":61,"children":62,"page":95},"Day to day","\u002Fguides\u002Fday-to-day","3.guides\u002F1.day-to-day",[63,67,71,75,79,83,87,91],{"title":64,"path":65,"stem":66},"The setup wizard on first start","\u002Fguides\u002Fday-to-day\u002Ffirst-run","3.guides\u002F1.day-to-day\u002F2.first-run",{"title":68,"path":69,"stem":70},"File a work item","\u002Fguides\u002Fday-to-day\u002Ffile-a-work-item","3.guides\u002F1.day-to-day\u002F3.file-a-work-item",{"title":72,"path":73,"stem":74},"Use Kraft from your agent","\u002Fguides\u002Fday-to-day\u002Fagent-integration","3.guides\u002F1.day-to-day\u002F4.agent-integration",{"title":76,"path":77,"stem":78},"Reviewing a change","\u002Fguides\u002Fday-to-day\u002Freview-a-change","3.guides\u002F1.day-to-day\u002F5.review-a-change",{"title":80,"path":81,"stem":82},"Raise a cap on a stopped item","\u002Fguides\u002Fday-to-day\u002Fraise-a-cap","3.guides\u002F1.day-to-day\u002F6.raise-a-cap",{"title":84,"path":85,"stem":86},"Kraft for VS Code","\u002Fguides\u002Fday-to-day\u002Fvscode","3.guides\u002F1.day-to-day\u002F7.vscode",{"title":88,"path":89,"stem":90},"Kraft on a phone","\u002Fguides\u002Fday-to-day\u002Fkraft-on-a-phone","3.guides\u002F1.day-to-day\u002F8.kraft-on-a-phone",{"title":92,"path":93,"stem":94},"Get notified when an item needs you","\u002Fguides\u002Fday-to-day\u002Fnotifications","3.guides\u002F1.day-to-day\u002F9.notifications",false,{"title":97,"path":98,"stem":99,"children":100,"page":95},"Customize and automate","\u002Fguides\u002Fcustomize","3.guides\u002F2.customize",[101,105,109],{"title":102,"path":103,"stem":104},"Write your own chain","\u002Fguides\u002Fcustomize\u002Fwrite-your-own-chain","3.guides\u002F2.customize\u002F1.write-your-own-chain",{"title":106,"path":107,"stem":108},"Add a security review or a gate reviewer","\u002Fguides\u002Fcustomize\u002Fadd-review-agents","3.guides\u002F2.customize\u002F2.add-review-agents",{"title":110,"path":111,"stem":112},"Schedule or webhook work","\u002Fguides\u002Fcustomize\u002Fschedule-and-webhook-work","3.guides\u002F2.customize\u002F3.schedule-and-webhook-work",{"title":114,"path":115,"stem":116,"children":117,"page":95},"Agents and harnesses","\u002Fguides\u002Fharnesses","3.guides\u002F3.harnesses",[118,122,126,130],{"title":119,"path":120,"stem":121},"Switch a task to another harness","\u002Fguides\u002Fharnesses\u002Fswitch-harness","3.guides\u002F3.harnesses\u002F1.switch-harness",{"title":123,"path":124,"stem":125},"Add or override a harness","\u002Fguides\u002Fharnesses\u002Fadding-a-harness","3.guides\u002F3.harnesses\u002F2.adding-a-harness",{"title":127,"path":128,"stem":129},"Build a worker Kit","\u002Fguides\u002Fharnesses\u002Fworker-kit","3.guides\u002F3.harnesses\u002F3.worker-kit",{"title":131,"path":132,"stem":133},"Give a worker its login","\u002Fguides\u002Fharnesses\u002Fgive-a-worker-its-login","3.guides\u002F3.harnesses\u002F4.give-a-worker-its-login",{"title":135,"path":136,"stem":137,"children":138,"page":95},"Run the server","\u002Fguides\u002Frun","3.guides\u002F4.run",[139,143,147,151,155,159,163,167,171,175,179],{"title":140,"path":141,"stem":142},"Remote access","\u002Fguides\u002Frun\u002Fremote-access","3.guides\u002F4.run\u002F01.remote-access",{"title":144,"path":145,"stem":146},"Put a proxy in front of Kraft","\u002Fguides\u002Frun\u002Fput-a-proxy-in-front-of-kraft","3.guides\u002F4.run\u002F02.put-a-proxy-in-front-of-kraft",{"title":148,"path":149,"stem":150},"Restart Kraft without ending running agents","\u002Fguides\u002Frun\u002Frestart-kraft","3.guides\u002F4.run\u002F03.restart-kraft",{"title":152,"path":153,"stem":154},"Back up and restore the database","\u002Fguides\u002Frun\u002Fback-up-and-restore","3.guides\u002F4.run\u002F04.back-up-and-restore",{"title":156,"path":157,"stem":158},"Logs and disk space","\u002Fguides\u002Frun\u002Flogs-and-disk-space","3.guides\u002F4.run\u002F05.logs-and-disk-space",{"title":160,"path":161,"stem":162},"Run Kraft as a service","\u002Fguides\u002Frun\u002Frun-as-a-service","3.guides\u002F4.run\u002F06.run-as-a-service",{"title":164,"path":165,"stem":166},"Upgrade Kraft","\u002Fguides\u002Frun\u002Fupgrade-kraft","3.guides\u002F4.run\u002F07.upgrade-kraft",{"title":168,"path":169,"stem":170},"Upgrade your configuration","\u002Fguides\u002Frun\u002Fupgrade-your-configuration","3.guides\u002F4.run\u002F08.upgrade-your-configuration",{"title":172,"path":173,"stem":174},"Upgrade from 1.4","\u002Fguides\u002Frun\u002Fupgrade-from-1-4","3.guides\u002F4.run\u002F09.upgrade-from-1-4",{"title":176,"path":177,"stem":178},"Upgrade from 0.x or a release candidate","\u002Fguides\u002Frun\u002Fupgrade-from-0-x-or-a-release-candidate","3.guides\u002F4.run\u002F10.upgrade-from-0-x-or-a-release-candidate",{"title":180,"path":181,"stem":182},"Roll back to 1.4","\u002Fguides\u002Frun\u002Froll-back","3.guides\u002F4.run\u002F11.roll-back",{"title":184,"path":185,"stem":186},"Kraft Lite","\u002Fguides\u002Fkraft-lite","3.guides\u002F5.kraft-lite",{"title":188,"path":189,"stem":190,"children":191},"Troubleshooting","\u002Ftroubleshooting","4.troubleshooting",[192,194,198,202,206,210],{"title":10,"path":189,"stem":193},"4.troubleshooting\u002Findex",{"title":195,"path":196,"stem":197},"Why did my item stop?","\u002Ftroubleshooting\u002Fwhy-did-my-item-stop","4.troubleshooting\u002F1.why-did-my-item-stop",{"title":199,"path":200,"stem":201},"Stop reasons in detail","\u002Ftroubleshooting\u002Fstop-reasons-in-detail","4.troubleshooting\u002F2.stop-reasons-in-detail",{"title":203,"path":204,"stem":205},"Starting and reaching Kraft","\u002Ftroubleshooting\u002Fstarting-and-reaching-kraft","4.troubleshooting\u002F3.starting-and-reaching-kraft",{"title":207,"path":208,"stem":209},"Doctor failures","\u002Ftroubleshooting\u002Fdoctor-failures","4.troubleshooting\u002F4.doctor-failures",{"title":211,"path":212,"stem":213},"Sandbox and Kit stops","\u002Ftroubleshooting\u002Fsandbox-and-kit-stops","4.troubleshooting\u002F5.sandbox-and-kit-stops",{"title":215,"path":216,"stem":217,"children":218},"Reference","\u002Freference","5.reference",[219,221,259,281,285,375,393,419,423,427,461,465],{"title":10,"path":216,"stem":220},"5.reference\u002Findex",{"title":222,"path":223,"stem":224,"children":225},"Web UI","\u002Freference\u002Fweb-ui","5.reference\u002F00.web-ui\u002Findex",[226,227,231,235,239,243,247,251,255],{"title":10,"path":223,"stem":224},{"title":228,"path":229,"stem":230},"Sidebar, search, and keyboard","\u002Freference\u002Fweb-ui\u002Fsidebar-search-and-keyboard","5.reference\u002F00.web-ui\u002F0.sidebar-search-and-keyboard",{"title":232,"path":233,"stem":234},"The board","\u002Freference\u002Fweb-ui\u002Fboard","5.reference\u002F00.web-ui\u002F1.board",{"title":236,"path":237,"stem":238},"An item's page","\u002Freference\u002Fweb-ui\u002Fitem-page","5.reference\u002F00.web-ui\u002F2.item-page",{"title":240,"path":241,"stem":242},"Fix loops and test scopes","\u002Freference\u002Fweb-ui\u002Ffix-loops-and-test-scopes","5.reference\u002F00.web-ui\u002F3.fix-loops-and-test-scopes",{"title":244,"path":245,"stem":246},"Config before an item starts","\u002Freference\u002Fweb-ui\u002Fconfig-before-start","5.reference\u002F00.web-ui\u002F4.config-before-start",{"title":248,"path":249,"stem":250},"The review page","\u002Freference\u002Fweb-ui\u002Freview-page","5.reference\u002F00.web-ui\u002F5.review-page",{"title":252,"path":253,"stem":254},"Templates and Settings","\u002Freference\u002Fweb-ui\u002Ftemplates-and-settings","5.reference\u002F00.web-ui\u002F6.templates-and-settings",{"title":256,"path":257,"stem":258},"Analytics","\u002Freference\u002Fweb-ui\u002Fanalytics","5.reference\u002F00.web-ui\u002F7.analytics",{"title":260,"path":261,"stem":262,"children":263},"CLI","\u002Freference\u002Fcli","5.reference\u002F01.cli\u002Findex",[264,265,269,273,277],{"title":10,"path":261,"stem":262},{"title":266,"path":267,"stem":268},"Item verbs","\u002Freference\u002Fcli\u002Fitem","5.reference\u002F01.cli\u002F2.item",{"title":270,"path":271,"stem":272},"View verbs","\u002Freference\u002Fcli\u002Fview","5.reference\u002F01.cli\u002F3.view",{"title":274,"path":275,"stem":276},"Repo verbs","\u002Freference\u002Fcli\u002Frepo","5.reference\u002F01.cli\u002F4.repo",{"title":278,"path":279,"stem":280},"Admin verbs","\u002Freference\u002Fcli\u002Fadmin","5.reference\u002F01.cli\u002F5.admin",{"title":282,"path":283,"stem":284},"Work item statuses","\u002Freference\u002Fstatuses","5.reference\u002F02.statuses",{"title":286,"path":287,"stem":288,"children":289},"Configuration","\u002Freference\u002Fconfiguration","5.reference\u002F03.configuration\u002Findex",[290,291,309,313,317,321,325,329,333,337,371],{"title":10,"path":287,"stem":288},{"title":292,"path":293,"stem":294,"children":295},"repos.yaml","\u002Freference\u002Fconfiguration\u002Frepos","5.reference\u002F03.configuration\u002F02.repos\u002Findex",[296,297,301,305],{"title":10,"path":293,"stem":294},{"title":298,"path":299,"stem":300},"How connect proposes commands","\u002Freference\u002Fconfiguration\u002Frepos\u002Fconnect-proposals","5.reference\u002F03.configuration\u002F02.repos\u002F1.connect-proposals",{"title":302,"path":303,"stem":304},"detectors.yaml","\u002Freference\u002Fconfiguration\u002Frepos\u002Fdetectors","5.reference\u002F03.configuration\u002F02.repos\u002F2.detectors",{"title":306,"path":307,"stem":308},"Workspaces","\u002Freference\u002Fconfiguration\u002Frepos\u002Fworkspaces","5.reference\u002F03.configuration\u002F02.repos\u002F3.workspaces",{"title":310,"path":311,"stem":312},"policy.yaml","\u002Freference\u002Fconfiguration\u002Fpolicy","5.reference\u002F03.configuration\u002F03.policy",{"title":314,"path":315,"stem":316},"Library and chains","\u002Freference\u002Fconfiguration\u002Flibrary-and-chains","5.reference\u002F03.configuration\u002F04.library-and-chains",{"title":318,"path":319,"stem":320},"harnesses.yaml","\u002Freference\u002Fconfiguration\u002Fharnesses-file","5.reference\u002F03.configuration\u002F05.harnesses-file",{"title":322,"path":323,"stem":324},"access.yaml","\u002Freference\u002Fconfiguration\u002Faccess","5.reference\u002F03.configuration\u002F06.access",{"title":326,"path":327,"stem":328},"intake.yaml","\u002Freference\u002Fconfiguration\u002Fintake","5.reference\u002F03.configuration\u002F07.intake",{"title":330,"path":331,"stem":332},"notify.yaml","\u002Freference\u002Fconfiguration\u002Fnotify","5.reference\u002F03.configuration\u002F08.notify",{"title":334,"path":335,"stem":336},"theme.yaml","\u002Freference\u002Fconfiguration\u002Ftheme","5.reference\u002F03.configuration\u002F09.theme",{"title":338,"path":339,"stem":340,"children":341},"Sandboxed workers","\u002Freference\u002Fconfiguration\u002Fsandbox","5.reference\u002F03.configuration\u002F10.sandbox\u002Findex",[342,343,347,351,355,359,363,367],{"title":10,"path":339,"stem":340},{"title":344,"path":345,"stem":346},"Resource limits","\u002Freference\u002Fconfiguration\u002Fsandbox\u002Fresource-limits","5.reference\u002F03.configuration\u002F10.sandbox\u002F1.resource-limits",{"title":348,"path":349,"stem":350},"Callbacks from a sandbox","\u002Freference\u002Fconfiguration\u002Fsandbox\u002Fcallbacks","5.reference\u002F03.configuration\u002F10.sandbox\u002F2.callbacks",{"title":352,"path":353,"stem":354},"Network policy","\u002Freference\u002Fconfiguration\u002Fsandbox\u002Fnetwork-policy","5.reference\u002F03.configuration\u002F10.sandbox\u002F3.network-policy",{"title":356,"path":357,"stem":358},"Credentials","\u002Freference\u002Fconfiguration\u002Fsandbox\u002Fcredentials","5.reference\u002F03.configuration\u002F10.sandbox\u002F4.credentials",{"title":360,"path":361,"stem":362},"Kits","\u002Freference\u002Fconfiguration\u002Fsandbox\u002Fkits","5.reference\u002F03.configuration\u002F10.sandbox\u002F5.kits",{"title":364,"path":365,"stem":366},"sandbox.yaml","\u002Freference\u002Fconfiguration\u002Fsandbox\u002Fsandbox-yaml","5.reference\u002F03.configuration\u002F10.sandbox\u002F6.sandbox-yaml",{"title":368,"path":369,"stem":370},"Git in a sandbox","\u002Freference\u002Fconfiguration\u002Fsandbox\u002Fgit-in-a-sandbox","5.reference\u002F03.configuration\u002F10.sandbox\u002F7.git-in-a-sandbox",{"title":372,"path":373,"stem":374},"Environment variables","\u002Freference\u002Fconfiguration\u002Fenvironment-variables","5.reference\u002F03.configuration\u002F11.environment-variables",{"title":376,"path":377,"stem":378,"children":379},"Chain file keys","\u002Freference\u002Fchain-nodes","5.reference\u002F04.chain-nodes\u002Findex",[380,381,385,389],{"title":10,"path":377,"stem":378},{"title":382,"path":383,"stem":384},"Subprocess tasks","\u002Freference\u002Fchain-nodes\u002Fsubprocess-tasks","5.reference\u002F04.chain-nodes\u002F2.subprocess-tasks",{"title":386,"path":387,"stem":388},"Fix loop and judge","\u002Freference\u002Fchain-nodes\u002Ffix-loop","5.reference\u002F04.chain-nodes\u002F3.fix-loop",{"title":390,"path":391,"stem":392},"Result file","\u002Freference\u002Fchain-nodes\u002Fresult-file","5.reference\u002F04.chain-nodes\u002F4.result-file",{"title":394,"path":395,"stem":396,"children":397},"Agent harnesses","\u002Freference\u002Fharnesses","5.reference\u002F05.harnesses\u002Findex",[398,399,403,407,411,415],{"title":10,"path":395,"stem":396},{"title":400,"path":401,"stem":402},"Unattended runs","\u002Freference\u002Fharnesses\u002Funattended-runs","5.reference\u002F05.harnesses\u002F2.unattended-runs",{"title":404,"path":405,"stem":406},"Agent profiles","\u002Freference\u002Fharnesses\u002Fagent-profiles","5.reference\u002F05.harnesses\u002F3.agent-profiles",{"title":408,"path":409,"stem":410},"Harness definition files","\u002Freference\u002Fharnesses\u002Fharness-files","5.reference\u002F05.harnesses\u002F4.harness-files",{"title":412,"path":413,"stem":414},"Fallback and escalation","\u002Freference\u002Fharnesses\u002Ffallback-and-escalation","5.reference\u002F05.harnesses\u002F5.fallback-and-escalation",{"title":416,"path":417,"stem":418},"Cost reporting","\u002Freference\u002Fharnesses\u002Fcost-reporting","5.reference\u002F05.harnesses\u002F6.cost-reporting",{"title":420,"path":421,"stem":422},"Permission gate","\u002Freference\u002Fpermissions","5.reference\u002F06.permissions",{"title":424,"path":425,"stem":426},"Inbound triggers","\u002Freference\u002Ftriggers","5.reference\u002F07.triggers",{"title":428,"path":429,"stem":430,"children":431},"HTTP API","\u002Freference\u002Fhttp-api","5.reference\u002F08.http-api\u002Findex",[432,433,437,441,445,449,453,457],{"title":10,"path":429,"stem":430},{"title":434,"path":435,"stem":436},"Filing, reading and changing work items","\u002Freference\u002Fhttp-api\u002Fwork-items","5.reference\u002F08.http-api\u002F2.work-items",{"title":438,"path":439,"stem":440},"Gates, run control, ending and retry","\u002Freference\u002Fhttp-api\u002Fgates-run-control-and-ending","5.reference\u002F08.http-api\u002F3.gates-run-control-and-ending",{"title":442,"path":443,"stem":444},"The work item object","\u002Freference\u002Fhttp-api\u002Fwork-item-object","5.reference\u002F08.http-api\u002F4.work-item-object",{"title":446,"path":447,"stem":448},"Budget, events, diff and documents","\u002Freference\u002Fhttp-api\u002Fbudget-and-events","5.reference\u002F08.http-api\u002F5.budget-and-events",{"title":450,"path":451,"stem":452},"Repos, chains, harnesses and the server","\u002Freference\u002Fhttp-api\u002Frepos-chains-harnesses-and-server","5.reference\u002F08.http-api\u002F6.repos-chains-harnesses-and-server",{"title":454,"path":455,"stem":456},"Drafts","\u002Freference\u002Fhttp-api\u002Fdrafts","5.reference\u002F08.http-api\u002F7.drafts",{"title":458,"path":459,"stem":460},"Ops for each draft area","\u002Freference\u002Fhttp-api\u002Fdraft-ops","5.reference\u002F08.http-api\u002F8.draft-ops",{"title":462,"path":463,"stem":464},"MCP tools","\u002Freference\u002Fmcp-tools","5.reference\u002F09.mcp-tools",{"title":466,"path":467,"stem":468},"Events","\u002Freference\u002Fevents","5.reference\u002F10.events",{"title":470,"path":471,"stem":472,"children":473},"Security and project","\u002Fproject","6.project",[474,476,480,484,488,492,496,500],{"title":10,"path":471,"stem":475},"6.project\u002Findex",{"title":477,"path":478,"stem":479},"Security","\u002Fproject\u002Fsecurity","6.project\u002F1.security",{"title":481,"path":482,"stem":483},"Data and privacy","\u002Fproject\u002Fdata-and-privacy","6.project\u002F2.data-and-privacy",{"title":485,"path":486,"stem":487},"What's new in 2.0","\u002Fproject\u002Fwhats-new","6.project\u002F3.whats-new",{"title":489,"path":490,"stem":491},"Status and support","\u002Fproject\u002Fstatus-and-support","6.project\u002F4.status-and-support",{"title":493,"path":494,"stem":495},"Architecture","\u002Fproject\u002Farchitecture","6.project\u002F5.architecture",{"title":497,"path":498,"stem":499},"Source map","\u002Fproject\u002Fsource-map","6.project\u002F6.source-map",{"title":501,"path":502,"stem":503},"Contributing","\u002Fproject\u002Fcontributing","6.project\u002F7.contributing",{"id":505,"title":127,"body":506,"description":1347,"extension":1348,"links":1349,"meta":1350,"navigation":1351,"path":128,"seo":1352,"stem":129,"__hash__":1353},"docs\u002F3.guides\u002F3.harnesses\u002F3.worker-kit.md",{"type":507,"value":508,"toc":1337},"minimark",[509,537,554,557,562,591,595,616,658,663,675,679,683,693,954,961,1017,1021,1079,1090,1093,1097,1106,1148,1155,1177,1180,1184,1200,1206,1213,1224,1236,1260,1267,1271,1274,1300,1310,1314,1333],[510,511,512,516,517,520,521,524,525,529,530,533,534,536],"p",{},[513,514,515],"strong",{},"Want workers in a plain container, with no Kit?"," Under the repository's entry in ",[518,519,292],"code",{},", set ",[518,522,523],{},"sandbox: {kind: docker, image: \u003Cyour image>, network: \u003Chosts>}","; a sandbox needs a ",[526,527,528],"a",{"href":353},"network policy"," or ",[518,531,532],{},"unrestricted_network: true",". ",[526,535,338],{"href":339}," has the rest of the keys.",[510,538,539,540,544,545,548,549,553],{},"Build a Kit for Claude ",[526,541,543],{"href":542},"\u002Fconcepts\u002Fvocabulary#worker","workers",", push it to your registry, and point a repository at it. A ",[526,546,547],{"href":361},"Kit"," is an image that carries its own ",[526,550,552],{"href":551},"\u002Fconcepts\u002Fvocabulary#sandbox","sandbox"," policy: which hosts its workload may reach, which credentials it holds, and its limits. Kraft publishes no worker image of its own.",[510,555,556],{},"Kraft runs a Kit you build for it. Docker's published Kits require capabilities Kraft does not enforce, so Kraft refuses them.",[558,559,561],"h2",{"id":560},"before-you-start","Before you start",[563,564,565,577,588],"ul",{},[566,567,568,569,572,573,576],"li",{},"Docker with BuildKit (",[518,570,571],{},"docker buildx version"," prints it), logged in to a registry you can push to. Replace ",[518,574,575],{},"registry.example.com\u002Facme"," below with yours.",[566,578,579,580,583,584,587],{},"The machine that runs Kraft logged in to the same registry: Kraft reads the Kit with that machine's ",[518,581,582],{},"docker manifest inspect"," and pulls it with its ",[518,585,586],{},"docker run",".",[566,589,590],{},"An Anthropic API key in the Kraft server's environment.",[558,592,594],{"id":593},"_1-write-the-image","1. Write the image",[510,596,597,598,601,602,605,606,609,610,613,614,587],{},"The image needs the agent CLI on its ",[518,599,600],{},"PATH"," and the minimum every sandboxed image needs: ",[518,603,604],{},"git",", ",[518,607,608],{},"sh",", CA certificates, and ",[518,611,612],{},"curl"," under a network policy. See ",[526,615,338],{"href":339},[617,618,624],"pre",{"className":619,"code":620,"filename":621,"language":622,"meta":623,"style":623},"language-dockerfile shiki shiki-themes github-light-high-contrast github-light-high-contrast github-dark-high-contrast","FROM docker.io\u002Flibrary\u002Fnode:22-slim\nRUN apt-get update \\\n && apt-get install -y --no-install-recommends bash ca-certificates curl git \\\n && rm -rf \u002Fvar\u002Flib\u002Fapt\u002Flists\u002F*\nRUN npm install -g @anthropic-ai\u002Fclaude-code\n","Dockerfile","dockerfile","",[518,625,626,634,640,646,652],{"__ignoreMap":623},[627,628,631],"span",{"class":629,"line":630},"line",1,[627,632,633],{},"FROM docker.io\u002Flibrary\u002Fnode:22-slim\n",[627,635,637],{"class":629,"line":636},2,[627,638,639],{},"RUN apt-get update \\\n",[627,641,643],{"class":629,"line":642},3,[627,644,645],{}," && apt-get install -y --no-install-recommends bash ca-certificates curl git \\\n",[627,647,649],{"class":629,"line":648},4,[627,650,651],{}," && rm -rf \u002Fvar\u002Flib\u002Fapt\u002Flists\u002F*\n",[627,653,655],{"class":629,"line":654},5,[627,656,657],{},"RUN npm install -g @anthropic-ai\u002Fclaude-code\n",[510,659,660,661,587],{},"Save it as ",[518,662,621],{},[510,664,665,666,669,670,674],{},"The image needs no agent ",[518,667,668],{},"Entrypoint",". Kraft keeps the image's entrypoint and replaces its command with the one the ",[526,671,673],{"href":672},"\u002Fconcepts\u002Fvocabulary#harness","harness"," file builds. A Kit whose entrypoint is the agent itself does not work.",[676,677,678],"note",{},"Kraft mounts each session's result file into the container, so a tool that replaces it by renaming a new file over it would fail. The Claude CLI writes it in place.",[558,680,682],{"id":681},"_2-write-the-descriptor","2. Write the descriptor",[510,684,685,686,689,690,692],{},"Save this as ",[518,687,688],{},"kraft-worker-claude.yaml"," beside the ",[518,691,621],{},":",[617,694,698],{"className":695,"code":696,"filename":688,"language":697,"meta":623,"style":623},"language-yaml shiki shiki-themes github-light-high-contrast github-light-high-contrast github-dark-high-contrast","# syntax=docker\u002Fsandbox-kit:3\nschemaVersion: \"3\"\nkind: workload\ndisplayName: Kraft claude worker\ndockerfile: Dockerfile\ncapabilities:\n  - type: com.docker.sandbox\u002Fnetwork-policy@1\n    config:\n      runtime:\n        allow: [api.anthropic.com, statsig.anthropic.com]\n  - type: com.docker.sandbox\u002Fcredential@1\n    config:\n      service: anthropic\n      phase: runtime\n      apiKey:\n        name: ANTHROPIC_API_KEY\n        proxyManaged: true\n        inject:\n          - {domain: api.anthropic.com, header: x-api-key}\n  - type: com.docker.sandbox\u002Fresources@1\n    config: {cpu: 2, memory: 2gib}\n","yaml",[518,699,700,706,720,730,740,749,758,772,780,788,808,820,827,838,849,857,868,880,888,914,926],{"__ignoreMap":623},[627,701,702],{"class":629,"line":630},[627,703,705],{"class":704},"sq92B","# syntax=docker\u002Fsandbox-kit:3\n",[627,707,708,712,716],{"class":629,"line":636},[627,709,711],{"class":710},"sb7M8","schemaVersion",[627,713,715],{"class":714},"s7iLA",": ",[627,717,719],{"class":718},"semJd","\"3\"\n",[627,721,722,725,727],{"class":629,"line":642},[627,723,724],{"class":710},"kind",[627,726,715],{"class":714},[627,728,729],{"class":718},"workload\n",[627,731,732,735,737],{"class":629,"line":648},[627,733,734],{"class":710},"displayName",[627,736,715],{"class":714},[627,738,739],{"class":718},"Kraft claude worker\n",[627,741,742,744,746],{"class":629,"line":654},[627,743,622],{"class":710},[627,745,715],{"class":714},[627,747,748],{"class":718},"Dockerfile\n",[627,750,752,755],{"class":629,"line":751},6,[627,753,754],{"class":710},"capabilities",[627,756,757],{"class":714},":\n",[627,759,761,764,767,769],{"class":629,"line":760},7,[627,762,763],{"class":714},"  - ",[627,765,766],{"class":710},"type",[627,768,715],{"class":714},[627,770,771],{"class":718},"com.docker.sandbox\u002Fnetwork-policy@1\n",[627,773,775,778],{"class":629,"line":774},8,[627,776,777],{"class":710},"    config",[627,779,757],{"class":714},[627,781,783,786],{"class":629,"line":782},9,[627,784,785],{"class":710},"      runtime",[627,787,757],{"class":714},[627,789,791,794,797,800,802,805],{"class":629,"line":790},10,[627,792,793],{"class":710},"        allow",[627,795,796],{"class":714},": [",[627,798,799],{"class":718},"api.anthropic.com",[627,801,605],{"class":714},[627,803,804],{"class":718},"statsig.anthropic.com",[627,806,807],{"class":714},"]\n",[627,809,811,813,815,817],{"class":629,"line":810},11,[627,812,763],{"class":714},[627,814,766],{"class":710},[627,816,715],{"class":714},[627,818,819],{"class":718},"com.docker.sandbox\u002Fcredential@1\n",[627,821,823,825],{"class":629,"line":822},12,[627,824,777],{"class":710},[627,826,757],{"class":714},[627,828,830,833,835],{"class":629,"line":829},13,[627,831,832],{"class":710},"      service",[627,834,715],{"class":714},[627,836,837],{"class":718},"anthropic\n",[627,839,841,844,846],{"class":629,"line":840},14,[627,842,843],{"class":710},"      phase",[627,845,715],{"class":714},[627,847,848],{"class":718},"runtime\n",[627,850,852,855],{"class":629,"line":851},15,[627,853,854],{"class":710},"      apiKey",[627,856,757],{"class":714},[627,858,860,863,865],{"class":629,"line":859},16,[627,861,862],{"class":710},"        name",[627,864,715],{"class":714},[627,866,867],{"class":718},"ANTHROPIC_API_KEY\n",[627,869,871,874,876],{"class":629,"line":870},17,[627,872,873],{"class":710},"        proxyManaged",[627,875,715],{"class":714},[627,877,879],{"class":878},"ssYy9","true\n",[627,881,883,886],{"class":629,"line":882},18,[627,884,885],{"class":710},"        inject",[627,887,757],{"class":714},[627,889,891,894,897,899,901,903,906,908,911],{"class":629,"line":890},19,[627,892,893],{"class":714},"          - {",[627,895,896],{"class":710},"domain",[627,898,715],{"class":714},[627,900,799],{"class":718},[627,902,605],{"class":714},[627,904,905],{"class":710},"header",[627,907,715],{"class":714},[627,909,910],{"class":718},"x-api-key",[627,912,913],{"class":714},"}\n",[627,915,917,919,921,923],{"class":629,"line":916},20,[627,918,763],{"class":714},[627,920,766],{"class":710},[627,922,715],{"class":714},[627,924,925],{"class":718},"com.docker.sandbox\u002Fresources@1\n",[627,927,929,931,934,937,939,942,944,947,949,952],{"class":629,"line":928},21,[627,930,777],{"class":710},[627,932,933],{"class":714},": {",[627,935,936],{"class":710},"cpu",[627,938,715],{"class":714},[627,940,941],{"class":878},"2",[627,943,605],{"class":714},[627,945,946],{"class":710},"memory",[627,948,715],{"class":714},[627,950,951],{"class":718},"2gib",[627,953,913],{"class":714},[510,955,956,957,960],{},"Two of these capabilities need something from you: the Kit has no ",[518,958,959],{},"install"," phase, and a Kit for Claude lists Claude's own hosts itself. What each capability becomes in Kraft:",[563,962,963,987,1009],{},[566,964,965,970,971,973,974,976,977,979,980,983,984,986],{},[513,966,967],{},[518,968,969],{},"network-policy@1",": the sessions reach ",[518,972,799],{}," and ",[518,975,804],{}," and nothing else. There is no ",[518,978,959],{}," phase, so the repository's ",[518,981,982],{},"setup_command"," reaches nothing: build what setup needs into the image, or add an ",[518,985,959],{}," allow list. Kraft does not add the Claude harness's own hosts under a Kit, so a Kit for Claude lists them itself.",[566,988,989,994,995,998,999,1001,1002,1004,1005,1008],{},[513,990,991],{},[518,992,993],{},"credential@1",": the container sees ",[518,996,997],{},"ANTHROPIC_API_KEY"," only as a placeholder. Kraft's egress proxy, the proxy that carries a sandboxed session's outbound traffic, adds the real key to the ",[518,1000,910],{}," header on requests to ",[518,1003,799],{},". The value comes from the server variable you bind to the ",[518,1006,1007],{},"anthropic"," service in step 4.",[566,1010,1011,1016],{},[513,1012,1013],{},[518,1014,1015],{},"resources@1",": two CPUs and a 2 GiB memory limit on every session.",[558,1018,1020],{"id":1019},"_3-build-push-and-pin-it","3. Build, push and pin it",[617,1022,1026],{"className":1023,"code":1024,"language":1025,"meta":623,"style":623},"language-bash shiki shiki-themes github-light-high-contrast github-light-high-contrast github-dark-high-contrast","docker buildx build -f kraft-worker-claude.yaml \\\n  -t registry.example.com\u002Facme\u002Fkraft-worker-claude:1 --push .\ndocker buildx imagetools inspect registry.example.com\u002Facme\u002Fkraft-worker-claude:1\n","bash",[518,1027,1028,1050,1064],{"__ignoreMap":623},[627,1029,1030,1034,1037,1040,1043,1046],{"class":629,"line":630},[627,1031,1033],{"class":1032},"szw1H","docker",[627,1035,1036],{"class":718}," buildx",[627,1038,1039],{"class":718}," build",[627,1041,1042],{"class":878}," -f",[627,1044,1045],{"class":718}," kraft-worker-claude.yaml",[627,1047,1049],{"class":1048},"sklAV"," \\\n",[627,1051,1052,1055,1058,1061],{"class":629,"line":636},[627,1053,1054],{"class":878},"  -t",[627,1056,1057],{"class":718}," registry.example.com\u002Facme\u002Fkraft-worker-claude:1",[627,1059,1060],{"class":878}," --push",[627,1062,1063],{"class":718}," .\n",[627,1065,1066,1068,1070,1073,1076],{"class":629,"line":642},[627,1067,1033],{"class":1032},[627,1069,1036],{"class":718},[627,1071,1072],{"class":718}," imagetools",[627,1074,1075],{"class":718}," inspect",[627,1077,1078],{"class":718}," registry.example.com\u002Facme\u002Fkraft-worker-claude:1\n",[510,1080,1081,1082,1085,1086,1089],{},"The ",[518,1083,1084],{},"# syntax=docker\u002Fsandbox-kit:3"," line makes BuildKit build it with the Kit frontend, which puts the descriptor on the image's manifest. The second command prints the digest (",[518,1087,1088],{},"Digest: sha256:...",").",[510,1091,1092],{},"Pin the Kit by that digest. Kraft refuses a Kit named by tag alone, because a tag can point at a different Kit tomorrow.",[558,1094,1096],{"id":1095},"_4-point-a-repository-at-it","4. Point a repository at it",[510,1098,1099,1100,1105],{},"In ",[526,1101,1103],{"href":1102},"\u002Freference\u002Fconfiguration\u002Frepos#sandbox",[518,1104,292],{},", under the repository's entry:",[617,1107,1110],{"className":695,"code":1108,"filename":1109,"language":697,"meta":623,"style":623},"sandbox:\n  kind: kit\n  runtime: docker\n  kit: registry.example.com\u002Facme\u002Fkraft-worker-claude:1@sha256:\u003Cthe digest>\n","config\u002Frepos.yaml",[518,1111,1112,1118,1128,1138],{"__ignoreMap":623},[627,1113,1114,1116],{"class":629,"line":630},[627,1115,552],{"class":710},[627,1117,757],{"class":714},[627,1119,1120,1123,1125],{"class":629,"line":636},[627,1121,1122],{"class":710},"  kind",[627,1124,715],{"class":714},[627,1126,1127],{"class":718},"kit\n",[627,1129,1130,1133,1135],{"class":629,"line":642},[627,1131,1132],{"class":710},"  runtime",[627,1134,715],{"class":714},[627,1136,1137],{"class":718},"docker\n",[627,1139,1140,1143,1145],{"class":629,"line":648},[627,1141,1142],{"class":710},"  kit",[627,1144,715],{"class":714},[627,1146,1147],{"class":718},"registry.example.com\u002Facme\u002Fkraft-worker-claude:1@sha256:\u003Cthe digest>\n",[510,1149,1099,1150,1154],{},[526,1151,1152],{"href":365},[518,1153,364],{},", bind the credential's service to the server variable holding the key:",[617,1156,1159],{"className":695,"code":1157,"filename":1158,"language":697,"meta":623,"style":623},"credentials:\n  anthropic: ANTHROPIC_API_KEY\n","config\u002Fsandbox.yaml",[518,1160,1161,1168],{"__ignoreMap":623},[627,1162,1163,1166],{"class":629,"line":630},[627,1164,1165],{"class":710},"credentials",[627,1167,757],{"class":714},[627,1169,1170,1173,1175],{"class":629,"line":636},[627,1171,1172],{"class":710},"  anthropic",[627,1174,715],{"class":714},[627,1176,867],{"class":718},[510,1178,1179],{},"The right-hand side is a variable in the Kraft server's environment. It can have any name.",[558,1181,1183],{"id":1182},"check-it-worked","Check it worked",[617,1185,1187],{"className":1023,"code":1186,"language":1025,"meta":623,"style":623},"kraft admin doctor\n",[518,1188,1189],{"__ignoreMap":623},[627,1190,1191,1194,1197],{"class":629,"line":630},[627,1192,1193],{"class":1032},"kraft",[627,1195,1196],{"class":718}," admin",[627,1198,1199],{"class":718}," doctor\n",[510,1201,1202,1203,1205],{},"The repository's ",[518,1204,552],{}," row reads and checks the Kit. If the Kit is refused, that row fails and names the Kit and why.",[510,1207,1208,1209,1212],{},"A ",[518,1210,1211],{},"kit hosts"," row is a warning, and it is expected: this Kit is for Claude, and sessions of other harnesses under it are refused their hosts. It reads:",[617,1214,1219],{"className":1215,"code":1217,"language":1218,"meta":623},[1216],"language-text","warn  kit hosts \u003Crepo>  the Kit does not allow what these harnesses need, so their sessions are refused it: amp requires ampcode.com; codex requires api.openai.com, chatgpt.com; gemini requires generativelanguage.googleapis.com\n","text",[518,1220,1221],{"__ignoreMap":623},[627,1222,1217],{"className":1223},[629],[510,1225,1226,1227,1231,1232,1235],{},"Then file a ",[526,1228,1230],{"href":1229},"\u002Fconcepts\u002Fvocabulary#work-item","work item"," on the repository. Its first task records a ",[518,1233,1234],{},"sandbox_kit_resolved"," event:",[617,1237,1239],{"className":1023,"code":1238,"language":1025,"meta":623,"style":623},"kraft view events ID --type sandbox_kit_resolved\n",[518,1240,1241],{"__ignoreMap":623},[627,1242,1243,1245,1248,1251,1254,1257],{"class":629,"line":630},[627,1244,1193],{"class":1032},[627,1246,1247],{"class":718}," view",[627,1249,1250],{"class":718}," events",[627,1252,1253],{"class":718}," ID",[627,1255,1256],{"class":878}," --type",[627,1258,1259],{"class":718}," sandbox_kit_resolved\n",[510,1261,1262,1263,587],{},"If the item stops instead, see ",[526,1264,1266],{"href":1265},"\u002Ftroubleshooting\u002Fsandbox-and-kit-stops#a-kit-is-refused","A Kit is refused",[558,1268,1270],{"id":1269},"change-the-kit","Change the Kit",[510,1272,1273],{},"A rebuilt Kit has a new digest, and an item filed before the change keeps the sandbox it was filed with.",[1275,1276,1277,1280,1287],"ol",{},[566,1278,1279],{},"Rebuild and push, as in step 3.",[566,1281,1282,1283,1286],{},"Copy the new digest from the ",[518,1284,1285],{},"imagetools inspect"," output.",[566,1288,1289,1290,1293,1294,1297,1298,587],{},"Put it in ",[518,1291,1292],{},"kit:"," under the repository's ",[518,1295,1296],{},"sandbox:"," in ",[518,1299,292],{},[510,1301,1302,1303,1305,1306,1309],{},"Kraft rereads ",[518,1304,292],{}," when an item is filed, so no ",[518,1307,1308],{},"kraft admin reload"," is needed.",[558,1311,1313],{"id":1312},"next-steps","Next steps",[563,1315,1316,1321,1328],{},[566,1317,1318,1320],{},[526,1319,360],{"href":361},": every field a Kit sandbox accepts.",[566,1322,1323,1327],{},[526,1324,1325],{"href":365},[518,1326,364],{},": bind credentials to server variables.",[566,1329,1330,1332],{},[526,1331,1266],{"href":1265},": the stop reasons for a Kit Kraft will not run.",[1334,1335,1336],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sq92B, html code.shiki .sq92B{--shiki-light:#66707B;--shiki-default:#66707B;--shiki-dark:#BDC4CC}html pre.shiki code .sb7M8, html code.shiki .sb7M8{--shiki-light:#024C1A;--shiki-default:#024C1A;--shiki-dark:#72F088}html pre.shiki code .s7iLA, html code.shiki .s7iLA{--shiki-light:#0E1116;--shiki-default:#0E1116;--shiki-dark:#F0F3F6}html pre.shiki code .semJd, html code.shiki .semJd{--shiki-light:#032563;--shiki-default:#032563;--shiki-dark:#ADDCFF}html pre.shiki code .ssYy9, html code.shiki .ssYy9{--shiki-light:#023B95;--shiki-default:#023B95;--shiki-dark:#91CBFF}html pre.shiki code .szw1H, html code.shiki .szw1H{--shiki-light:#702C00;--shiki-default:#702C00;--shiki-dark:#FFB757}html pre.shiki code .sklAV, html code.shiki .sklAV{--shiki-light:#A0111F;--shiki-default:#A0111F;--shiki-dark:#FF9492}",{"title":623,"searchDepth":636,"depth":636,"links":1338},[1339,1340,1341,1342,1343,1344,1345,1346],{"id":560,"depth":636,"text":561},{"id":593,"depth":636,"text":594},{"id":681,"depth":636,"text":682},{"id":1019,"depth":636,"text":1020},{"id":1095,"depth":636,"text":1096},{"id":1182,"depth":636,"text":1183},{"id":1269,"depth":636,"text":1270},{"id":1312,"depth":636,"text":1313},"Build a Docker Sandbox Kit for Kraft's Claude workers, push it to your registry, and run a repository's sandbox from it, pinned by digest.","md",null,{},true,{"title":127,"description":1347},"uMyOYWArjEg3jbxbnsySW6lceSPL3CO8PN5MtsgKw7E",[1355,1357],{"title":123,"path":124,"stem":125,"description":1356,"children":-1},"Add an agent CLI to Kraft with a YAML file, and override a shipped one.",{"title":131,"path":132,"stem":133,"description":1358,"children":-1},"Give the agent CLI a worker runs on, whether Claude Code, Codex, Cursor, OpenCode, Amp, Antigravity or Gemini CLI, a login it can use headless, and check that the worker reaches it.",1791801240573]