# Die Codex-app-server-Integration

> Wie der Desktop den Codex-Kindprozess findet, startet und überwacht: die JSON-RPC-Pipe, jede Methode, die der Desktop sendet, was einen Kindprozess am Leben hält, Profile und Anmeldung, Nutzungslimits und die Tool-Liste, die beim Start eines Threads festgelegt wird.

Handbuch / Architektur · Gegen den Quellcode geprüft am 2026-10-05 · https://www.hbcode.ai/de/docs/codex-app-server

## Ein überwachter Kindprozess

Codex läuft als Kindprozess mit dem Namen codex-app-server. Der Desktop sucht die Binärdatei im Ordner seiner eigenen ausführbaren Datei, dann unter macOS in ../Resources, dann in binaries, src-tauri/binaries und desktop/src-tauri/binaries unter dem aktuellen Verzeichnis. Er akzeptiert die Namen codex-app-server und codex-app-server-<target triple>. Die Binärdatei codex-code-mode-host muss im selben Ordner liegen. Der Desktop weicht nie auf ein Codex aus, das auf dem Rechner installiert ist. Fehlt der Sidecar, scheitert der Start mit einem Fehler, der pnpm -C desktop sync:codex-sidecars nennt.

Argumente des Kindprozess-Befehls, in der Reihenfolge, in der der Desktop sie anfügt:

```
-c features.local_thread_store_compression=false
-c features.background_paginated_rollout_migration=false
-c features.multi_agent_v2.tool_namespace="hbcode"
--listen stdio://
--session-source app-server
-c sqlite_home=<storage-profile-home>
--allowed-storage-root <storage-profile-home>
--auth-home <execution-profile-home>
```

| Was der Kindprozess sieht | Wert |
| --- | --- |
| CODEX_HOME, CODEX_SQLITE_HOME | Das Home des Speicherprofils, <app data>/codex/profiles/<uuid>/home. Geerbte Werte werden zuerst entfernt. |
| CODEX_CONFIG, CODEX_CONFIG_HOME, CODEX_DISABLE_SQLITE_LOGS | Aus der Umgebung entfernt. |
| Arbeitsverzeichnis | <app data>/codex/sidecar-cwd. |
| PATH | Beginnt mit einem Ordner, der rg enthält: dem mitgelieferten Ordner codex-path, dem Sidecar-Ordner oder einer Kopie im Cache-Ordner. HBCODE_RG_BIN nennt ein anderes rg. |
| NO_COLOR | 1. |
| RUST_LOG | warn, außer HBCODE_CODEX_APP_SERVER_RUST_LOG enthält einen anderen Filter. |
| stdin, stdout, stderr | Drei Pipes. Der Prozess wird beendet, sobald der Desktop sein Handle freigibt. |

Jedes Profil-Home hat eine stabile, undurchsichtige UUID. Der Desktop legt jeden Ordner dieses Pfads selbst an und lehnt einen Symlink in jeder Komponente ab. Der mitgelieferte Kindprozess öffnet keine Datenbank, solange --allowed-storage-root, CODEX_HOME und sqlite_home nicht kanonisch auf dasselbe Verzeichnis zeigen.

Vor jedem Start liest der Desktop die PID-Datei im Profilstamm. Die Datei heißt app-server.pid, wenn Speicherprofil und Ausführungsprofil gleich sind, und app-server-<execution profile>.pid bei einem gemischten Paar. Der Desktop beendet den eingetragenen Prozess nur, wenn er noch ein codex-app-server ist und dieser Desktop ihn nicht gestartet hat. Ein Prozess, den dieser Desktop betreibt, bekommt nie ein Signal. Danach trägt der Desktop die neue Prozess-ID ein und leert stderr in einem eigenen Task.

