codexbox: Vier Umgebungsvariablen und ein mkdir Zwischen Dir und OpenAIs CLI

Die Tirade „warum ich meinen eigenen Repos die Installation herausgerissen und ein Basis-Image gebaut habe“ habe ich schon im aicodebox-Beitrag geschrieben, also mache ich das hier nicht noch einmal. Kurzfassung: ich habe claudebox für Claude Code gebaut, ihm eine HTTP-API, einen OpenAI-kompatiblen Endpoint, einen MCP-Server, einen Telegram-Bot und einen Cron-Scheduler wachsen lassen, wollte dann exakt dasselbe für einen zweiten Agenten und habe mich geweigert, neunhundert Zeilen FastAPI und Telegram-Markdown-Rendering ein drittes Mal in ein neues Repo zu kopieren. Also wurde die Installation in aicodebox herausgerissen, ein agentenagnostisches Basis-Image, und jeder konkrete Agent wurde zu einem dünnen Kind-Image, das bloß eine Adapterklasse implementiert.
codexbox ist genau dieser Adapter, auf OpenAIs Codex-CLI gerichtet. Dieselbe Basis, dieselbe REST-Oberfläche, derselbe Telegram-Bot, derselbe Cron-Scheduler, das einzig wirklich Neue hier ist der Code, der eine generische „führ diesen Prompt aus“-Anfrage in die wahnsinnige Flag-Kombination übersetzt, die Codex an dem Tag gerade will, plus der Authentifizierungstanz um zwei völlig verschiedene Arten, dafür zu bezahlen.

Das Problem speziell mit OpenAIs CLI

Die Codex-CLI ist in Ordnung. Die Ergonomie der Codex-CLI als etwas, das man programmatisch aufruft, ist eine andere Geschichte. Ein paar Highlights daraus, das Ding tatsächlich zu lesen, statt seiner Doku zu glauben:

  • Es stürzt beim Start wegen eines Verzeichnisses ab, das nicht existiert. Setz CODEX_HOME auf einen Pfad und leg ihn nicht vorher an, und codex bricht einfach mit einem Fehler ab, statt das einzeilige mkdir -p zu machen, das buchstäblich jede andere CLI auf diesem Planeten für dich erledigt. Mehr dazu weiter unten, denn es ist das beste und zugleich schlimmste Detail im ganzen Repo.
  • Das Flag zum Umgehen der Sandbox liest sich wie eine Rechtsklausel. --dangerously-bypass-approvals-and-sandbox. Nicht --yolo, nicht -y, ein vollständiger Satz, vermutlich damit niemand behaupten kann, er habe nicht gewusst, was er tat, als sein Container losgezogen ist und irgendwas mit rm -rf plattgemacht hat.
  • Fortsetzen ist ein Unterbefehl, kein Flag. Jede andere Agenten-CLI, die ich verdrahtet habe, nimmt --continue oder --resume <id> als Flag am normalen Ausführungsbefehl. Codex zwingt dich, exec resume <id> oder exec resume --last als eigenständiges Verb aufzurufen, was heißt, dass der Adapter eine komplett andere argv-Form bauen muss, je nachdem, ob du fortsetzt oder nicht.
  • Es gibt keinen „schalte alle Tools ab“-Schalter. update_plan ist bedingungslos und apply_patch bleibt, solange eine lokale Umgebung existiert, ein echter Tool-freier Modus heißt also, die Shell- und Websuche-Tools über die Config zu entfernen und die Sandbox zur Sicherheit doppelt auf read-only zu zwingen, weil die Config allein es nicht vollständig entschärfen kann.
  • Strukturierte Ausgabe nimmt nur einen Dateipfad. Codex hat native JSON-Schema-Durchsetzung über --output-schema, was ehrlich gesagt besser ist als das, was die anderen Adapter auf dieser Basis bekommen, keine Selbstkorrektur-Retries nötig, aber es akzeptiert nur eine Datei auf der Platte, kein Inline-Schema, der Adapter muss dein Schema also bei jedem einzelnen Aufruf in eine temporäre Datei schreiben.
  • Sein eigener JSON-Stream lügt dich an, JSON zu sein. Führ codex exec --json aus und du bekommst einen JSONL-ThreadEvent-Stream auf stdout, nur dass codex auch noch Klartext-Logzeilen der Form ERROR ... direkt in denselben stdout einstreut. Du darfst nicht annehmen, dass jede Zeile parst. Du parst, du fängst den Dekodierfehler ab, du zählst ihn, du machst weiter.

