
Product
Socket MCP Adds Org Alerts, Threat Feed Review, and Package Inspection
Socket MCP now lets AI assistants review org alerts, investigate threats using the Socket threat feed, and inspect package files in addition to dependency scoring.
@howells/envelope
Advanced tools
Strict Zod IO wrapper around local CLI LLMs (Claude Code, Codex, Gemini), plus an AI SDK adapter.
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:
--json-schema / --output-schemanpm install @howells/envelope
claude CLI installed and authenticated (Claude Code), orcodex CLI installed and authenticated (Codex), orgemini CLI installed and authenticated (Gemini CLI)createClaudeCodeClient()| Option | Type | Default | Description |
|---|---|---|---|
model | string | "opus" | Model name passed to --model |
maxBudgetUsd | number | 5 | Spend cap per call via --max-budget-usd |
timeoutMs | number | 120_000 | Kill the process after this many ms |
options.claudePath | string | "claude" | Path to the claude binary |
options.cwd | string | process.cwd() | Working directory for the subprocess |
options.env | NodeJS.ProcessEnv | process.env | Environment variables for the subprocess |
options.permissionMode | string | "dontAsk" | One of "default", "plan", "dontAsk", "acceptEdits", "bypassPermissions", "auto" |
options.tools | string | "" | Tools flag; "" (default) omits the flag entirely, "default" enables built-ins |
options.systemPrompt | string | — | Full system prompt via --system-prompt |
options.appendSystemPrompt | string | — | Appended system prompt via --append-system-prompt |
options.allowedTools | string[] | [] | Repeated --allowedTools per entry |
options.disallowedTools | string[] | [] | Repeated --disallowedTools per entry |
options.fallbackModel | string | — | Fallback model via --fallback-model |
options.betas | string[] | [] | Repeated --betas per entry |
options.agent | string | — | Agent name via --agent |
options.agents | string | — | JSON object string for custom agents via --agents |
options.retries | number | 1 | Retries after timeout kill (total attempts = 1 + retries) |
options.retryDelayMs | number | 800 | Base 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.
createCodexClient()| Option | Type | Default | Description |
|---|---|---|---|
model | string | "gpt-5.3-codex" | Model name passed to --model |
timeoutMs | number | 180_000 | Kill the process after this many ms |
options.codexPath | string | "codex" | Path to the codex binary |
options.cwd | string | process.cwd() | Working directory for the subprocess |
options.env | NodeJS.ProcessEnv | process.env | Environment variables for the subprocess |
options.skipGitRepoCheck | boolean | true | Skip git repo validation via --skip-git-repo-check |
options.sandbox | string | "workspace-write" | One of "read-only", "workspace-write", "danger-full-access" |
options.profile | string | — | Profile name via --profile |
options.config | string[] | [] | Repeated --config key=value per entry |
options.jsonlEvents | boolean | false | Enable JSONL event output via --json |
options.image | string[] | [] | Repeated --image path per entry |
createGeminiClient()| Option | Type | Default | Description |
|---|---|---|---|
model | string | "gemini-3-flash-preview" | Model name passed to --model |
timeoutMs | number | 180_000 | Kill the process after this many ms |
options.geminiPath | string | "gemini" | Path to the gemini binary |
options.cwd | string | process.cwd() | Working directory for the subprocess |
options.env | NodeJS.ProcessEnv | process.env | Environment variables for the subprocess |
options.approvalMode | string | "plan" | One of "default", "auto_edit", "yolo", "plan" |
options.sandbox | boolean | false | Enable Gemini sandbox mode |
options.debug | boolean | false | Enable Gemini debug mode |
options.policy | string[] | [] | Repeated --policy path per entry |
options.adminPolicy | string[] | [] | Repeated --admin-policy path per entry |
options.extensions | string[] | [] | Repeated --extensions name per entry |
options.includeDirectories | string[] | [] | 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:
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);
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:
claude --output-format stream-json.workspace-write; opt into danger-full-access explicitly when you really need it.approvalMode: "plan" so the CLI stays in a read-only posture unless you opt into a more permissive mode.FAQs
Strict Zod IO wrapper around local CLI LLMs (Claude Code, Codex, Gemini), plus an AI SDK adapter.
The npm package @howells/envelope receives a total of 20 weekly downloads. As such, @howells/envelope popularity was classified as not popular.
We found that @howells/envelope demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

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.

Product
Socket MCP now lets AI assistants review org alerts, investigate threats using the Socket threat feed, and inspect package files in addition to dependency scoring.

Product
Socket Firewall blocks malicious VS Code and Open VSX extensions before install, protecting developers from compromised editor marketplaces.

Research
More than 140 Mastra npm packages were compromised in a supply chain attack that used a typosquatted dependency to deliver a cross-platform infostealer during installation.