Der Handshake besteht aus initialize mit Client-Informationen und aktiviertem experimentalApi, danach initialized. Die Antwort auf initialize muss jede der 15 erforderlichen Protokollerweiterungen aufführen, darunter threadItem.createdAtMs, threadItem.commandOutputSource, threadItemsList.path, threadUnload und threadTurn.executionMetadata. Fehlt ein Eintrag, wird der Kindprozess als inkompatibel mit diesem Build beendet, und jeder andere Initialisierungsfehler beendet ihn ebenfalls. Diese Schranke macht eine beliebige Upstream-Binärdatei unbrauchbar.

## Die JSON-RPC-Pipe

Ein JSON-Objekt pro Zeile auf stdin und stdout:

```
{"id":42,"method":"initialize","params":{"capabilities":{"experimentalApi":true},"clientInfo":{"name":"hbcode","version":"<build-version>"}}}
```

**Der Actor hält die ersten Events eines Turns zurück, bis turn/start antwortet**

Ein einziger Actor liest alles, was der Codex-Kindprozess auf stdout schreibt, und die Zeichnung folgt einem Beispiel-Turn in der Reihenfolge, in der seine Nachrichten diese Pipe passieren. Der Kindprozess meldet turn/started und item/started, bevor er Anfrage 42 beantwortet, deshalb hält der Actor beide Events zurück. Die Antwort nennt Turn T, der Actor öffnet den Kanal dieses Turns, und die zurückgehaltenen Events landen vor dem ersten Live-Delta darin. Danach läuft ein Tool-Aufruf in einem eigenen Task, während weiter Deltas ankommen, und der Actor schreibt die Antwort des Tools zurück an den Kindprozess.

- **Antwort** (id): Wird der Anfrage zugeordnet, die auf sie wartet. Die Antwort auf turn/start trägt die Turn-ID, die den Kanal des Turns öffnet.
- **Event** (threadId · turnId): Wird in den Kanal dieses Turns geleitet. Solange ein turn/start für den Thread wartet, werden seine Events zurückgehalten, bis zu 4.096, und vor den Live-Events eingespielt.
- **Anfrage des Kindprozesses** (item/tool/call · …/requestApproval): Ein Tool-Aufruf läuft in einem eigenen Task. Er bekommt die Anfrage (tool, arguments, threadId, turnId, callId) und keinen Actor-Zustand, die Antwort schreibt der Actor. Eine Freigabe ohne aktiven Empfänger wird abgelehnt.

| Grenze von Prozess und Client | Wert |
| --- | --- |
| Start des Kindprozesses samt Handshake | 35 Sekunden. |
| Antwort auf eine Anfrage | 30 Sekunden nach dem Schreiben. Der Aufrufer gibt nach 31 Sekunden auf. Nur initialize beginnt seine 30 Sekunden jedes Mal neu, wenn der Kindprozess vor der Antwort eine Anfrage sendet. |
| stdin-Schreiben | 5 Sekunden. |
| Platz in der Befehls-Warteschlange des Actors | 5 Sekunden. Die Warteschlange fasst 256 Befehle. |
| Tool-Antworten, die auf den Actor warten | 64. |
| Nachrichten, die aufbewahrt werden, während initialize wartet | 4.096. Ein voller Puffer verwirft ein gewöhnliches Event vor einem kritischen. |
| Sauberes Herunterfahren vor dem Kill | 2 Sekunden, nachdem stdin geschlossen wurde. |
| stderr-Zeilen, die für den Fehlertext aufbewahrt werden | Die letzten 40. |