Nichts davon macht Codex schlecht. Es macht Codex zu einer CLI, die für einen Menschen an einem Terminal gebaut wurde, nicht für ein Programm, das sie in einer Schleife aufruft, und genau diese Lücke existiert der Adapter, um sie zu überkleben.

Vier Umgebungsvariablen und ein mkdir

Das Dockerfile setzt exakt vier Umgebungsvariablen, um den Adapter in das Basis-Image zu verdrahten, alle in einem einzigen Block:

ENV AICODEBOX_ADAPTER=codexbox.adapter:CodexAdapter 
    AICODEBOX_AGENT_BINARY=codexbox-agent 
    CODEXBOX_IMAGE_VARIANT=minimal 
    CODEX_HOME=/home/aicode/.codex

AICODEBOX_ADAPTER richtet die Adapter-Lademaschinerie der Basis auf CodexAdapter, damit sie weiß, wie sie argv speziell für codex baut. AICODEBOX_AGENT_BINARY schiebt für den interaktiven und den Passthrough-Gebrauch ein Launcher-Skript ein, statt codex direkt aufzurufen (warum, weiter unten). CODEXBOX_IMAGE_VARIANT markiert nur, auf welchem Image du bist (minimal hier, full im Toolchain-Build). Und CODEX_HOME ist die, auf die es wirklich ankommt, wegen des erwähnten Startabsturzes.
Codex liest auth.json, config.toml und seine Session-Rollout-Dateien aus $CODEX_HOME. Ist diese Variable nicht gesetzt, fällt codex auf einen vernünftigen Default zurück. Ist sie aber gesetzt, was sie hier sein muss, weil der ganze Sinn darin besteht, sie vom Host zu bind-mounten, damit ein Login das Plattmachen und Neuerstellen eines Containers überlebt, und existiert das Verzeichnis, auf das sie zeigt, noch nicht, weigert sich codex zu starten. Keine Warnung, kein automatisches Anlegen, ein harter Fehler. Also macht das Dockerfile direkt nach dem ENV-Block das hier:

RUN mkdir -p /home/aicode/.codex && chown -R aicode:aicode /home/aicode/.codex

Ein einzelnes mkdir -p und ein chown, zur Build-Zeit ins Image gebacken, einzig damit eine CLI, geschrieben von einem Unternehmen mit hundert Milliarden Dollar auf dem Konto, nicht beim ersten Mal umfällt, wenn du sie auf einen frischen Bind-Mount richtest. Das ist ehrlich mein Lieblingsdetail im ganzen Repo, nicht weil es clever wäre, es ist das Gegenteil von clever, es ist ein Workaround für einen fehlenden mkdir-Aufruf. Aber es ist die Sorte Sache, die man nur findet, wenn man das Dockerfile tatsächlich liest, statt einer README zu glauben, und es erklärt, warum CODEX_HOME vorab angelegt wird, statt bloß deklariert und codex überlassen zu werden.

Was CodexAdapter tatsächlich implementiert

