Codex agent provider
The official Codex extension is a TypeScript agent provider. It observes a running Codex CLI process and its JSONL rollout journal; it never starts Codex or reads an unrelated local home.
What it demonstrates
- A manifest with
agent-observationand a singleagentProviderscontribution. - Foreground-process matching by executable name.
- Binding a session only to a writable rollout owned by that terminal’s process tree.
- Watching the root journal, discovering Codex child journals, and mapping records into agent events.
Package shape
terminay-agent-codex/
├── package.json
├── src/
│ ├── constants.ts
│ ├── index.ts
│ └── provider.ts
├── fixtures/v0.1/basic.jsonl
└── test/ src/index.ts activates the extension. src/provider.ts contains the
process and file observation logic; fixtures and tests keep the journal mapping compatible.
Register the provider
import { defineExtension } from "@terminay/extension-api";
import { PROVIDER_ID } from "./constants.js";
import { codexAgentProvider } from "./provider.js";
export default defineExtension({
activate(context) {
context.subscriptions.add(
context.agents.registerProvider(PROVIDER_ID, codexAgentProvider),
);
},
});
The contribution ID in the package manifest is the same PROVIDER_ID passed to
registerProvider(). Adding the registration to subscriptions disposes it when
the extension is deactivated.
Observe and bind safely
export const codexAgentProvider = defineAgentProvider({
mappingVersion: MAPPING_VERSION,
matchesForeground(process) {
return isCodexForeground(process.executableName);
},
async observe(terminal) {
if (!terminal.capabilities.has("process-observation")
|| !terminal.capabilities.has("filesystem-observation")
|| !terminal.capabilities.has("agent-journal")) {
return { state: "unavailable", reason: "environment-capability-missing" };
}
const rollout = await findProcessBoundRootRollout(terminal);
if (!rollout) return { state: "not-bound" };
const binding = await terminal.bindSession({
providerSessionId: rollout.sessionId,
mappingVersion: MAPPING_VERSION,
journal: rollout.journal,
fingerprint: { kind: "writable-file-below-terminal-process", file: rollout.sourceFile },
});
return jsonlSession({
binding,
source: new CodexSessionWatcher({ terminal, rollout: rollout.journal, sessionId: rollout.sessionId }),
mapRecord(record, context) {
mapCodexRecord(record, context);
},
});
},
});The full source also enriches the root session title from Codex’s session index and admits child journals only when their native parent ID matches the already-bound root session.
Build the shipped package
cd extensions/agent-codex
npm install
npm run compile
npm pack
# Upload terminay-agent-codex-0.1.0.tgz in Settings → Extensions
The package requires Node 24 or newer and declares @terminay/extension-api ^1.2.0. See the agent-provider API
for the complete contract.