skelm

Author, run, and operate skelm pipelines — typed TypeScript orchestrations that mix deterministic code, LLM inference, and full agent loops behind a default-deny permission model. The serious alternative to lobster and llm-task for agentic workflows.

Safety Notice

This listing is from the official public ClawHub registry. Review SKILL.md and referenced scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "skelm" with this command: npx skills add scottgl9/skelm

skelm

Build secure, agentic, long-running workflows in TypeScript. Run them anywhere Node runs.

npm license


Why skelm exists

Most LLM workflow tools make security an afterthought. Agents call arbitrary tools, read arbitrary files, hit arbitrary URLs — because the framework has no model for preventing it. When something goes wrong (prompt injection, runaway loops, accidental secret exfiltration), you find out after the fact.

skelm is built the other way around. Every agent step starts with zero privileges. Filesystem roots, network hosts, MCP servers, CLI binaries, secrets — each is declared upfront in the step definition. Anything not declared is denied at dispatch, before the backend ever starts. The audit log records every privileged action in a tamper-evident chain so you can always reconstruct what happened.

The rest of the design follows from that principle:

  • Real TypeScript. Workflows are .ts modules you type-check, refactor, test, and version like any other code. No DSL, no YAML, no JSON config.
  • Three step kinds, none wrapping another. code() for deterministic logic, llm() for single inference calls, agent() for full multi-turn loops. Mix them freely in a single pipeline.
  • Multi-backend agents. Opencode, ACP (Copilot, Claude Code, Gemini), OpenAI, Anthropic, Pi — plus a provider SPI for custom backends. Switch backends by changing one config key.
  • First-class MCP support. MCP servers are lifecycle-managed by the gateway, not bolted on. Attach them per-step; the permission model governs which steps can reach which servers.
  • Native control flow. parallel, forEach, branch, loop, wait, and nested pipelines are core primitives.
  • Schedulable. Cron, interval, webhook, one-shot, and queue triggers. The gateway hosts everything long-running.
  • Tamper-evident audit. Hash-chained audit log. Query it with skelm audit query.

Get started in 60 seconds

# 1. Install the CLI
npm install -g skelm

# 2. Scaffold a project
skelm init my-bot && cd my-bot && npm install

# 3. Run your first workflow
skelm run workflows/hello.workflow.ts --input '{"name":"world"}'

# 4. Stand up the gateway (long-running, handles scheduling + agent steps)
skelm gateway start

When this skill activates

Use this skill when:

  • The user is working in a skelm project (any *.workflow.ts / *.pipeline.ts file)
  • The user wants to scaffold, author, or modify a pipeline
  • The user asks about AgentPermissions, skelm.config.ts, MCP wiring, backend setup
  • The user wants to run, inspect, schedule, or debug a pipeline
  • The user is migrating from another workflow tool (LangChain, Inngest, llm-task, lobster)

The unit of work

A pipeline is a TypeScript file that exports a pipeline() call:

import { code, llm, agent, pipeline } from 'skelm'
import { z } from 'zod'

export default pipeline({
  id: 'my-workflow',
  description: 'What this pipeline does.',
  input:  z.object({ task: z.string() }),
  output: z.object({ result: z.string() }),
  steps: [ /* Step[] */ ],
  finalize: (ctx) => ctx.steps['last-step'] as { result: string },
})

Step kinds: code · llm · agent · parallel · forEach · branch · loop · wait · pipelineStep · idempotent

Import everything from 'skelm'. Access prior step outputs via ctx.steps['step-id'].


Step kind quick reference

code() — deterministic logic

code({
  id: 'parse',
  run: (ctx) => ({ value: (ctx.input as { raw: string }).raw.trim() }),
})

llm() — single-shot inference

llm({
  id: 'classify',
  backend: 'openai',
  prompt: (ctx) => `Classify: ${(ctx.input as { text: string }).text}`,
  output: z.object({ label: z.string(), confidence: z.number() }),
  maxTokens: 512,
})

agent() — full agentic loop (default-deny)

agent({
  id: 'implement',
  backend: 'pi',
  prompt: (ctx) => `Implement ticket ${(ctx.input as { id: string }).id}. Return JSON {prUrl}.`,
  permissions: {
    allowedTools:       ['gh.*'],
    allowedExecutables: ['git'],
    allowedMcpServers:  ['github'],
    fsRead:             ['./'],
    fsWrite:            ['./src/'],
    networkEgress:      { allowHosts: ['api.github.com'] },
  },
  workspace: { mode: 'ephemeral', cleanup: 'on-run-end' },
  output: z.object({ prUrl: z.string() }),
  maxTurns: 20,
})

Default-deny: every AgentPermissions field defaults to deny when omitted. An agent with no permissions block cannot call tools, read files, execute binaries, attach MCP servers, or make network requests.


Permissions are part of the API