Der Adaptervertrag aus dem Basis-Image gibt dir eine Handvoll Methoden zum Ausfüllen, und CodexAdapter implementiert sie alle: validate (weist unbekannte Werte für den Denkaufwand zurück, warnt bei einer Tool-Allowlist, für die codex kein Äquivalent hat, und ignoriert sie), build_argv (das Fleisch, übersetzt eine generische Ausführungsanfrage in codex’ tatsächliche Flag-Suppe), translate_auth (tut nichts, weil codex OPENAI_API_KEY / OPENAI_BASE_URL / auth.json nativ liest, kein Aliasing nötig), parse_output und parse_events (dekodieren den JSONL-Stream in ein normalisiertes Ergebnis und überspringen die eingestreuten Nicht-JSON-Logzeilen), parse_stream_event (macht aus einzelnen Zeilen kanonische Stream-Deltas für die Live-Streaming-Endpoints), interactive_argv und passthrough_argv (roher Aufruf des codex-Binarys für TUI und Passthrough), und auth_paths (sagt dem Basis-Image, wo die Credential-Datei liegt, damit ihre Existenz geprüft werden kann).
build_argv ist der Ort, an dem die interessanten Entscheidungen wohnen. Ein Lauf, bei dem weder resume noch noContinue gesetzt ist, fällt standardmäßig auf exec resume --last zurück und setzt damit standardmäßig die jüngste Sitzung des Workspace fort, dieselbe Idee wie bei claudebox. systemPrompt bildet auf -c instructions=... ab, was codex’ eingebauten System-Prompt ersetzt; appendSystemPrompt bildet auf -c developer_instructions=... ab, was stattdessen eine Nachricht in der Developer-Rolle danebenstellt. Der Denkaufwand läuft über -c model_reasoning_effort=<level> statt über ein eigenes Thinking-Flag. Und jedes davon wird als ein einzelnes argv-Element übergeben, nicht durch eine Shell interpoliert, mehrzeiliger Prompt-Text und System-Prompts überleben also wortwörtlich, ohne irgendwo in der Pipe von einer Shell zerlegt zu werden.

Was codexbox-agent.sh wiederherstellt, das die Basis fallen lässt

aicodebox’ Passthrough-Modus ist bewusst dumm: für interaktive und einmalige Aufrufe führt er einfach exec $AICODEBOX_AGENT_BINARY "$@" aus und geht aus dem Weg. Für ein generisches Basis-Image ist das in Ordnung, aber es heißt, dass die containerseitigen Defaults, keine Freigabeabfragen, vernünftige Sitzungsfortsetzung, nicht automatisch für Codex’ eigene interaktive TUI gelten, sondern nur für die adaptergetriebenen Servermodi. codexbox-agent.sh ist das über AICODEBOX_AGENT_BINARY eingehängte Skript, das diese Defaults speziell für die TUI- und CLI-Passthrough-Pfade wieder einsetzt:

case "${1:-}" in
    login | logout | mcp | mcp-server | doctor | completion | update | resume | review | apply | sandbox | debug | features | help | -V | --version | -h | --help)
        exec "$CODEX_BIN" "$@"
        ;;
    exec | e)
        # inject --dangerously-bypass-approvals-and-sandbox unless already present
        exec "$CODEX_BIN" "$sub" "$BYPASS" "$@"
        ;;
esac
# bare interactive TUI — defaults to resuming the workspace's last session
exec "$CODEX_BIN" resume --last "$BYPASS" ${args[@]+"${args[@]}"}

Auth- und Wartungs-Unterbefehle (login, logout, mcp, doctor, update und so weiter) laufen vollständig unverändert, ohne injizierte Flags, und genau das lässt codexbox login --device-auth den ChatGPT-OAuth-Ablauf unangetastet fahren. Alles andere, eine nackte interaktive Sitzung oder ein exec-Aufruf, bekommt das Bypass-Flag automatisch injiziert, damit du nicht jedes Mal --dangerously-bypass-approvals-and-sandbox von Hand tippst, und die nackte TUI bekommt zusätzlich denselben „setz die letzte Sitzung dieses Verzeichnisses fort“-Default, den der Adapter im Servermodus benutzt. Die Servermodi (API, Telegram, Cron, MCP) fassen dieses Skript überhaupt nicht an, sie laufen über CodexAdapter.build_argv und starten codex direkt.

Doppelte Auth: API-Schlüssel oder ChatGPT-Abo, eine Datei

Codex unterstützt zwei Authentifizierungsmodi, und codexbox muss beide am Laufen halten, ohne dass sie sich gegenseitig zertrampeln. Ein Init-Skript, das einmal pro Boot läuft (10-codex-auth-config.sh), liest jede vorhandene auth.json, prüft ihr Feld auth_mode und sät nur dann über codex login --with-api-key einen API-Schlüssel ein, wenn es keine vorhandene Auth gibt oder die vorhandene bereits im apikey-Modus ist. Ein OAuth-Login per ChatGPT-Abo gewinnt immer und wird nie überschrieben, selbst wenn OPENAI_API_KEY zufällig in der Umgebung gesetzt ist. Der Grund, warum der API-Schlüssel überhaupt einen Login-Schritt braucht, statt einfach direkt aus der Umgebungsvariable gelesen zu werden: codex’ exec-Unterbefehl akzeptiert keinen nackten OPENAI_API_KEY zur Authentifizierung, er braucht zuerst eine auf die Platte geschriebene auth.json.
Beide Auth-Modi laufen auf exakt dieselbe Datei zu, was auch exakt der Grund ist, warum CODEX_HOME das Plattmachen eines Containers überleben muss. CodexAdapter.auth_paths() gibt einen einzigen Pfad zurück:

def auth_paths(self) -> list[str]:
    home = os.environ.get("HOME", "/home/aicode")
    cfg = os.environ.get("CODEX_HOME", f"{home}/.codex")
    return [f"{cfg}/auth.json"]

Bind-mounte ~/.codex vom Host, und egal wie du dich authentifiziert hast, mit einem gespeicherten API-Schlüssel oder einem ChatGPT-OAuth-Token, es überlebt jedes Neuerstellen des Containers, weil es nicht in der beschreibbaren Schicht des Containers lebt, sondern auf dem Mount, den das vorab angelegte und per chown übereignete Verzeichnis der Basis überhaupt erst sicher gemacht hat, um CODEX_HOME daraufzurichten.

Minimal gegen Full: dieselbe Auth, derselbe Adapter, mehr Toolchain

Das Standard-Image psyb0t/codexbox:latest ist codex plus Node, Python, uv, Docker, git, jq und curl, genug um den Agenten zu fahren und nicht viel mehr. Dockerfile.full baut ein zweites Image auf dem minimalen auf, per Digest auf einen bestimmten veröffentlichten Tag festgenagelt, und legt dieselbe Allzweck-Entwicklungs-Toolchain darauf, die claudeboxs volles Image mitbringt: Go mit golangci-lint, eine Python-Toolchain über pyenv, eine Node-Toolchain, installiert aus einer eingecheckten pnpm-Lockdatei mit deaktivierten Lifecycle-Skripten, GitHub CLI, Terraform, kubectl, Helm und den üblichen Haufen Build-Werkzeuge, DB-Clients und Debugger, aufgeteilt in die Abhängigkeitsverzeichnisse full-go/, full-node/ und full-python/, damit die Eingaben jeder Toolchain versionsfixiert und prüfsummenverifiziert sind statt „was apt heute gerade installieren mag“. Derselbe Codex-Adapter, derselbe Entrypoint, dasselbe Auth-Verhalten, der volle Build legt bloß Werkzeuge drumherum, und jeder Download darin wird vor dem Vertrauen gegen eine festgenagelte SHA256 prüfsummenverifiziert.

Die Host-Seite: wrapper.sh und install.sh

install.sh zieht das gewählte Image (minimal per Default, full über CODEXBOX_FULL=1), legt ~/.codex und ein SSH-Schlüsselverzeichnis für git über SSH im Container an, lädt wrapper.sh herunter, backt den aufgelösten Image-Tag hinein und installiert es als codexbox auf deinem PATH. Von da an:

