Atenție, postarea asta a fost depășită. De la v2.0.0, claudebox e o imagine copil subțire a lui aicodebox, baza agnostică la agent care deține acum fiecare suprafață descrisă mai jos. API-ul, endpointul compatibil cu OpenAI, serverul MCP, botul de Telegram și schedulerul de cron stau toate în bază și sunt împărțite cu pibox și codexbox. claudebox în sine e acum adaptorul de Claude Code plus un wrapper pe partea de host. Citește întâi postarea despre aicodebox, acolo stă de fapt arhitectura. Ce e mai jos încă merge și documentează suprafața proprie a lui claudebox, dar baza e povestea adevărată acum.
MCP e propriul lui mod, nu un colț al API-ului
Merită spus explicit, pentru că documentația l-a descris multă vreme ca pe un endpoint dinăuntrul modului API, iar asta îl subestimează. MCP rulează în două feluri:
Inside API mode mounted at /mcp on the API server, no extra process port 8080
Standalone its own uvicorn process, spawned as a sidecar port 8081Varianta de sine stătătoare coexistă cu orice alt mod în loc să îl înlocuiască și își ia propriul token, CLAUDEBOX_MCP_MODE_TOKEN, care nu cade înapoi pe tokenul de API. Îl lași gol și suprafața MCP nu are autentificare deloc, ceea ce e un default diferit și mult mai prost decât „moștenește ce folosește API-ul”. Setează-l deliberat.
Cinci unelte: run_prompt plus patru unelte de fișiere, list_files, read_file, write_file, delete_file, fiecare rezolvându-și path-ul sub rădăcina workspace-ului și respingând orice iese în afară. Preferă-le în loc să îndeși o încărcătură în prompt: agentul poate citi singur workspace-ul, deci „scrie inputul într-un fișier și spune-i care fișier” bate un prompt de 50 KB.
Folosesc Claude Code pentru tot. Scris de cod, depanat căcaturi, deployat infrastructură, administrat repo-uri, scris articole chiar pentru blogul ăsta și chiar automatizat sesiuni de browser din mers. A devenit coloana vertebrală a felului în care lucrez. Dar să dai unui agent AI acces complet la sistemul tău e al dracului de înfricoșător, nu pentru că ar fi Claude răuvoitor, ci pentru că rulează cu
--permission-mode bypassPermissions și are puterea să facă ce vrea. O comandă proastă și host-ul tău e praf. În zilele astea containerul în care rulează nici măcar nu mai e specific lui claudebox, e aicodebox cu un adaptor în formă de Claude înșurubat pe el.Răspunsul evident e: bagă-l într-un container. Dar să faci asta cum trebuie e o cu totul altă problemă. Am construit claudebox ca să o rezolv. Ce a început ca un simplu wrapper containerizat peste Claude Code a crescut în șapte feluri diferite de a rula Claude, fiecare chiar folositor, niciunul de umplutură.
Redenumirea
Chestia asta se numea înainte docker-claude-code, imaginea psyb0t/claude-code, binarul claude. Acum e claudebox, imaginea psyb0t/claudebox, binarul claudebox. Cheile SSH s-au mutat de la ~/.ssh/claude-code la ~/.ssh/claudebox.
Dacă faci upgrade: dezinstalezi binarul vechi, tragi imaginea nouă, rulezi din nou scriptul de instalare. Directorul tău de config ~/.claude și istoricul de sesiuni supraviețuiesc redenumirii neatinse.
v2.0.0, Rebazat pe aicodebox
Schimbarea mai mare a venit după redenumire. claudebox e acum o imagine copil subțire a lui psyb0t/aicodebox, o bază comună, agnostică la agent, care se ocupă de fiecare suprafață de mod. Același tipar ca psyb0t/pibox și psyb0t/codexbox. Serverul de API, botul de Telegram, schedulerul de cron și endpointul MCP stau toate în bază acum; claudebox contribuie cu un adaptor care știe să vorbească anume cu Claude Code. Reparațiile din bază ajung gratis în fiecare imagine copil.
Ăsta e un rebase arhitectural complet, deci a rupt lucruri. Toate sunt aliasate sau legate simbolic mai departe, ca să meargă configurațiile existente, dar numele canonice s-au schimbat:
- Endpointuri:
POST /run/cancel?runId=…a devenitDELETE /run/{run_id}.GET /healtha devenitGET /healthz. - Unealta MCP:
claude_runa devenitrun_prompt. Actualizează-ți configurațiile de client MCP. - Variabile de mediu:
CLAUDEBOX_MODE_APIa devenitCLAUDEBOX_API_MODE,CLAUDEBOX_MODE_CRON_FILEa devenitCLAUDEBOX_CRON_MODE_FILEși tot așa pe listă. Entrypointul aliasează numele vechi mai departe. - Căi: rădăcina de workspace
/workspacesa devenit/workspace(la singular). Home-ul din container/home/claude/.claudea devenit/home/aicode/.aicodebox. Legăturile simbolice de compatibilitate țin bind mounturile vechi să se rezolve. - Cron: doar croniter pe șase câmpuri. Pune
0în față la orice program pe cinci câmpuri pe care îl foloseai. - Dispărut: comanda
/bashdin Telegram. Reimplementeaz-o pe partea de client dacă ai nevoie de ea. - Varianta full:
make build-fullse așază acum peste imaginea minimală în loc să fie o țintă multi-stage separată.
Adaptorul vine cu 32 de teste unitare pytest, plus 9 teste de fum containerizate care rulează pe un binar claude simulat, healthz, lista de modele OpenAI, markerele init.d, legăturile simbolice de compatibilitate, aliasarea de variabile de mediu, injecția always-skills, argumentele în plus și modul de permisiuni implicit.
Șapte Interfețe, Un Singur Container
claudebox nu mai e doar un wrapper. Sunt șapte interfețe diferite spre Claude Code care rulează înăuntrul Docker:
- CLI interactiv: container persistent, reluare de sesiune, modul original
- CLI programatic: neinteractiv, merge din scripturi și din CI, cu propriul container dedicat
- Server HTTP API: API REST cu administrare de workspace-uri, operații pe fișiere, rulări sincrone și asincrone
- Endpoint compatibil cu OpenAI: înlocuitor direct la
/openai/v1/chat/completionscu streaming - Server MCP: cinci unelte pe care Claude le poate folosi din alți agenți prin Model Context Protocol
- Bot de Telegram: workspace-uri per chat, partajare de fișiere, comenzi de shell de pe telefon
- Scheduler de cron: joburi programate definite în YAML, cu rezoluție sub minut, istoric per job și notificări opționale pe Telegram
Instalare
curl -fsSL https://raw.githubusercontent.com/psyb0t/docker-claudebox/master/install.sh | bashAsta generează chei SSH la ~/.ssh/claudebox, trage imaginea (mereu, rerularea instalatorului e modul suportat de a face upgrade) și lasă binarul claudebox la /usr/local/bin/claudebox. Dacă trebuie să dai variabile de mediu instalatorului, exportă-le întâi pe o linie separată, pentru că dacă dai VAR=x curl ... | bash prin pipe nu se transmite variabila către script:
export CLAUDEBOX_INSTALL_DIR=/usr/local/bin
curl -fsSL https://raw.githubusercontent.com/psyb0t/docker-claudebox/master/install.sh | bashApoi:
claudeboxPrima rulare îți cere autentificare. După aia merge pur și simplu. Wrapper-ul se ocupă de tot ciclul de viață al containerului, creează unul nou dacă nu există deja pentru directorul curent, îl repornește și se reatașează dacă există.
Variante de Imagine
Full: psyb0t/claudebox:latest-full
Bază Ubuntu încărcată cu tot ce îi trebuie cu adevărat unui dezvoltator: Go cu tot toolchainul (golangci-lint, gopls, delve), Python 3.14 prin pyenv (flake8, black, mypy, pyright, vulture, pytest, poetry), Node.js 24 LTS cu ecosistemul obișnuit, toolchain de C/C++, Docker CE cu Compose, Terraform, kubectl, helm, GitHub CLI, clienți de baze de date pentru SQLite/PostgreSQL/MySQL/Redis și un morman de utilitare (jq, ripgrep, fd-find, bat, shellcheck, shfmt, httpie). Containerul își generează singur un CLAUDE.md care listează fiecare unealtă disponibilă, ca să știe Claude cu ce are de lucru.
Minimală: psyb0t/claudebox:latest
Doar strictul necesar peste baza aicodebox: Ubuntu 24.04, git/curl/wget/jq, Node.js 24 LTS cu npm, Python 3.14 cu uv, Docker CE. Imagine mai mică, tras mai rapid. Claude are sudo fără parolă, așa că își instalează din mers ce îi trebuie. Ține minte că denumirea s-a inversat în v2: latest e acum imaginea minimală (înainte era cea full), latest-full e buildul cu toolchain, iar vechiul opt-in CLAUDEBOX_MINIMAL=1 nu mai face nimic, pentru că minimala e implicită. CLAUDEBOX_FULL=1 e felul în care optezi în sens invers, iar dacă instalezi cu el setat se coace alegerea aia în wrapper, ca să rămână. Folosește init hooks ca să îți pre-coci setup-ul, ca să nu aștepți instalări de pachete la fiecare container proaspăt.
Claude Code în sine nu mai e în niciuna dintre imagini, iar motivul e licențierea. CLI-ul de la Anthropic e proprietar și fără drept de redistribuire, deci să publici o imagine cu el copt înăuntru ar însemna să livrezi softul altcuiva. În schimb imaginea cară versiunea fixată în CLAUDEBOX_CLAUDE_VERSION, iar entrypointul rulează npm install -g @anthropic-ai/claude-code@<version> prima dată când pornește un container proaspăt. Nimic de-al lui Anthropic nu călătorește în straturile publicate; fiecare container îl aduce singur de la npm. Costul e că prima pornire a unui container nou are nevoie de rețea și de câteva secunde în plus. Repornirile calde o sar complet. Vrei altă versiune, setezi CLAUDEBOX_CLAUDE_VERSION la docker run.
Cutiile se pot lansa una pe alta acum
Instalează claudebox, codexbox și pibox în același director și fiecare wrapper le montează pe celelalte două doar în citire la /usr/local/bin/<name>. Adică Claude, din interiorul propriului container, poate da shell la codexbox sau pibox și poate pune alt agent să facă o bucată de treabă. Utilizarea evidentă e o a doua părere despre un diff fără să ieși din sesiune.
Partea care a cerut gândire reală e contextul. O rulare imbricată trebuie să știe unde stau lucrurile pe host, nu înăuntrul containerului care se întâmplă să cheme, așa că există un bloc versionat pentru asta: AICODEBOX_LAUNCH_CONTEXT_VERSION=1 plus AICODEBOX_HOST_HOME, AICODEBOX_HOST_WORKSPACE, AICODEBOX_HOST_WRAPPER_DIR și, per agent, AICODEBOX_HOST_CLAUDE_HOME / CODEX_HOME / PI_HOME, cu câte un *_WRAPPER potrivit pentru fiecare. Versionat pentru că forma se va schimba și o lansare imbricată ar trebui să își poată da seama.
Rulările imbricate sunt și deliberat de unică folosință: sar peste scrierile de fișiere de autentificare pe care le face o rulare de nivel superior, deci un agent copil nu poate rescrie pe tăcute credențialele cutiei care l-a chemat.
Pe lângă asta, AICODEBOX_ENV_* și AICODEBOX_MOUNT_* transmit variabile de mediu și mounturi spre fiecare cutie, lângă CLAUDEBOX_ENV_* și CLAUDEBOX_MOUNT_* existente, care sunt per cutie. Iar AICODEBOX_MANAGED_INSTALL=1 e o instalare neinteractivă pentru scripturi de provisioning care, important, refuză să calce peste o cheie SSH care există deja. CLAUDEBOX_INSTALL_DIR și CLAUDEBOX_BIN_NAME controlează unde aterizează și cum se numește.
Un detaliu de lanț de aprovizionare care merită menționat: instalatorul trage acum wrapper.sh din tagul de release imutabil potrivit, nu din master, deci dacă instalezi o versiune fixată chiar primești wrapper-ul versiunii ăleia.
Modul Interactiv
Rulezi claudebox din orice director și primești o sesiune vie. Containerul persistă între rulări, sesiunea continuă de unde ai lăsat-o. Fiecare workspace primește propriul container, numit după calea directorului.
Comenzi utilitare:
claudebox --version # show version
claudebox doctor # health check
claudebox auth # manage authentication
claudebox setup-token # interactive OAuth token setup
claudebox stop # stop the running container for this workspace
claudebox clear-session # wipe session history, next run starts fresh
claudebox --update # pull the latest image and reinstallContinuitatea sesiunii. claudebox rulează Claude cu --continue, deci reia ultima conversație din directorul curent. Omori terminalul, te întorci a doua zi, îl pornești iar și Claude prinde exact de unde a rămas. Fără sesiune, nicio problemă, pornește de la zero.
Limita de memorie. Containerele sunt plafonate la 10g implicit. Suprascrii la lansare cu CLAUDEBOX_MAX_MEM=16g claudebox (vechiul CLAUDE_MAX_MEM încă merge).
Potrivirea UID/GID. Entrypointul detectează proprietarul workspace-ului și ajustează utilizatorul containerului ca să se potrivească. Fișierele create înăuntrul containerului au proprietarul corect pe host. Fără căcaturi cu chown -R.
Modul Programatic
Îi dai un prompt și claudebox rulează neinteractiv. Folosește un container _prog dedicat per workspace, separat de cel interactiv, fără TTY, merge din scripturi, din cron, din alte unelte:
# basic run
claudebox "explain this codebase"
# pick a model
claudebox "explain this codebase" --model sonnet
claudebox "audit this" --model opus
# output formats
claudebox "list all TODOs" --output-format json
claudebox "list all TODOs" --output-format json-verbose | jq .
claudebox "list all TODOs" --output-format stream-json | jq .
# reasoning effort
claudebox "debug this complex issue" --effort high
claudebox "quick question" --effort low
# custom system prompt
claudebox "review this" --system-prompt "You are a security auditor"
claudebox "review this" --append-system-prompt "Focus on SQL injection"
# structured output
claudebox "extract author and title" --output-format json
--json-schema '{"type":"object","properties":{"author":{"type":"string"},"title":{"type":"string"}}}'
# session control
claudebox "start over" --no-continue
claudebox "keep going" --resume abc123-def456Aliasuri de modele: opus (Opus 4.6), sonnet (Sonnet 4.6), haiku (Haiku 4.5), opusplan (Opus pentru planificare plus Sonnet pentru execuție), sonnet[1m] (Sonnet cu fereastră de context de 1M). Sau dai numele complet al unui model ca să fixezi o versiune anume.
Formate de ieșire: text (implicit), json (un singur obiect rezultat, cu costul și defalcarea pe tokeni), json-verbose (la fel ca json, dar cu un array turns care arată fiecare apel de unealtă, fiecare rezultat de unealtă și fiecare mesaj de asistent, vizibilitate completă asupra a ce a făcut Claude), stream-json (NDJSON, un eveniment pe linie, init de sistem, răspunsuri de asistent, folosire de unelte, rezultate de unelte, evenimente de rate limit, rezultatul final).
Modul API
Setezi CLAUDEBOX_API_MODE=1 ca să rulezi containerul ca server HTTP API. Îl bagi într-un stack docker-compose și alte servicii pot vorbi cu Claude peste HTTP:
services:
claudebox:
image: psyb0t/claudebox:latest
ports:
- "8080:8080"
environment:
- CLAUDEBOX_API_MODE=1
- CLAUDEBOX_API_MODE_TOKEN=your-secret-token
- CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-xxx
volumes:
- ~/.claude:/home/aicode/.aicodebox
- /your/projects:/workspace
- /var/run/docker.sock:/var/run/docker.sockEndpointuri:
- POST /run: trimiți un prompt, primești un rezultat. Câmpuri:
prompt,workspace,model,system_prompt,append_system_prompt,json_schema,effort,no_continue,resume. Întoarce 409 dacă workspace-ul procesează deja. - POST /run cu
"async": true: întoarce imediat unrunId. Interoghezi GET /run/result?runId=X până se termină. Tragi și uiți. - DELETE /run/{run_id}: omoară un proces care rulează (era
POST /run/cancel?runId=…înainte de v2) - GET /files/{path}: listează un director sau descarcă un fișier
- PUT /files/{path}: încarcă un fișier (directoarele părinte se creează automat)
- DELETE /files/{path}: șterge un fișier
- GET /healthz: verificare de sănătate, fără autentificare (era
GET /healthînainte de v2) - GET /status: arată ce workspace-uri sunt ocupate acum
Toate căile sunt relative la /workspace. Autentificare prin bearer token în headerul Authorization, setezi CLAUDEBOX_API_MODE_TOKEN ca să o activezi. Urmărirea workspace-urilor ocupate întoarce 409 Conflict, ca să nu îngrămădești din greșeală rulări suprapuse pe același workspace.
Ieșirea structurată și înregistrarea completă sunt butoane separate acum
Două lucruri s-au schimbat în API, lucruri care erau încurcate unul în altul. jsonSchema trece acum prin flagul propriu --json-schema al lui Claude Code în loc să fie lipit pe deasupra, iar reținerea evenimentelor e propriul ei control: eventMode: "full" pornește streamingul de mesaje parțiale, de text de la subagenți și de evenimente de hook și îți dă înapoi fiecare înregistrare nativă stream-json, fără să comprime ture și fără să trunchieze rezultate de unelte. Să vrei transcrierea întreagă nu mai cere să te prefaci că voiai o schemă, iar să ceri o schemă nu îți mai bagă pe gât tot furtunul. Alegi fiecare separat.
Endpoint Compatibil cu OpenAI
POST /openai/v1/chat/completions, un adaptor OpenAI de înlocuire directă care rutează cererile spre Claude Code din container. Merge cu orice vorbește API-ul OpenAI: LiteLLM, Open WebUI, clienți proprii, orice.
curl https://ciprian.51k.eu80/openai/v1/chat/completions
-H "Authorization: Bearer your-secret-token"
-H "Content-Type: application/json"
-d '{
"model": "sonnet",
"messages": [{"role": "user", "content": "explain this codebase"}],
"stream": true
}'Streamingul merge prin Server-Sent Events. Conversațiile pe mai multe ture merg, dai tot istoricul de mesaje și Claude ține contextul. Merge și multimodalul, trimiți conținut de imagine în base64 în mesaj și Claude îl poate vedea.
Headere proprii pentru controlul comportamentului:
X-Claude-Workspace: în ce workspace să rulezeX-Claude-Continue: dacă să continue sesiunea anterioarăX-Claude-Append-System-Prompt: adaugă instrucțiuni suplimentare la promptul de sistem
Pentru LiteLLM, îl îndrepți spre http://your-host:8080/openai/v1 ca provider OpenAI personalizat și merge fără nicio configurație specială.
Tură de întărire. Adaptorul OpenAI a primit o suită de teste adevărată și un audit de securitate: o gardă anti-SSRF respinge cererile care încearcă să strecoare URL-uri interne prin câmpurile de workspace, valorile finish_reason sunt mapate cum trebuie, ca să vadă clienții OpenAI stop/length/tool_calls în loc de gunoi, conversațiile pe mai multe ture rămân corect pe același workspace la continuări, iar câmpurile de cerere nesuportate întorc acum 400 în loc să fie aruncate în tăcere. Susținut de 24 de teste unitare și 3 teste de integrare, ca să rămână suprafața cinstită pe măsură ce crește.
Server MCP
Activează serverul MCP la /mcp/ ca să lași alți agenți și alte unelte să cheme în containerul tău de Claude prin Model Context Protocol. Cinci unelte expuse:
- run_prompt: rulează un prompt într-un workspace și îți dă rezultatul înapoi (redenumită din
claude_runîn v2.0.0) - list_files: listează fișierele dintr-un director de workspace
- read_file: citește un fișier dintr-un workspace
- write_file: scrie un fișier într-un workspace
- delete_file: șterge un fișier dintr-un workspace
Asta înseamnă că alte instanțe de Claude, agenți proprii sau orice client compatibil MCP pot folosi instanța ta de claudebox ca pe o unealtă, delegând muncă unei sesiuni proaspete de Claude cu acces complet la fișiere.
Modul Telegram
Setezi CLAUDEBOX_TELEGRAM_MODE=1 și primești un bot de Telegram care vorbește cu Claude. Fiecare chat primește propriul workspace și propriile setări. Trimiți text, fișiere, poze, clipuri, mesaje vocale. Primești fișiere înapoi cu /fetch.
Configurarea stă într-un fișier YAML, cu model, effort, workspace, prompt de sistem și buget per chat:
# ~/.claude/telegram.yml
allowed_chats:
- 123456789
- -987654321
default:
model: sonnet
effort: high
continue: true
chats:
123456789:
workspace: my-project
model: opus
effort: max
system_prompt: "You are a senior engineer"
max_budget_usd: 5.00
-987654321:
workspace: team-stuff
model: sonnet
allowed_users:
- 123456789services:
claudebox-telegram:
image: psyb0t/claudebox:latest
environment:
- CLAUDEBOX_TELEGRAM_MODE=1
- CLAUDEBOX_TELEGRAM_MODE_TOKEN=123456:ABC-DEF
- CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-xxx
volumes:
- ~/.claude:/home/aicode/.aicodebox
- ~/telegram-workspaces:/workspace
- /var/run/docker.sock:/var/run/docker.sockComenzile botului:
- orice text → trimis lui Claude ca prompt
- trimiți un fișier/poză/clip/voce → salvat în workspace, iar descrierea devine promptul
/model [name]: arată modelul curent cu butoane selectabile sau îl setează direct:haiku,sonnet,opus,opusplan,reset/effort [level]: arată sau selectează efortul:low,medium,high,xhigh,max,reset/system_prompt [text]: arată, setează sau resetează suprascrierea de prompt de sistem pentru chatul ăsta/append_system_prompt [text]: la fel, pentru promptul de sistem adăugat/fetch <path>: trimite înapoi un fișier din workspace ca atașament de Telegram/cancel: omoară procesul Claude care rulează pentru chatul ăsta/status: arată ce chaturi au acum procese care rulează/config: afișează configurația curentă a chatului ăstuia/reload: reîncarcă la cald configurația YAML fără să repornești containerul
Claude poate împinge fișiere înapoi punând [SEND_FILE: path] în răspunsul lui. Imaginile vin ca poze, clipurile ca video, tot restul ca documente. Răspunsurile lungi se despart automat în mai multe mesaje.
Randarea de Markdown. Botul traduce ieșirea markdown a lui Claude în dialectul HTML al lui Telegram înainte să o trimită, iar bold, italic, cod inline, blocuri de cod, citate, titluri, liste și linkuri se randează toate nativ în chat. Gata cu **asteriscurile brute și accentele grave care îți poluează mesajele. Octeții NUL din ieșirea uneltelor sunt mapați pe un substitut din zona de uz privat, ca să supraviețuiască drumului dus-întors spre Telegram fără să trunchieze mesajul.
Modul Cron
Setezi CLAUDEBOX_CRON_MODE=1 și îndrepți CLAUDEBOX_CRON_MODE_FILE spre un fișier YAML ca să rulezi joburi Claude programate. Doar croniter pe șase câmpuri de la v2.0.0, */30 * * * * * se declanșează la fiecare 30 de secunde. Configurațiile de dinainte de v2, scrise cu intrări pe cinci câmpuri, au nevoie de un 0 pus în față.
model: haiku # default model for all jobs
append_system_prompt: |
The current date and time is {system_datetime}.
telegram_chat_id: -1001234567890 # optional: post results to this Telegram chat
jobs:
- name: hourly_check
schedule: "0 0 * * * *"
instruction: |
Look at the git log for the last hour. Summarize commits.
- name: every_30_seconds
schedule: "*/30 * * * * *" # sub-minute
model: sonnet
instruction: Write the current UTC timestamp to ./status.txt.
- name: nightly_cleanup
schedule: "0 0 3 * * *"
model: opus
system_prompt: |
You are a cleanup agent. Current time: {system_datetime}.
instruction: |
Find files older than 7 days under ./tmp and delete them.Variabile de șablon disponibile în instruction, system_prompt și append_system_prompt: {system_datetime} (data și ora UTC curente) și {job_name} (câmpul de nume al jobului). model, system_prompt și append_system_prompt per job suprascriu valorile implicite din rădăcină.
services:
claudebox-cron:
image: psyb0t/claudebox:latest
environment:
- CLAUDEBOX_CRON_MODE=1
- CLAUDEBOX_CRON_MODE_FILE=/home/aicode/.aicodebox/cron.yaml
- CLAUDEBOX_WORKSPACE=/workspace
- CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-xxx
volumes:
- ./cron.yaml:/home/aicode/.aicodebox/cron.yaml:ro
- ./workspace:/workspace
- ~/.claude:/home/aicode/.aicodebox
- /var/run/docker.sock:/var/run/docker.sockSchedulerul rulează în prim-plan, iar docker logs arată fiecare tic. Dacă un job încă rulează când se declanșează ticul următor, ticul ăla se sare. Istoricul jobului curge spre ~/.claude/cron/history/<workspace-slug>/<timestamp>-<job-name>/ sub formă de activity.jsonl, stderr.log și meta.json.
Setezi telegram_chat_id (în rădăcină sau per job) plus CLAUDEBOX_TELEGRAM_MODE_TOKEN ca să îți ajungă rezultatul lui Claude pe Telegram după ce se termină fiecare job. Botul de Telegram nu trebuie să ruleze, cronul folosește tokenul direct.
Efort de raționament per job. Setezi effort în rădăcină pentru o valoare implicită și suprascrii per job, aceeași scară ca la CLI (low, medium, high, xhigh, max). Modele ieftine pentru joburi ieftine, efort maxim pentru auditul nocturn nasol.
Istoricul rulărilor anterioare, injectat automat. Fiecare tic de cron adaugă acum un bloc de sistem care îi spune lui Claude unde stau rulările lui anterioare, rădăcina de istoric, directorul de istoric al workspace-ului și directorul de istoric per job (~/.claude/cron/history/<workspace-slug>/*-<job-name>/). Claude nu le citește lacom; primește căile și decide dacă face Glob sau Read atunci când jobul chiar cere analiză de tendințe sau detectare de regresii. Prima rulare din istorie sare peste indiciu, pentru că încă nu există nimic. Asta deblochează „compară cu săptămâna trecută”, „a regresat metrica asta”, „ce s-a schimbat de la rularea de ieri”, fără să cablezi nimic din toate astea per job. Combinat cu telegram_chat_id primești un agent de rezumat zilnic care chiar știe ce a zis ieri.
Personalizare
Skilluri Mereu Active
Pui fișiere SKILL.md în ~/.claude/.always-skills/ și se injectează automat în fiecare invocare de claudebox, interactivă, programatică, API, Telegram, cron, toate. Context persistent care îl urmează pe Claude în fiecare sesiune, fără să atingi fișierele CLAUDE.md ale proiectelor individuale.
Hookuri de Init
Scripturile din ~/.claude/init.d/*.sh rulează o singură dată la prima creare a containerului, ca root, înainte de a coborî la utilizatorul claude. Nu mai rulează la docker start-urile următoare, doar pe containere proaspete. Folosește-le pentru instalări de pachete în plus sau pentru setup făcut o singură dată:
mkdir -p ~/.claude/init.d
cat > ~/.claude/init.d/setup.sh << 'EOF'
#!/bin/bash
apt-get update && apt-get install -y some-package
pip install some-library
EOF
chmod +x ~/.claude/init.d/setup.shScripturi Proprii
Pui executabile în ~/.claude/bin/ pe host și sunt în PATH înăuntrul fiecărui container. Persistă în toate sesiunile, în toate workspace-urile.
Transmiterea Variabilelor de Mediu
Folosește prefixul CLAUDEBOX_ENV_ ca să dai variabile de mediu arbitrare în container, iar prefixul se taie:
CLAUDEBOX_ENV_GITHUB_TOKEN=xxx CLAUDEBOX_ENV_MY_VAR=hello claudebox "do stuff"Mounturi de Volum Suplimentare
Prefixul CLAUDEBOX_MOUNT_ ca să montezi directoare suplimentare:
# Mount at same path on both sides
CLAUDEBOX_MOUNT_DATA=/data claudebox "process the data"
# Explicit source:dest
CLAUDEBOX_MOUNT_STUFF=/host/path:/container/path claudebox "do stuff"
# Read-only
CLAUDEBOX_MOUNT_RO=/data:/data:ro claudebox "read the data"Modelul de Workspace
claudebox creează două containere per workspace: claude-<path> pentru sesiuni interactive și claude-<path>_prog pentru rulări programatice. Nu împart stare și pot rula simultan. Sesiunea interactivă nu îți blochează scripturile. Scripturile nu îți întrerup sesiunea.
Directorul ~/.claude se montează în fiecare container, iar configurația, cheile de API, skillurile mereu active, hookurile de init și scripturile proprii sunt toate împărțite între workspace-uri. Cheile SSH din ~/.ssh/claudebox se montează automat. Izolarea e la nivel de workspace, identitatea e comună.
Socketul Docker se montează și el, ca să poată Claude construi imagini, ridica stackuri de compose și administra containere din interiorul propriului container. Pentru că workspace-ul se montează pe calea lui reală de pe host ($PWD:$PWD), mounturile de volum din interiorul lui Claude se rezolvă corect pe host. Claude scrie un docker-compose.yml, îl rulează, iar căile merg.
Își Livrează Propriul Skill și Plugin
Repo-ul cară .agents/skills/claudebox/, un skill de agent care documentează fiecare mod pe care îl expune cutia, așa că un asistent pe care îl îndrepți spre el știe deja shellul interactiv, execuția dintr-un foc, API-ul REST, endpointul compatibil cu OpenAI, serverul MCP, botul de Telegram și schedulerul de cron, fără să îi explici nimic.
Lângă el, @psyb0t/claudebox la .agents/plugins/claudebox/, o punte MCP stdio↔HTTP peste mcp-remote, ca să poată un agent OpenClaw sau MCP să conducă direct endpointul /mcp al unei cutii care rulează. Licențiat MIT. CI le publică pe amândouă pe ClawHub la push-uri de tag.
Modelul de Securitate
Chestia asta rulează cu --permission-mode bypassPermissions, echivalentul modern al vechiului --dangerously-skip-permissions. Claude are sudo fără parolă înăuntrul containerului și poate face ce vrea.
Granița de securitate e containerul. Claude nu îți poate atinge sistemul de fișiere al host-ului dincolo de workspace-ul montat și de configul ~/.claude. Dacă o ia razna, docker stop și docker rm și s-a dus. Ridici unul proaspăt în câteva secunde.
Montarea socketului Docker e excepția, pentru că dă acces la daemonul Docker al host-ului. Nu îl monta dacă te îngrijorează asta. Tot restul e ținut în frâu.
Cheile SSH stau în ~/.ssh/claudebox, o pereche de chei dedicată, generată în timpul instalării. Cheile tale personale nu intră niciodată în container. Configurezi ce cheie se folosește prin CLAUDEBOX_SSH_DIR, dacă e nevoie.
Lanțul de aprovizionare. Imaginea de bază e fixată pe digest @sha256:, nu doar pe un tag, pentru că tagurile sunt mutabile, iar un digest e adresat prin conținut, deci o reconstrucție nu poate trage pe tăcute alți octeți de bază. În imaginea full, arhiva de Go se descarcă pe disc și se verifică cu sha256sum -c pe o sumă de control per arhitectură înainte de extragere, în loc de vechea țeavă neverificată curl … | tar. O descărcare falsificată sau trunchiată pică buildul în loc să aterizeze în imagine.
Autentificarea modului API se face prin bearer token în headerul Authorization. Setezi CLAUDEBOX_API_MODE_TOKEN. Dacă nu îl setezi, API-ul rulează neautentificat, ceea ce e în regulă pentru uz local și o idee proastă expus pe o rețea.
Pe Scurt
Rulez acum fiecare sesiune de Claude înăuntrul lui claudebox. Șapte moduri, zero poluare a host-ului. Izolarea înseamnă că nu stau pe gânduri când îl las să instaleze pachete, să rescrie configurații sau să ruleze orice comenzi îi trebuie ca să ducă treaba la capăt. Continuitatea sesiunii înseamnă că închid terminalul, mă întorc peste câteva ore și prind exact de unde am rămas. API-ul și endpointul OpenAI înseamnă că pot lega Claude de alte servicii fără să scriu cod de lipit. Botul de Telegram înseamnă că pot porni o sarcină de pe telefon când sunt departe de birou. Schedulerul de cron înseamnă că Claude muncește în timp ce eu dorm.
Ia-l de aici: github.com/psyb0t/docker-claudebox
Licențiat sub WTFPL, pentru că singurul lucru mai periculos decât un AI cu acces de root e un AI cu acces de root și o licență restrictivă.
Cum Îl Instalezi în Agentul Tău
Claude Code care rulează Claude Code într-o cutie, iar acum instalabil chiar din Claude Code, ceea ce e cam atât de recursiv pe cât vreau să ajung. Tot ce e sub .agents/ e catalogat într-un singur marketplace, deci sunt două comenzi:
claude plugin marketplace add psyb0t/agents
claude plugin install claudebox@psyb0tCodex folosește același marketplace cu alt verb, codex plugin add claudebox@psyb0t, pentru că nu există codex plugin install. Găsește singur și skillul într-un checkout al repo-ului, pentru că scanează .agents/skills/ nativ, fără să fie instalat absolut nimic. E listat acum și pe MCP Registry-ul oficial, deci un client care rezolvă servere de acolo îl poate găsi fără să i se dea un URL.