Auch der Kindprozess kann Anfragen senden. Der Desktop beantwortet zwei Arten: einen Tool-Aufruf im Namespace hbcode und die drei Freigabeanfragen. Jede andere Anfrage bekommt den JSON-RPC-Fehler -32601 mit dem Text „HB Code desktop does not handle app-server request“, und ein Tool-Aufruf für einen anderen Namespace ist eine solche Anfrage. Eine Freigabeanfrage, die eintrifft, während initialize wartet, wird abgelehnt. Eine stdout-Zeile, die nicht mit { oder [ beginnt, wird protokolliert und ignoriert. Wenn stdout schließt, enthält der Fehler das Ende von stderr.

- [Freigaben](https://www.hbcode.ai/de/docs/codex-turns.md#approvals): Wer eine Freigabeanfrage beantwortet, die Frist von 30 Sekunden und der Weg über das Telefon.
- [Fehlschlag eines Turns](https://www.hbcode.ai/de/docs/codex-turns.md#failure): Die Fristen eines Turns: Unterbrechung, Abschluss nach einem Fehler und das Nachlesen nach dem Ende.

## Jede Methode, die der Desktop sendet

Der Codex-Client ist ein fester Satz von 27 Methoden. Der Desktop sendet keine andere Methode an den Kindprozess.

| Methode | Wann der Desktop sie sendet |
| --- | --- |
| initialize, initialized | Einmal, direkt nach dem Start des Kindprozesses. |
| thread/start | Erster Turn einer neuen Session, eine One-Shot-Textanfrage und ein privater Worker. Enthält dynamicTools, developerInstructions und die Zugriffsstufe. |
| thread/read | Direkt nach thread/start, um den absoluten Rollout-Pfad zu erfahren. Außerdem, um den Eltern-Thread eines Threads zu lesen, bis zu 16 Ebenen weit, wenn der Desktop den Wurzel-Thread sucht. |
| thread/resume | Vor einem Turn auf einem bekannten Thread, mit dem exakten Pfad und den Verlaufsquellen. Dient auch dazu, sich an einen laufenden Turn anzuhängen, und geht einem Rollback voraus. |
| thread/source/read | Um einen Thread aus einem exakten JSONL-Pfad zu lesen. |
| thread/items/list | Jede Verlaufsseite der Timeline. |
| thread/turns/list | Vor einem Rollback, limit 1, um den letzten Turn zu finden. |
| thread/revert | Rollback des letzten Turns, mit beforeTurnId. Ein Turn mit dem Status inProgress lehnt ihn ab. |
| thread/list | Bestehende Sessions (sourceKinds appServer, cli, vscode, standardmäßig 25 pro Seite, höchstens 100) und die Subagent-Threads unter einem Thread (ancestorThreadId). |
| thread/unload | Nach einem Run, nach einer One-Shot-Anfrage und bevor ein anderer Kindprozess denselben Thread öffnet. |
| thread/settings/update | Eine Änderung von Modell, Aufwand oder Zugriffsstufe, während ein Turn läuft. Ohne laufenden Turn sendet der Desktop nichts, und die gespeicherten Einstellungen gelten ab dem nächsten Turn. |
| thread/commandOutput/read | Ein Ausschnitt gespeicherter Befehlsausgabe. |
| thread/goal/get, thread/goal/set, thread/goal/clear | Ziele lesen und ändern. |
| turn/start | Jeder neue Turn. |
| turn/steer | Eine Nachricht für den laufenden Turn. |
| turn/detachPendingInputForReplay | „Stop and send now“ holt eine wartende Nachricht zurück. |
| turn/interrupt | Stop. |
| model/list | Der Modellkatalog, mit includeHidden false. |
| account/read, account/sessions/list | Kontoidentität nach einer Anmeldung und für die Abonnement-Auswahl. |
| account/rateLimits/read | Nutzungslimits. |
| account/usage/read | Token-Aktivität für den Nutzungsverlauf. |
| account/login/start, account/login/cancel | Anmeldung im Browser. |

- [Ein Turn von Anfang bis Ende](https://www.hbcode.ai/de/docs/codex-turns.md#turn-lifecycle): turn/start, turn/steer und die Events eines Turns.
- [Ziele](https://www.hbcode.ai/de/docs/codex-turns.md#goals): Wie die Ziel-Methoden aus vielen Turns einen Run machen.
- [Stop](https://www.hbcode.ai/de/docs/codex-turns.md#stop): Die Reihenfolge von Ziel-Pause, turn/interrupt und dem Ausweichweg.
- [Verlaufsseiten](https://www.hbcode.ai/de/docs/timeline.md): Wie Seiten von thread/items/list zu Timeline-Zeilen werden.

## Der Tool-Namespace hbcode

thread/start enthält dynamicTools, die einen Namespace namens hbcode neben die Shell- und Datei-Tools stellen, die Codex schon hat. Der Kindprozess wird mit features.multi_agent_v2.tool_namespace auf demselben Namen gestartet, deshalb teilen Codex’ eigene Multi-Agent-Tools ihn. Die Liste enthält 4 bis 8 Tools und folgt den Einstellungen in diesem Moment.

| Tool | In der Liste, und seine Freigabeklasse |
| --- | --- |
| use_user_browser | Immer. Klasse agent: Der Agent fragt seinen Nutzer. |
| maintain_sessions | Immer. Klasse read-only: Niemand gibt frei. |
| manage_sessions | Immer. Klasse agent: Der Agent fragt seinen Nutzer. |
| send_session_message | Immer. Klasse desktop: Der Desktop wendet seine eigene Regel an. |
| send_mobile_notification | Wenn die Einstellung „Desktop- und Telefon-Benachrichtigungen“ eingeschaltet ist. Klasse agent: Der Agent fragt seinen Nutzer. |
| synthesize_speech | Wenn ein Gemini-API-Schlüssel gespeichert ist. Klasse agent: Der Agent fragt seinen Nutzer. |
| create_explainer_video | Wenn ein Gemini-API-Schlüssel gespeichert ist. Klasse agent: Der Agent fragt seinen Nutzer. |
| extract_video_context | Wenn ein Gemini-API-Schlüssel gespeichert ist. Klasse agent: Der Agent fragt seinen Nutzer. |

thread/start enthält außerdem developerInstructions. agents/session_rules.rs fügt dafür drei Texte in dieser Reihenfolge zusammen: den App-Tool-Text des Katalogs, die Regel für Anweisungen und den Text des Antwortstils. Der Stil Default fügt keinen Text hinzu. Ein normales Senden und ein Ziel-Run verwenden dieselben Anweisungen. Codex liest sie, wenn ein Thread startet. thread/resume sendet sie erneut, und Codex verwendet sie nur, wenn eine Komprimierung den Kontext des fortgesetzten Threads neu aufbaut. Eine Änderung des Antwortstils erreicht daher neue Sessions und eine ältere Session erst nach einer Komprimierung.

Die Freigabeklasse sagt, wer einen Aufruf freigibt, wenn ein Agent seinen Nutzer vor Tool-Aufrufen fragt. Codex führt diese Tools ohne Freigabeanfrage aus. Für Codex wirkt deshalb nur die Klasse desktop: Eine Session-Nachricht, die den Nutzer braucht, wartet in der Warteschlange des Empfängers.

> **Die Liste steht mit thread/start fest** thread/resume hat kein Feld für Tools. Codex behält die Liste, solange der Thread existiert, und ein Resume sendet nur die Anweisungen. Eine Einstellungsänderung oder ein neuer Gemini-Schlüssel erreicht nur neue Threads.

Jede Spezifikation ist mit deferLoading markiert und enthält keine Session-, Run- oder Projektwerte. Der App-Tool-Text ist die Namespace-Beschreibung, die die Tool-Gruppen nennt, und danach „Find the hbcode tool for the task. Follow its instructions. For a video, give a brief. Its tool runs a worker.“ Die Namespace-Beschreibung und der App-Tool-Text bleiben zusammen unter 600 Zeichen. Für jeden item/tool/call schlägt der Desktop den Session-Link des aufrufenden Threads und den aktiven Run dieser Session nach. So erreicht ein fortgesetzter Thread oder ein abgezweigter Subagent den laufenden Run. Ein Aufruf mit einem Tool-Namen, den der Desktop nicht kennt, bekommt ein Ergebnis mit success: false und dem Text „Unsupported HB Code app tool.“ Die JSON-RPC-Antwort selbst ist ein normales Ergebnis.

create_explainer_video startet einen privaten Worker-Thread mit dem Namensraum explainer_video und den Tools save_scenes, render_stills und finish_explainer_video. Der Desktop leitet jeden Aufruf an den Job dieses Threads weiter. Aufrufe in anderen Namensräumen werden abgelehnt. Alle 250 Millisekunden prüft der Desktop, ob der übergeordnete Run noch aktiv ist. Andernfalls stoppt er den Worker, unterbricht den Turn und entlädt den Thread.

- [Dokumente, Sprache, Video, Benachrichtigungen, Session-Suche](https://www.hbcode.ai/de/docs/tools/agent-tools.md): Die Mechanik jedes Tools, seine Grenzen und wohin seine Daten gehen.
- [Zugriffsstufen](https://www.hbcode.ai/de/docs/agents.md#access-levels): Wie eine Zugriffsstufe auf Codex-Berechtigungen und die Freigaberichtlinie abgebildet wird.
- [Dieselben Tools für Claude](https://www.hbcode.ai/de/docs/claude-agent-sdk.md#app-tools): Wo die Freigabeklasse entscheidet, wer gefragt wird.
- [Antwortstil und Anweisungen](https://www.hbcode.ai/de/docs/tools/agent-tools.md#reply-style): Der Text der Regel für Anweisungen und was jeder Antwortstil hinzufügt.

## Clients pro Profilpaar

**Ein Kontowechsel schickt den nächsten Turn an einen anderen Kindprozess mit demselben Speicher**

Zeilen sind Speicherprofile, in denen das Transkript einer Session liegt. Spalten sind angemeldete Konten, und jede Zelle ist ein Codex-Kindprozess. Session A bleibt in Zeile S1, deshalb läuft ihr nächster Turn nach dem Wechsel zu P2 im Kindprozess (S1, P2), während der Kindprozess (S1, P1) mit entladenem Thread untätig ist. Der laufende Turn von Session B behält P1 bis zu seinem Ende, und ihr nächster Turn startet den Kindprozess (S2, P2).

- **Speicherprofil** (CODEX_HOME · sqlite_home): Ein HB-Code-eigenes Codex-Home, benannt nach einer opaken UUID. Eine neue Session wird mit dem Home des Kontos verknüpft, das bei ihrem ersten Turn aktiv ist, und ein Wechsel kopiert, verschiebt oder verknüpft das Transkript nie neu.
- **Konto** (--auth-home): Das angemeldete ChatGPT-Profil, Ausführungsprofil genannt, das bei der Zulassung eines Turns aktiv ist. Der Turn behält es bis zu seinem Ende.
- **Codex-Kindprozess** (CodexRuntimePair): Einer pro Paar aus Speicher und Konto, bei Bedarf gestartet. Bevor ein Kindprozess einen Thread fortsetzt, entlädt jeder andere seine untätige Kopie, daher wandert ein laufender Turn nie.

Der Quellenlink speichert eine Thread-ID und den exakten Rollout-Pfad. thread/start liefert nur die ID, deshalb liest der Desktop den absoluten Pfad mit einem separaten thread/read, bevor er den Link veröffentlicht und bevor turn/start folgt. Der Pfad eines Subagent-Threads kommt mit dessen thread/started-Benachrichtigung. Ein Wechsel der Zugangsdaten ändert nie die Unterhaltungsquelle.

**Ein Codex-Kindprozess stoppt erst, wenn ihn keine Lease, kein Subagent-Thread und keine Anmeldung mehr hält**

Ein Kindprozess des Paars (S1, P1) vom Start bis zum Stop, nicht maßstäblich. Eine Lease deckt den Start, Run 1 und ein späteres Lesen des Verlaufs ab. Ein Subagent-Thread, den Run 1 gestartet hat, bleibt nach dem Ende des Runs aktiv, der Kindprozess bleibt also beschäftigt. Die Registry prüft die Obergrenze von 3 jedes Mal, wenn eine Lease genommen wird. Die erste Prüfung findet diesen Kindprozess beschäftigt und lässt ihn in Ruhe. Die zweite Prüfung findet ihn untätig und am längsten unbenutzt, markiert ihn als auslaufend und stoppt ihn. Ein Probe-Kindprozess für ein anderes Profil wird schon beim Start als auslaufend registriert, liest das Konto und stoppt.

- **Lease** (CodexAppServerLease): Jeder Run, jedes Lesen des Verlaufs und jeder Tool-Worker nimmt eine: eine Server-Lease und eine Home-Lease für das Paar. Ein Start und eine Probe nehmen nur eine Home-Lease. Jede endet mit ihrer Arbeit.
- **Subagent-Thread** (thread/started · parentThreadId): Hält den Kindprozess, nachdem der Root-Run geendet hat. Er lässt los bei thread/status/changed idle, bei turn/completed oder 5 Sekunden nach einem Fehler ohne Wiederholung.
- **Prüfung der Obergrenze** (MAX_LIVE_APP_SERVERS = 3): Läuft, nachdem eine Lease genommen wurde. Bei mehr als 3 verfügbaren Kindprozessen stoppt sie den am längsten unbenutzten untätigen. Sind alle beschäftigt, wächst die Registry.
- **Probe-Kindprozess** (account/read · account/rateLimits/read): Die Abonnement-Auswahl liest ein Profil ohne Kindprozess über einen Wegwerfprozess. Er lässt keinen Turn zu und wird nach dem Lesen gestoppt.

Jedes Paar hat seine eigene Startsperre, deshalb wartet ein Paar nie auf den Start eines anderen. Ein zweiter Start für ein Paar, das noch startet, scheitert mit „This Codex subscription is still starting.“ Ein Kindprozess, der außer Dienst geht, schließt seine Schranke für die Turn-Zulassung, und ein turn/start, das auf ihm vorbereitet wurde, scheitert vor der Zulassung.

Nach jedem Chat-Run entlädt der Desktop den Thread mit thread/unload. Ein fehlgeschlagenes Entladen oder ein Subagent-Pfad, der nicht gespeichert werden konnte, nimmt diesen Kindprozess außer Dienst, denn die Prozessgrenze ist der einzige Beweis, dass der JSONL-Writer fort ist. Auch ein Ziel-Run entlädt seinen Thread, dort wird ein fehlgeschlagenes Entladen aber nur protokolliert. Bevor sich der Quellenlink eines Threads ändert, wird außerdem jede untätige Kopie auf jedem laufenden Kindprozess entladen.

- [Verbindungsverlust](https://www.hbcode.ai/de/docs/codex-turns.md#recovery): Was ein laufender Turn tut, wenn sein Kindprozess stirbt.
- [Speicher- und Ausführungsprofile](https://www.hbcode.ai/de/docs/storage.md#profiles): Welches Profil ein Transkript besitzt und welches für einen Turn bezahlt.

## Profile und Anmeldung

**Eine Anmeldung hält den Kindprozess eines Profils bis zu 10 min 30 s, während andere Profile weiterlaufen**

Eine Browser-Anmeldung für Profil Q, nicht maßstäblich. Der Desktop startet den Kindprozess von Q und sendet account/login/start. Die Antwort enthält loginId und authUrl, und der Desktop öffnet authUrl im Browser. Danach wartet der Desktop höchstens 10 Minuten 30 Sekunden auf account/login/completed mit derselben loginId. Er liest account/read und account/sessions/list, speichert das Profil als authenticated und meldet codex-login-settled. Wenn der Versuch endet, steigt die Auth-Generation von Q um eins, und der Anmelde-Kindprozess geht außer Dienst, sobald er untätig ist. Die Kindprozesse anderer Profile führen während des ganzen Versuchs Turns aus.

- **Profil** (signed_out → authenticated): Eine Anmeldung verwendet ein Profil mit dem Status signed_out wieder, das nicht aktiv ist. Gibt es keines, legt sie ein Profil mit einer neuen UUID und eigenem Home an.
- **Anmelde-Kindprozess** (account/login/start · type chatgpt): Eine Lease hält ihn für den ganzen Versuch. Der Versuch wird abgelehnt, solange Profil Q einen Turn, eine Home-Lease oder eine andere Anmeldung hat.
- **Ergebnis** (account/login/completed · loginId): Zugeordnet über loginId. Der Desktop behält nur E-Mail, Tarif, Nutzer-ID, Anzeigename und Workspace-Felder. Er speichert nie Tokens, Login-IDs oder Browser-URLs.
- **Auth-Generation** (pro Ausführungsprofil): Steigt nach jedem beendeten Versuch: Erfolg, Fehlschlag, Timeout oder Abbruch. Ein Kindprozess mit einer älteren Generation wird für einen neuen Turn nicht wiederverwendet.

| Regel | Detail |
| --- | --- |
| Aktives Profil | Die Einstellung agent.chat.codex_profile_id. Ein Wechsel schreibt diese Einstellung und meldet die Änderung. Er stoppt keinen Kindprozess, und ein laufender Turn behält sein Paar. |
| Senden | Braucht ein aktives Profil mit dem Status authenticated. |
| Verlauf lesen | Braucht keine Anmeldung. Ein verknüpftes Transkript wird über ein beliebiges lokales Profil gelesen. |
| Profil löschen | Erlaubt, wenn das Profil nicht aktiv ist, keinen Session-Link besitzt und kein verknüpftes Transkript in seinem Ordner liegt. Die Registry lehnt außerdem ab, solange das Profil einen Turn, eine Lease, einen Subagent-Thread oder eine Anmeldung hat. |
| Was ein Löschen stoppt | Nur die Kindprozesse dieses Profils. Es sperrt jede neue Lease, bis der Ordner fort ist, und entfernt dann die Zeile und den Ordner. |

Ein Telefon liest die Codex-Profile mit system.codexAuthProfiles und wechselt mit system.activateCodexAuthProfile. Der Wechsel ist eine ändernde Methode und braucht deshalb einen Idempotenzschlüssel. Die Antwort ist die neue Profilliste.

- [Agent-Konten auf der Relay-Seite](https://www.hbcode.ai/de/docs/accounts-and-auth.md#agent-accounts): Wie ein Telefon die Konten beider Agenten auflistet und wechselt.
- [Claude-Konten](https://www.hbcode.ai/de/docs/claude-agent-sdk.md#accounts): Dieselbe Aufgabe für den anderen Agenten, mit Ordnern statt Profilen.

## Nutzungslimits

Die Codex-Limits kommen von account/rateLimits/read auf dem Kindprozess des aktiven Profils. Der Desktop liest rateLimitsByLimitId.codex oder rateLimits, wenn dieser Eintrag fehlt. Er behält das primäre und das sekundäre Fenster (usedPercent, Fensterminuten, resetsAt), das Guthaben und den Tarif. Ein Telefon bekommt dieselben Werte mit system.codexUsageLimits.

| Lesen | Cache und Grenze |
| --- | --- |
| Limits des aktiven Profils | 60 Sekunden, ein Wert für den ganzen Desktop. Der Cache hat keinen Profilschlüssel, und ein Profilwechsel leert ihn nicht. Nach einem Wechsel können deshalb bis zu 60 Sekunden lang die Limits des alten Profils erscheinen. |
| Abonnement-Auswahl | 60 Sekunden pro Profil, nur für angemeldete Profile. Die Profile werden nacheinander gelesen, jedes mit einer Obergrenze von 45 Sekunden. Ein fehlgeschlagenes Lesen wird nicht zwischengespeichert, und eine Aktualisierung leert den Cache. |
| Auswahl liest ein Profil ohne Kindprozess | Startet einen Probe-Kindprozess, der keinen Turn zulässt und nach dem Lesen stoppt. |

- [Limits beider Agenten](https://www.hbcode.ai/de/docs/agents.md#limits): Was der Desktop und die Telefone für Codex und für Claude zeigen.

## Anfragen außerhalb eines Runs

Session-Titel und Textverbesserung nutzen eine One-Shot-Textanfrage. Der Desktop startet einen flüchtigen Thread ohne Tools, mit permissions :read-only und der Freigaberichtlinie never. Er startet einen Turn, wartet höchstens 120 Sekunden auf den Text und entlädt den Thread. Nach einem Timeout oder einem Fehler gibt er zuerst den Turn auf. Eine leere Antwort ist ein Fehler.

Der Modellkatalog kommt von model/list mit includeHidden false. Der Desktop speichert ihn 300 Sekunden pro Speicherprofil zwischen und leert den Cache, wenn ein Profil gelöscht wird. Ein Senden liest den Katalog und prüft das gewählte Modell und den Aufwand dagegen, bevor der Turn zugelassen wird.

Die Liste bestehender Codex-Sessions kommt von thread/list auf dem Kindprozess des aktiven Profils. Der Desktop öffnet dafür nie die Codex-State-Datenbank und durchsucht nie Rollout-Dateien.

- [Zulassung](https://www.hbcode.ai/de/docs/message-delivery.md#admission): Was ein Senden prüft, bevor es als zugestellt gilt.

## Der mitgelieferte Sidecar

**Ein Build läuft nur, solange die akzeptierte Revision dem zuletzt geholten main entspricht**

Drei Werte ändern sich zu verschiedenen Zeitpunkten. Das offizielle main wandert von A über B zu C. Der lokale Snapshot wechselt erst zu B, wenn reconcile:codex-source ihn holt, und die akzeptierte Revision wechselt erst zu B, wenn accept:codex-source läuft. Jeder Lauf von sync:codex-sidecars vergleicht nur den Snapshot mit der akzeptierten Revision. Er baut also noch, nachdem sich das offizielle main bewegt hat, stoppt, sobald der Snapshot neuer ist, und baut nach der Akzeptanz wieder. tauri:dev führt diesen Sync zuerst aus.

- **Geholtes main** (refs/remotes/origin/main): Wird nur von reconcile:codex-source in den lokalen Spiegel geschrieben. Der Sync vergleicht mit diesem Snapshot, daher ändert ein neuerer Commit auf dem offiziellen main nichts bis zum nächsten Reconcile.
- **Akzeptierte Revision** (vendor/codex/upstream-revision): Ändert sich nur durch accept:codex-source, sobald der abgeglichene Kandidat dem geholten main entspricht, keine Konflikte hat und seine Tests besteht. Die vollständigen Override-Dateien wechseln mit ihr.
- **Sync** (sync:codex-sidecars): Stoppt vor dem Bauen, wenn die akzeptierte Revision nicht dem geholten main entspricht. Sonst checkt er diese Revision aus, kopiert die Overrides darüber, baut mit --locked und prüft das Manifest.

tauri:dev führt zuerst sync:codex-sidecars aus, der Kindprozess wird also aus dem eingebetteten Quellcode gebaut. Rechnen Sie mit einem Rust-Build und dem Netzwerkzugriff, den desktop/BUILD.md beschreibt.

Der Sync ist eine Aktualitätsschranke. Er scheitert, wenn desktop/vendor/codex/upstream-revision nicht dem main entspricht, den das letzte reconcile:codex-source in den lokalen Spiegel geholt hat. Die akzeptierte Revision ist damit so aktuell wie dieser Abruf. Die 309 Override-Dateien unter desktop/vendor/codex/source implementieren die Protokollerweiterungen und die Speichergrenze, auf die sich der Desktop verlässt. Deshalb scheitert eine fremde Upstream-Binärdatei an der initialize-Schranke. Behalten Sie den Protokolltransport als Verlaufsgrenze bei und fügen Sie keinen weiteren Transkript-Parser hinzu.

Einen bereits vorbereiteten Sidecar untersuchen, ohne die App zu starten:

```
pnpm -C desktop sync:codex-sidecars:verify
```