export OPENAI_API_KEY=sk-...          # or: codexbox login --device-auth
codexbox                              # interactive TUI, continues last session for this dir
codexbox --no-continue                # same, but forces a fresh session
codexbox exec "fix the failing test"  # one-shot exec, output to your terminal
echo "summarize README.md" | codexbox exec -
codexbox stop                         # kill this dir's running container(s)
codexbox clear-session                # drop saved codex sessions, keep auth + config

Die Aufgabe des Wrappers ist bewusst schmal: das Image auflösen, den Workspace, das persistierte ~/.codex und den Docker-Socket mounten, die Auth und alle CODEXBOX_ENV_* / CODEXBOX_MOUNT_*-Variablen weiterreichen und einen Container pro Verzeichnis über seinen Namen verwalten. Jede tatsächliche codex-Flag-Entscheidung, Bypass-Injektion, Fortsetzen gegen frische Sitzung, Unterbefehl-Passthrough, lebt im Image in codexbox-agent.sh, nicht im Host-Skript. Der Wrapper reicht deine Argumente unangetastet weiter und lässt den Container entscheiden, was damit passiert.

Installieren, was du gerade gebaut hast, nicht was auf Docker Hub liegt

Der Installationsweg ging davon aus, dass du das veröffentlichte Image willst. Fein zum Benutzen, nutzlos zum Daranarbeiten, du würdest ein lokales Image bauen, den Installer laufen lassen, und der würde die Registry-Kopie direkt über deine Änderungen ziehen.

Also gibt es dafür jetzt Targets:

make install          # build the minimal image, then install the wrapper against it
make install-full     # same, full variant
make install-wrapper  # wrapper only, against an image you already built

Alle drei laufen über CODEXBOX_SRC_LOCAL=true, das install.sh sagt, den docker pull zu überspringen und das gewählte lokale Image zu benutzen. Es scheitert laut, wenn dieses Image nicht gebaut wurde, statt still auf Ziehen zurückzufallen, denn der ganze Sinn ist ja, nicht das veröffentlichte zu bekommen. Dieses Flag funktioniert auch eigenständig, wenn du install.sh direkt aufrufst.

make install-wrapper ist das, nach dem du wirklich immer wieder greifen wirst: Korrekturen am Host-Wrapper verlangen nicht mehr, das Image neu zu bauen, nur um eine Änderung an einem Shell-Skript zu testen.

Verwaltungsbefehle hörten auf, in deiner Sitzung zu hocken

Der Wrapper schickte früher alles durch den persistenten interaktiven Container. Für eine echte Coding-Sitzung richtig und für die Haushalts-Unterbefehle falsch, plugin, doctor, sandbox, debug, review, apply, resume, archive, delete, die jetzt jeweils einen Wegwerf-Container mit --rm bekommen.

Verwandt: jeder unterstützte Codex-Unterbefehl auf oberster Ebene wird jetzt direkt durchgereicht, statt als interaktive Fortsetzungsaufforderung behandelt zu werden. Einen echten Unterbefehl zu tippen bescherte dir früher eine Sitzung, um die du nicht gebeten hattest.

Du kannst behalten, was Codex tatsächlich gesagt hat

Standardmäßig ist die Antwort die nützliche Zusammenfassung. Setz eventMode am Lauf auf "full" und du bekommst stattdessen Codex’ eigene Aufzeichnungen unangetastet zurück: Denken, Befehlsausführung, Dateiänderungen, MCP-Aktivität, Web-Aktivität, Todo-Updates, Verbrauch. Nichts in einen Turn zusammengefaltet, nichts abgeschnitten, damit die Nutzlast ordentlich bleibt. Das zählt vor allem dann, wenn ein Lauf etwas getan hat, das du nicht erwartet hast, und die Zusammenfassung genau die Schicht ist, die die Beweise weggeworfen hat.

Drei Korrekturen, für die es sich lohnt, den Pin zu überspringen