DimensionFieldDefault
ToolallowedTools / deniedToolsdeny
ExecutableallowedExecutablesdeny
MCP serverallowedMcpServersdeny
SkillallowedSkillsdeny
SecretallowedSecretsdeny
NetworknetworkEgressdeny
FS readfsReaddeny
FS writefsWritedeny
Approval gateapproval

Composition is intersection-only. Project defaults → named profile → step-level. Each layer can only narrow, never widen.

Named profiles in skelm.config.ts:

defaults: {
  permissionProfiles: {
    'github-write': {
      allowedExecutables: ['git'],
      allowedTools:       ['gh.*'],
      allowedMcpServers:  ['github'],
      fsRead:             ['./'],
      fsWrite:            ['./'],
      networkEgress:      { allowHosts: ['api.github.com'] },
    },
  },
}

Apply: permissions: { profile: 'github-write', allowedTools: ['gh.create_pr'] }

Full permissions reference: {baseDir}/references/permissions.md


Project layout

my-project/
├── skelm.config.ts          # Required for gateway + agent steps
├── workflows/
│   └── hello.workflow.ts    # One pipeline per file
├── package.json             # { "dependencies": { "skelm": "^0.3.7", "zod": "^4" } }
└── tsconfig.json

Scaffold a new pipeline from template:

bash {baseDir}/scripts/new-pipeline.sh my-pipeline "What it does"
bash {baseDir}/scripts/new-pipeline.sh my-pipeline "What it does" --agent

Config reference: {baseDir}/references/config.md


CLI essentials

skelm run <workflow.ts> --input '<json>'   # run once
skelm list                                 # discover pipelines
skelm describe <id> --format mermaid       # visualize
skelm history --last 10                    # run history
skelm validate <workflow.ts>               # static preflight
skelm logs                                 # stream gateway logs
skelm audit query --run <id>               # tamper-evident audit trail
skelm schedule add <id> --cron '0 * * * *' # schedule
skelm gateway start                        # long-running gateway

Exit codes: 0 ok · 1 CLI error · 2 schema validation · 3 run failed · 4 cancelled · 5 wait timeout · 6 permission denied · 7 step timeout

Full CLI reference: {baseDir}/references/cli.md


The gateway is the trust boundary

The gateway owns permission resolution, enforcement, secret resolution, audit log, approval gating, trigger dispatch, and registry management.

Never write permission enforcement in pipeline or step code. Pipelines are the user layer. The gateway is the trust layer.

skelm gateway start
skelm gateway status
skelm gateway install --systemd   # systemd unit at ~/.config/systemd/user/skelm-gateway.service

Gateway reference: {baseDir}/references/gateway.md


Common pitfalls

  • Widening at step levelnetworkEgress: 'allow' in a step when the project default is deny has no effect. Intersection always wins.
  • Missing Zod schemainput/output are validated at run boundaries; omitting them skips validation silently.
  • agent() with an unregistered backend — step fails at runtime if backend references an id with no matching entry in config backends: or instances:. The pi SDK backend must be in instances:.
  • Step id collisions inside parallel() — sibling ids must be unique within the parallel block.
  • Editing dist/ — never edit generated files. Run pnpm build to regenerate.

Full references

  • {baseDir}/references/pipeline-authoring.md — all builders, control flow, context shape, retry
  • {baseDir}/references/agent-step.mdagent() signature, backends, workspace modes, MCP
  • {baseDir}/references/permissions.md — full permission model, TrustEnforcer, testing
  • {baseDir}/references/config.mdskelm.config.ts shape, backends, MCP entries
  • {baseDir}/references/gateway.md — gateway lifecycle, HTTP surface, audit log, systemd
  • {baseDir}/references/cli.md — complete CLI reference with all flags and exit codes

skelm v0.3.7 · MIT · npm

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

96push

User-approved 96Push desktop client publishing helper — query platforms/accounts, create content, inspect platform rules, and publish only after explicit con...

Registry SourceRecently Updated
Coding

google-search-web

调用 Google 网页搜索接口,获取实时网页搜索结果。使用此技能当用户需要:Google 搜索/网页搜索/搜索引擎查询、调用 /google/search/web 接口、用 Python 脚本执行 Google 搜索、获取搜索结果列表(标题/链接/摘要)。Use this skill for Google we...

Registry SourceRecently Updated
Coding

DeepMiner Skills

通过 dm-cli 命令行工具与 DeepMiner (DM) 系统交互。**凡是涉及 DM/DeepMiner 系统的任务,必须先读此 Skill。** 触发条件:用户提到 "使用 DM"、"发给 DM"、"用 DM 问一下"、"DM 帮我..."、"DeepMiner 执行..." 等任何涉及 DM 系统的任...

Registry SourceRecently Updated
Coding

CordysCRM

Cordys CRM CLI 指令映射技能,支持将自然语言高效转换为标准 `cordys crm` 命令,具备意图识别、模块匹配、参数补全及分页与全量查询处理能力,输出简洁稳定、无歧义。

Registry SourceRecently Updated
2670Profile unavailable