Official

codex

Codex agent provider: runs the Codex CLI's app-server for each account.

The app opens the listing; nothing installs until an agent in your Plugins workspace has read the files and you enable the plugin. In a terminal: cvg install convergence/codex@0.2.0

Permissions in 0.2.0

  • Provide agents agents.provideMediumAdds agents to the app.Provide the Codex agent and pass its tool calls to plugin tools
  • Run named programs processMediumStarts the listed programs.Run the Codex CLI, and ask or tell the installer that owns it (npm or Homebrew) about a newer versionPrograms: codexnpmbrew
  • Environment variables envMediumReads the listed environment variables.Find each account's Codex home, and pass extra app-server arguments set in CODEX_ARGSVariables: HOMECODEX_HOMECODEX_ARGS
  • Read files fs.readMediumReads files in the listed places.Read, once, the accounts the previous Codex provider keptPlaces: its own data folder

Files

wire.ts7.7 KB
// The app-server fields this provider consumes. Optional fields preserve
// Codex's lenient defaults and unknown item types remain forward compatible.
import * as z from "zod";

const text = z.string().nullish();
const number = z.number().nullish();
export const action = z.looseObject({ type: text, path: text, command: text });
export const change = z.looseObject({ path: text, diff: text, kind: z.looseObject({ type: text }).nullish() });
export const input = z.looseObject({ type: text, text: text, path: text });
const collabState = z.object({ status: text, message: text });
export const item = z.looseObject({
  type: text,
  id: text,
  clientId: text,
  text: text,
  delivery: text,
  command: text,
  cwd: text,
  status: text,
  aggregatedOutput: text,
  exitCode: number,
  commandActions: z.array(action).nullish(),
  changes: z.array(change).nullish(),
  server: text,
  tool: text,
  error: z.unknown().optional(),
  result: z.unknown().optional(),
  arguments: z.unknown().optional(),
  success: z.boolean().nullish(),
  contentItems: z.array(z.object({ type: text, text: text, imageUrl: text })).nullish(),
  query: text,
  path: text,
  summary: z.array(z.unknown()).nullish(),
  content: z.array(z.unknown()).nullish(),
  senderThreadId: text,
  receiverThreadIds: z.array(z.unknown()).nullish(),
  prompt: text,
  model: text,
  reasoningEffort: text,
  agentsStates: z.record(z.string(), collabState).nullish(),
  kind: text,
  agentThreadId: text,
  agentPath: text,
  questions: z.array(z.object({ title: text, options: z.array(z.unknown()).nullish() })).nullish(),
});
export const turnError = z.object({ message: text, codexErrorInfo: z.unknown().optional(), additionalDetails: text });
export const turn = z.looseObject({
  id: text,
  status: text,
  startedAt: number,
  completedAt: number,
  error: turnError.nullish(),
  items: z.array(item).nullish(),
});
const spawn = z.looseObject({ parent_thread_id: text, agent_nickname: text, agent_role: text, agent_path: text });
const subagent = z.object({ thread_spawn: spawn.nullish() });
export const thread = z.looseObject({
  id: text,
  name: text,
  preview: text,
  parentThreadId: text,
  agentNickname: text,
  agentRole: text,
  model: text,
  reasoningEffort: text,
  createdAt: number,
  updatedAt: number,
  historyMode: text,
  source: z
    .union([
      z.string(),
      z.object({
        subAgent: z.union([z.string(), subagent]).nullish(),
        subagent: z.union([z.string(), subagent]).nullish(),
      }),
    ])
    .nullish(),
  turns: z.array(turn).nullish(),
});
export const model = z.looseObject({
  id: z.string(),
  hidden: z.boolean().optional(),
  isDefault: z.boolean().optional(),
  displayName: text,
  description: text,
  modelSpecialty: text,
  defaultReasoningEffort: text,
  defaultServiceTier: text,
  supportedReasoningEfforts: z.array(z.object({ reasoningEffort: z.string(), description: text })).nullish(),
  serviceTiers: z.array(z.object({ id: z.string(), name: text, description: text })).nullish(),
});
export const config = z.looseObject({
  model: text,
  model_reasoning_effort: text,
  approval_policy: text,
  sandbox_mode: text,
});
const window = z.object({ windowDurationMins: number, usedPercent: number, resetsAt: number });
const limitSnapshot = z.object({
  limitId: text,
  rateLimitReachedType: text,
  limitName: text,
  primary: window.nullish(),
  secondary: window.nullish(),
  spendControlReached: z.boolean().nullish(),
  individualLimit: z.object({ resetsAt: number }).nullish(),
});
export const limits = z.object({
  ordinaryUsageAllowed: z.boolean().nullish(),
  accountId: text,
  rateLimits: limitSnapshot.nullish(),
  rateLimitsByLimitId: z.record(z.string(), limitSnapshot).nullish(),
  rateLimitResetCredits: z.object({ availableCount: number }).nullish(),
});
export const status = z.object({ type: text, activeFlags: z.array(z.unknown()).nullish() });
export const property = z.looseObject({
  type: text,
  title: text,
  description: text,
  oneOf: z.array(z.object({ const: z.unknown().optional(), title: text, description: text })).nullish(),
  enum: z.array(z.unknown()).nullish(),
  enumNames: z.array(z.unknown()).nullish(),
});
export const elicitation = z.object({
  properties: z.record(z.string(), property.extend({ items: property.nullish() })).nullish(),
  required: z.array(z.unknown()).nullish(),
});
export const requestQuestion = z.object({
  id: z.unknown().optional(),
  header: text,
  question: text,
  isOther: z.boolean().nullish(),
  options: z.array(z.object({ label: text, description: text })).nullish(),
});
export const notification = z.looseObject({
  threadId: text,
  turnId: text,
  itemId: text,
  delta: text,
  item: item.nullish(),
  turn: turn.nullish(),
  thread: thread.nullish(),
  changes: z.array(change).nullish(),
  plan: z.array(z.object({ step: text, status: text })).nullish(),
  tokenUsage: z
    .object({
      total: z.object({ totalTokens: number }).nullish(),
      last: z.object({ totalTokens: number }).nullish(),
      modelContextWindow: number,
    })
    .nullish(),
  status: status.nullish(),
  threadName: text,
  error: turnError.nullish(),
  willRetry: z.boolean().nullish(),
  message: text,
  fromModel: text,
  toModel: text,
  requestId: z.unknown().optional(),
  rateLimits: limits.shape.rateLimits,
  thread_id: text,
  tool: text,
  arguments: z.unknown().optional(),
  callId: text,
  command: text,
  cwd: text,
  commandActions: z.array(action).nullish(),
  reason: text,
  grantRoot: text,
  mode: text,
  url: text,
  _meta: z
    .object({ codex_approval_kind: text, persist: z.union([z.string(), z.array(z.string())]).nullish() })
    .nullish(),
  requestedSchema: elicitation.nullish(),
  questions: z.array(requestQuestion).nullish(),
});
const responseSchemas = {
  initialize: z.object({ userAgent: text }),
  "thread/read": z.object({ thread: thread.nullish() }),
  "thread/start": z.object({ thread: thread.nullish() }),
  "thread/resume": z.unknown(),
  "thread/fork": z.object({ thread: thread.nullish() }),
  "thread/list": z.object({ data: z.array(thread).nullish() }),
  "thread/turns/list": z.object({ data: z.array(turn).nullish(), nextCursor: text }),
  "model/list": z.object({ data: z.array(model).nullish(), nextCursor: text }),
  "config/read": z.object({ config: config.nullish() }),
  "account/rateLimits/read": limits,
  "account/read": z.object({
    account: z.unknown().optional(),
    requiresOpenaiAuth: z.boolean().optional(),
    workspaceRouting: z.object({ chatgptAccountId: z.string() }).nullish(),
  }),
  "skills/list": z.object({
    data: z
      .array(
        z.object({
          skills: z
            .array(
              z.object({
                name: text,
                path: text,
                enabled: z.boolean().nullish(),
                shortDescription: text,
                description: text,
                scope: text,
              }),
            )
            .nullish(),
        }),
      )
      .nullish(),
  }),
  "turn/start": z.object({ turn: turn.nullish() }),
  "turn/steer": z.object({ turnId: z.string() }),
  "turn/interrupt": z.unknown(),
  "thread/unsubscribe": z.unknown(),
  "thread/revert": z.unknown(),
  "thread/compact/start": z.unknown(),
  "account/logout": z.unknown(),
  "account/login/start": z.object({ authUrl: text, verificationUrl: text }),
};
export type Item = z.infer<typeof item>;
export type Thread = z.infer<typeof thread>;
export type Turn = z.infer<typeof turn>;
export type Model = z.infer<typeof model>;
export type Config = z.infer<typeof config>;
export type Notification = z.infer<typeof notification>;
export type Elicitation = z.infer<typeof elicitation>;

export const responses: { [M in keyof typeof responseSchemas]: z.ZodType<z.infer<(typeof responseSchemas)[M]>> } =
  responseSchemas;

Versions

VersionPublishedPlugin APISizePermissionsStatus
0.2.0latestOct 5, 2026>=2 <378.1 KB4 permissionsListed

Reviews and comments

0 threads · 0 reviews

No comments yet.