codex update scheiterte mit EACCES. codex wurde in npms globalen Standardpräfix unter /usr installiert, was das Paket root-eigen in /usr/lib/node_modules zurücklässt, während der Container als unprivilegierter Benutzer aicode läuft. Der eigene Selbstupdater der CLI konnte also nicht in seine eigene Installation schreiben. Es installiert jetzt unter /home/aicode/.local, mit einer /home/aicode/.npmrc, die denselben Präfix über den Privilegienabstieg des Entrypoints hinweg festnagelt.
Das volle Image erbte ein Fossil. Dockerfile.full zeigte standardmäßig auf eine Basis, die zurück auf v0.2.0 gedriftet war, latest-full wurde also auf einem Image gebaut, das latest mehrere Monate hinterherhinkte. Der gestufte Workflow veröffentlicht jetzt zuerst das minimale Image, und die volle Variante erbt das aktuelle, was „dieselbe Basis, mehr Toolchain“ von Anfang an hätte heißen sollen. Diese ganze Bug-Klasse ist seit v0.5.11 weg, weil codexbox überhaupt aufgehört hat, eine driftfähige Toolchain zu besitzen: das gemeinsame Werkzeug für Go, Node, Python, Editoren, Datenbankclients und Ops ist nach oben in psyb0t/aicodebox:v0.15.0-full gewandert, und codexboxs volles Image geht jetzt bloß noch davon aus. Wobei unterwegs rund 15.800 Zeilen Lockdateien gelöscht wurden. Es ist keine zweite Kopie mehr übrig, die zurückfallen könnte.
Subagenten klauten die Unterhaltung. Codex’ Fortsetzung wird pro Workspace wiederaufgenommen, und ein neuerer Subagenten-Rollout konnte den Faden kapern, den Cron, die API, MCP oder Telegram gerade fortsetzten. Es persistiert jetzt den bestätigten exec-Faden oberster Ebene pro kanonischem Workspace und nimmt genau diese ID wieder auf, ein Subagentenlauf kann also nicht still zu dem werden, woran dein Cron-Job morgen anknüpft.

Boxen, die Boxen starten

Installier codexbox, claudebox und pibox in dasselbe Verzeichnis und jeder Wrapper mountet die anderen beiden schreibgeschützt unter /usr/local/bin/<name>. Codex kann dann mitten in der Sitzung einen anderen Agenten aufrufen, was vor allem nützlich ist, wenn du ein zweites Modell auf denselben Diff schauen lassen willst.
Verschachtelte Läufe tragen einen versionierten Host-Kontext, weil „wo ist der Workspace“ innerhalb eines Containers eine andere Antwort hat als auf der Maschine, die ihn gestartet hat: AICODEBOX_LAUNCH_CONTEXT_VERSION=1, plus AICODEBOX_HOST_HOME, AICODEBOX_HOST_WORKSPACE, AICODEBOX_HOST_WRAPPER_DIR und je Agent ein Home und ein Wrapper-Pfad, für jeden der drei. Ein verschachtelter Lauf überspringt außerdem die Auth-Dateischreibvorgänge, die ein Lauf oberster Ebene durchführt, ein Kind kann also die Zugangsdaten des Aufrufers nicht überschreiben.
AICODEBOX_ENV_* und AICODEBOX_MOUNT_* reichen Umgebung und Mounts an alle Boxen auf einmal weiter, neben den boxeigenen CODEXBOX_ENV_* und CODEXBOX_MOUNT_*. AICODEBOX_MANAGED_INSTALL=1 gibt Provisioning-Skripten eine nicht interaktive Installation, die einen vorhandenen SSH-Schlüssel nicht überschreibt, wobei CODEXBOX_INSTALL_DIR und CODEXBOX_BIN_NAME entscheiden, wo es landet und wie es heißt. Der Installer holt wrapper.sh außerdem vom passenden Release-Tag statt von master, eine festgenagelte Installation bekommt also den Wrapper genau dieser Version.

Jeder Weg in die Box

