🚀 Socket Launch Week Day 4:Socket MCP Adds Org Alerts, Threat Feed Review, and Package Inspection.Learn more
Sign In

@howells/envelope

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@howells/envelope

Strict Zod IO wrapper around local CLI LLMs (Claude Code, Codex, Gemini), plus an AI SDK adapter.

latest
Source
npmnpm
Version
0.3.0
Version published
Weekly downloads
21
-72.73%
Maintainers
1
Weekly downloads
 
Created
Source

envelope

Thin wrapper around the claude (Claude Code), codex (Codex CLI), and gemini (Gemini CLI) for strict Zod-validated input/output.

This is designed for local Node apps where you want "model calls" to look like a normal API:

  • validate inputs with Zod
  • request structured JSON output via --json-schema / --output-schema
  • validate outputs with Zod again (defense in depth)

Install

npm install @howells/envelope

Requirements

  • Node 20+
  • claude CLI installed and authenticated (Claude Code), or
  • codex CLI installed and authenticated (Codex), or
  • gemini CLI installed and authenticated (Gemini CLI)

Claude Code Options

createClaudeCodeClient()

OptionTypeDefaultDescription
modelstring"opus"Model name passed to --model
maxBudgetUsdnumber5Spend cap per call via --max-budget-usd
timeoutMsnumber120_000Kill the process after this many ms
options.claudePathstring"claude"Path to the claude binary
options.cwdstringprocess.cwd()Working directory for the subprocess
options.envNodeJS.ProcessEnvprocess.envEnvironment variables for the subprocess
options.permissionModestring"dontAsk"One of "default", "plan", "dontAsk", "acceptEdits", "bypassPermissions", "auto"
options.toolsstring""Tools flag; "" (default) omits the flag entirely, "default" enables built-ins
options.systemPromptstringFull system prompt via --system-prompt
options.appendSystemPromptstringAppended system prompt via --append-system-prompt
options.allowedToolsstring[][]Repeated --allowedTools per entry
options.disallowedToolsstring[][]Repeated --disallowedTools per entry
options.fallbackModelstringFallback model via --fallback-model
options.betasstring[][]Repeated --betas per entry
options.agentstringAgent name via --agent
options.agentsstringJSON object string for custom agents via --agents
options.retriesnumber1Retries after timeout kill (total attempts = 1 + retries)
options.retryDelayMsnumber800Base delay between retries (linear backoff)

Note: total_cost_usd is reported by the Claude Code CLI. If you're using a subscription plan, this may be an estimate and not necessarily an incremental billed amount.

Codex Options

createCodexClient()

OptionTypeDefaultDescription
modelstring"gpt-5.3-codex"Model name passed to --model
timeoutMsnumber180_000Kill the process after this many ms
options.codexPathstring"codex"Path to the codex binary
options.cwdstringprocess.cwd()Working directory for the subprocess
options.envNodeJS.ProcessEnvprocess.envEnvironment variables for the subprocess
options.skipGitRepoCheckbooleantrueSkip git repo validation via --skip-git-repo-check
options.sandboxstring"workspace-write"One of "read-only", "workspace-write", "danger-full-access"
options.profilestringProfile name via --profile
options.configstring[][]Repeated --config key=value per entry
options.jsonlEventsbooleanfalseEnable JSONL event output via --json
options.imagestring[][]Repeated --image path per entry

Gemini Options

createGeminiClient()

OptionTypeDefaultDescription
modelstring"gemini-3-flash-preview"Model name passed to --model
timeoutMsnumber180_000Kill the process after this many ms
options.geminiPathstring"gemini"Path to the gemini binary
options.cwdstringprocess.cwd()Working directory for the subprocess
options.envNodeJS.ProcessEnvprocess.envEnvironment variables for the subprocess
options.approvalModestring"plan"One of "default", "auto_edit", "yolo", "plan"
options.sandboxbooleanfalseEnable Gemini sandbox mode
options.debugbooleanfalseEnable Gemini debug mode
options.policystring[][]Repeated --policy path per entry
options.adminPolicystring[][]Repeated --admin-policy path per entry
options.extensionsstring[][]Repeated --extensions name per entry
options.includeDirectoriesstring[][]Repeated --include-directories path per entry

Note: Gemini does not currently expose a native JSON-schema flag in its CLI. Envelope's Gemini structured mode embeds the JSON Schema into the prompt, parses the returned JSON strictly, and then validates it again with Zod.

Tracking native schema support upstream:

  • https://github.com/google-gemini/gemini-cli/issues/13388
  • https://github.com/google-gemini/gemini-cli/issues/5021

Usage (Zod envelope)

import { z } from "zod";
import {
  createEnvelope,
  createClaudeCodeClient,
  createCodexClient,
  createGeminiClient,
} from "@howells/envelope";

const summarizeClaude = createEnvelope({
  client: createClaudeCodeClient({ model: "opus", maxBudgetUsd: 2 }),
  input: z.object({ text: z.string().min(1) }),
  output: z.object({ summary: z.string().min(1) }),
  prompt: ({ text }) =>
    `Summarize this in 1 sentence. Return JSON only: ${JSON.stringify({ text })}`,
});

const summarizeCodex = createEnvelope({
  client: createCodexClient({ model: "gpt-5.3-codex" }),
  input: z.object({ text: z.string().min(1) }),
  output: z.object({ summary: z.string().min(1) }),
  prompt: ({ text }) =>
    `Summarize this in 1 sentence. Return JSON only: ${JSON.stringify({ text })}`,
});

const summarizeGemini = createEnvelope({
  client: createGeminiClient({ model: "gemini-3-flash-preview" }),
  input: z.object({ text: z.string().min(1) }),
  output: z.object({ summary: z.string().min(1) }),
  prompt: ({ text }) =>
    `Summarize this in 1 sentence. Return JSON only: ${JSON.stringify({ text })}`,
});

const out = await summarizeClaude({ text: "..." });
console.log(out.summary);

Usage (AI SDK 6)

import { generateText } from "ai";
import { claudeCode, codex, gemini } from "@howells/envelope/ai-sdk";

const { text } = await generateText({
  model: claudeCode("opus"),
  prompt: "Write a haiku about camellias.",
});

const r2 = await generateText({
  model: codex("gpt-5.3-codex"),
  prompt: "Write a haiku about camellias.",
});

const r3 = await generateText({
  model: gemini("gemini-3-flash-preview"),
  prompt: "Write a haiku about camellias.",
});

Structured JSON output is also supported via Output.object():

import { generateText, Output, jsonSchema } from "ai";
import { claudeCode } from "@howells/envelope/ai-sdk";

const { output } = await generateText({
  model: claudeCode("sonnet"),
  prompt: "List three colours and their hex codes.",
  output: Output.object({
    schema: jsonSchema({
      type: "object",
      properties: {
        colours: {
          type: "array",
          items: {
            type: "object",
            properties: {
              name: { type: "string" },
              hex: { type: "string" },
            },
            required: ["name", "hex"],
          },
        },
      },
      required: ["colours"],
    }),
  }),
});

Notes:

  • The adapter uses single-shot calls under the hood (streaming is simulated).
  • If we want true streaming, we can extend it to use claude --output-format stream-json.
  • Codex defaults to workspace-write; opt into danger-full-access explicitly when you really need it.
  • Gemini defaults to approvalMode: "plan" so the CLI stays in a read-only posture unless you opt into a more permissive mode.
  • Gemini structured output is prompt-guided rather than CLI-schema-native, so strict Zod validation after parsing matters even more there.

Keywords

llm

FAQs

Package last updated on 05 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts