helm
CI
·
Releases
·
Issues

A typed TypeScript framework for AI agents. Call typed functions instead of parsing CLI stdout.
Install
npm install helm
Quick start
import { createHelm, fs } from "helm";
const agent = createHelm({
permissions: {
"fs.read": "allow",
"fs.write": "ask",
"fs.remove": "deny",
},
onPermissionRequest: async (operation, args) => {
console.log(`${operation} requested with args:`, args);
return true;
},
}).use(fs());
const { content } = await agent.fs.read("./package.json");
const { entries } = await agent.fs.list("./src", { glob: "*.ts" });
Why helm?
Agents today shell out and parse strings. That means no type safety, no structured errors, and no way to control what operations are allowed.
helm gives agents typed functions with structured inputs and outputs:
const output = bash("git status --porcelain");
const files = parseGitStatus(output);
const { staged, unstaged } = await agent.git.status();
Features
- Typed everything. Inputs, outputs, errors. The types are the docs.
- Builder pattern.
.use() chains accumulate skills; TypeScript infers the full type at each step.
- Permissions are first-class. Every operation has a permission level (
allow, ask, deny). Policies are set per-skill or per-operation.
- Search the registry. A single
search(query) lets agents discover operations without loading the full skill set into context.
- Extensible. Define custom skills that get types, search, and permissions for free.
Defining custom skills
import { defineSkill } from "helm";
const weather = defineSkill({
name: "weather",
description: "Weather forecast operations",
operations: {
forecast: {
description: "Get the forecast for a city",
signature: "(city: string) => Promise<{ temp: number; sky: string }>",
defaultPermission: "allow",
tags: ["weather", "read"],
handler: async (city: string): Promise<{ temp: number; sky: string }> => {
return { temp: 72, sky: "sunny" };
},
},
},
});
const agent = createHelm().use(weather);
const { temp, sky } = await agent.weather.forecast("Seattle");
Permissions
Resolution order (first match wins):
- Exact match in policy —
"git.status": "allow"
- Wildcard match —
"git.*": "ask"
- Operation's own default — set by the skill author
- Global default —
defaultPermission option (defaults to "ask")
const agent = createHelm({
permissions: {
"fs.read": "allow",
"fs.*": "ask",
"dangerous.*": "deny",
},
defaultPermission: "ask",
onPermissionRequest: async (operation, args) => {
console.log(`${operation} requested with args:`, args);
return true;
},
});
Search
Agents can discover operations without knowing what's available upfront:
const results = agent.search("file read");
const { content } = await agent.fs.read("./package.json");
Project structure
src/
index.ts — public API re-exports
types.ts — all type definitions
create-helm.ts — createHelm() factory
define-skill.ts — defineSkill() helper
permissions.ts — permission resolution
search.ts — text search over the registry
skills/
fs.ts — built-in fs skill
Development
pnpm install
pnpm lint
pnpm test
pnpm build
License
MIT © bgub