Jenseits der interaktiven Shell und des einmaligen exec gelten hier dieselben Serveroberflächen aus aicodebox, nur dass unten drunter codex läuft:

  • API-Modus: ein FastAPI-Server mit /run (synchrone oder asynchrone Agentenläufe), /files/* (auflisten, lesen, schreiben, löschen innerhalb des Workspace, mit Prüfung auf Pfad-Traversal) und einem OpenAI-kompatiblen /openai/v1/chat/completions-Endpoint. Verlangt, dass CODEXBOX_AVAILABLE_MODELS ausdrücklich gesetzt ist, denn codex hat keine fest verdrahtete Modellliste, sie ist servergesteuert, es gibt also keinen vernünftigen Default zum Zurückfallen.
  • Telegram-Modus: Text rein, codex läuft, Markdown wird zurück nach HTML gerendert. Overrides pro Chat für Modell, Denkaufwand und System-Prompts, über Neustarts hinweg persistiert.
  • Cron-Modus: croniter-getriebene geplante Jobs, die codex nach einem Zeitplan mit einer festen Anweisung abfeuern, jeder Lauf in ein Historienverzeichnis pro Job geloggt.
  • MCP-Modus: die eigene Dateioperations- und Prompt-Ausführungs-MCP-Oberfläche des Basis-Images, unter /mcp eingehängt, wenn der API-Modus an ist, sonst als Sidecar-Prozess. Das ist getrennt von codex’ eigenen MCP-Client- und Server-Fähigkeiten, die in nichts davon eingebunden sind.

Das eine, was ausdrücklich gesagt gehört: toolsAllowlist und noTools werden auf /run aus API-Kompatibilität mit den anderen Agenten auf dieser Basis akzeptiert, aber codex hat keine benannte Allowlist eingebauter Tools. Eine Allowlist wird geloggt und ignoriert. noTools ist die eine Ausnahme, die tatsächlich beachtet wird, sie entfernt die Shell- und Websuche-Tools aus der Anfrage und zwingt die Sandbox auf read-only, weil die Config allein apply_patch oder update_plan nicht entfernen kann.

Hat Es Sich Gelohnt

codexbox ist die Neufassung von gar nichts. Es ist das, was „noch einen Agenten dazu“ kosten soll, sobald die eigentliche Infrastrukturarbeit anderswo erledigt ist: ein Dockerfile, vier Umgebungsvariablen, ein mkdir -p für ein Verzeichnis, das OpenAIs eigene CLI sich nicht selbst anlegt, und eine Python-Klasse, die Codex’ spezifisches Flag-Vokabular kennt. Alles andere, die API, der Telegram-Bot, der Cron-Scheduler, die MCP-Oberfläche, der ganze Host-Wrapper, gehört aicodebox, unangetastet.
Wenn du die vollständige Begründung des Basis-Images willst, lies den aicodebox-Beitrag. Wenn du den Claude-Code-Bruder willst, das ist claudebox. Wenn du einfach eine Box willst, die Codex fährt, ohne dass OpenAIs CLI über ein fehlendes Verzeichnis auf die Fresse fällt, die liegt auf GitHub. Sie macht einen Job und sie hat aufgehört, auf die Fresse zu fallen, was alles ist, was ich je von ihr wollte.

Wie Du Es In Deinen Agenten Installierst

Codex kann das Ding installieren, das Codex fährt. Alles unter .agents/ ist in einem einzigen Marktplatz katalogisiert, es sind also zwei Befehle:

claude plugin marketplace add psyb0t/agents
claude plugin install codexbox@psyb0t

Codex benutzt denselben Marktplatz mit einem anderen Verb, codex plugin add codexbox@psyb0t, weil es kein codex plugin install gibt. Es findet den Skill in einem Checkout des Repos auch von allein, da es .agents/skills/ nativ scannt, ganz ohne dass irgendetwas installiert ist. Es ist inzwischen auch in der offiziellen MCP Registry gelistet, ein Client, der Server von dort auflöst, kann es also finden, ohne eine URL in die Hand gedrückt zu bekommen.