TRY IT HANDS-ON functional βœ“ tested 2026-07-21
// sandboxed in macOS (host) Β· aarch64 Β·install log Β·functional log

Contentful skill-kit

by Contentful · https://github.com/contentful/skill-kit · MIT · vv1.10.1 (repo) / v1.10.2 (npm) · updated 2026-07-21

A first-party SDK that treats skills as compile targets. Typed workflow graphs, host-aware XML primitives, and three invocation modes. Genuinely novel, unusually well documented, held back by Node 24 and a bun dependency.

4 / 5
quality 4/5
documentation 5/5
setup 3/5
value 4/5
ecosystem fit 4/5
// bottom line

contentful/skill-kit is the most conceptually ambitious skill-authoring tool GearScope has reviewed. It reframes an agent skill as a typed state machine you compile, not a markdown file you write, and the engineering backs the idea: 427 tests pass, the build emits a real agentskills.io directory, and the MCP server responds to a clean initialize handshake. The friction is real and specific: Node 24 or newer is required, the default build mode needs bun installed, the npm version (1.10.2) drifts ahead of the repo (1.10.1), and the flagship example ships with two lint errors the SDK's own checker flags. For a team building multi-step agent workflows in TypeScript, it is worth a serious look. For anyone happy writing prose SKILL.md files, the state-machine paradigm is extra machinery.

install via npm (public registry)
$npm install @contentful/skill-kit
dev install from source
$git clone --depth 1 https://github.com/contentful/skill-kit && cd skill-kit && npm install && npm run build
build a skill to a distributable dir
$npx skill-kit build src/skill.ts -o skill --mode node

install if

  • TypeScript developers building multi-step agent workflows. If your skill has real branching (do A if the user is a developer, do B if a designer), typed response schemas, and side effects between steps, the state-machine model with compile-time store guarantees is a concrete upgrade over a prose SKILL.md.
  • Teams that want one skill to run across multiple agent hosts. The host-aware XML primitive system (ask-user, confirm, plan, checklist, survey, subagent) renders the same tags for every host, with a preamble mapping tags to host-specific tools. If you target Claude Code and Cursor and Codex from one codebase, this is the design pattern for it.
  • SDK and tooling authors studying skill-authoring infrastructure. The SPEC.md (2,012 lines), the type-level test files, and the three-skill-shapes taxonomy (workflow, reference, composite) are reference material for anyone designing their own skill format. Even if you do not adopt skill-kit, the design decisions are documented well enough to learn from.

What It Does

contentful/skill-kit is an official first-party TypeScript SDK from Contentful (the headless CMS company) for authoring agent skills as compiled artifacts rather than hand-written markdown. You define a skill as a typed state machine: a builder chain of .step() calls, each with a prompt, an ArkType response schema, and declarative branching (next), which you then .build() and compile into a self-contained directory an agent invokes through Bash or MCP. The SDK supports three skill shapes: workflow skills (the typed state machines), reference skills (progressive-disclosure topic loaders for large docs), and composite skills (a dispatcher that routes to sub-skills and topics). The compiled output follows the agentskills.io specification, so a built skill installs anywhere that format is understood (skills.sh, agents-kit, or a plain git clone). It targets developers building structured, multi-step agent workflows in TypeScript who want compile-time guarantees that a prose SKILL.md cannot provide. At review time the repo carried 62 stars and 0 forks, created 2026-04-17 and pushed the same day as this test.

The Good

The "store knows your graph" type system is a real innovation, not marketing. Most skill frameworks treat state as an untyped bag the agent mutates. skill-kit computes, from your step declarations and next transitions, which predecessor steps are guaranteed on every path from entry (non-optional access: store.steps.greet.name) versus which are branch targets (optional access requiring ?.: store.steps['ask-stack']?.answer). Backward edges for retry loops do not create false branches, so the forward path stays guaranteed. The repo backs this with dedicated type-level test files (src/types/store.test-d.ts, branch-extraction.test-d.ts, builder-narrowing.test-d.ts, sub-store.test-d.ts, edge-cases.test-d.ts) that assert the type system narrows correctly. This is the kind of type-safety claim most projects make in a README and never verify. Here it is testable and tested.

The documentation depth is exceptional for a 62-star repo. The README runs 486 lines with a working quick start, a full API builder reference, a step-lifecycle diagram, and a key-decisions section. Beyond the README there are 4,700 lines of supporting docs: docs/api.md (1,459 lines), docs/architecture.md (507 lines), docs/hosts.md (722 lines covering host-aware primitive mapping), and SPEC.md (2,012 lines as the source of truth). Five complete examples ship in the repo (get-to-know-you, ts-patterns, contentful-help, game-jam, primitives-showcase), each with a full skill.ts source and a colocated skill.test.ts. For comparison, most skill repos GearScope reviews treat the README as the entire documentation surface.

The build pipeline produces a portable, spec-compliant artifact. Running npx skill-kit build examples/get-to-know-you/src/skill.ts -o skill --mode node compiled the workflow into a directory containing a generated SKILL.md (with correct frontmatter: name, description, argument-hint, allowed-tools referencing both Bash and mcp__ tool names), a package.json, a single bundled bin/get-to-know-you.mjs Node bundle, a scripts/run shell wrapper as the public interface, and a references/fun-facts.md loaded on demand. The reference-skill build (ts-patterns) produced the same structure with argument-hint: [topic] and MCP tool references for topic loading. The generated SKILL.md even includes a preamble mapping XML primitive tags to host tools, so the same compiled skill works across hosts without per-host forks.

All three invocation surfaces work end to end. The CLI session mode ran a real two-step transition: start --session new returned the greet step prompt with a name schema, then advance --step greet --output {"name":"Alice"} transitioned to ask-role and returned a structured prompt with four options (dev, designer, manager, other), a JSON schema with a role enum, and a completed-step record for greet. The MCP stdio server responded to a JSON-RPC initialize request with protocolVersion: 2025-06-18, serverInfo (name and version), capabilities.tools.listChanged, and human-readable instructions, then tools/list returned the start and advance tools. The reference topics and topic error-handling commands returned the rendered markdown table on demand. Nothing here is a stub.

The test suite is large, colocated, and green. node --test --import tsx/esm 'src/**/*.test.ts' ran 427 tests with 0 failures in 17 seconds, covering the engine, state store, schema validation, cycle-guard detection, deep-merge, preamble rendering, every render helper (table, code, diff, kv, section, checklist), the action lifecycle, and the linter rules. The typecheck (tsc --noEmit) passes clean under strict mode. The 15 example tests (5 each across get-to-know-you, ts-patterns, contentful-help) pass once the library is built. For a v1 SDK at this adoption level, this is above the bar.

The Bad

The npm version (1.10.2) and the repo version (1.10.1) are out of sync, and the install story is muddled. The package.json declares version 1.10.1 with publishConfig.registry set to https://npm.pkg.github.com/ (GitHub Packages), and the README says to install with pnpm add @contentful/skill-kit. But npm view @contentful/skill-kit shows the package is also published to the public npmjs.org registry at version 1.10.2, released 6 days ago by GitHub Actions OIDC, ahead of the repo's own package.json. So a user who follows the README and installs from npm gets 1.10.2 while the repo main branch still declares 1.10.1. The CLAUDE.md contributor guide states "Published to GitHub Packages" as a convention, but the public npm publish contradicts that. Three version surfaces (repo, npm, GitHub Packages) with no documented release process for the public-npm path is the kind of inconsistency the SDK's own linter philosophy would flag in a user skill.

Node 24 or newer is a hard requirement, which excludes the common LTS user. The package.json engines field declares "node": ">=24". Node 24 is recent, and many development machines and CI images still run Node 20 or 22 LTS. The test host happened to have Node 24.13.1, so install and tests proceeded, but a developer on an older Node will hit an engine error or, worse, a runtime failure in a transitive dependency with no obvious cause. For a skill-authoring SDK that wants adoption, pinning to the newest major is aggressive. The badge in the README ("Node.js 24+") is honest about this, but the cost is real.

The default build mode requires bun, which is not a standard install. The README documents two build modes: the default bun mode, which produces standalone executables per platform (roughly 50 to 100 MB each), and the --mode node mode, which produces a single lightweight bundle (roughly 100 to 500 KB) via esbuild. On the test host, bun was not installed, so only the --mode node path was exercisable. A user who runs npx skill-kit build without bun installed and without passing --mode node will hit a failure that the README does not pre-warn about. The node mode is the saner default for most users, but it is not the default.

The flagship example ships with two lint errors the SDK's own checker catches. Running npx skill-kit check examples/get-to-know-you/src/skill.ts flagged two violations of the no-host-tool-names rule in the ask-stack and ask-hobby steps, both referencing the host tool "question" directly instead of using an SDK primitive like act.askUser. The checker is correct to flag this (portability is the SDK's whole value proposition), and it is good that the tool exists. But the example the README points to as the hero demonstration of declarative branching (NextBranch[], askUser) is the same example that fails its own portability lint. The linter also exits 0 even when it reports errors, which means a CI gate that keys off exit status will not catch them.

Adoption is effectively zero, which limits the ecosystem signal. Zero forks and 62 stars three months after creation means nobody outside Contentful is building skills with this yet. There is no community-contributed skill registry, no third-party examples beyond the five in-repo, and no evidence of any agent host shipping first-party skill-kit support. The agentskills.io compliance means built skills are portable in principle, but in practice the only tested consumers are the in-repo examples. This is early-adopter territory, and a team committing to skill-kit is committing to Contentful's roadmap for the concept.

Smoke Test Results

Testing ran on the host (macOS 26.5.1, aarch64, Node 24.13.1). The repo was cloned shallow (5.0 MB, 312 files), dependencies installed via npm install (295 packages, 14 seconds), and the library built with npm run build before example tests could resolve @contentful/skill-kit through the package.json exports field.

Structural validation

$ git clone --depth 1 https://github.com/contentful/skill-kit
βœ… Cloned, 312 files, 5.0 MB

$ npm install --no-audit --no-fund
βœ… 295 packages added in 14s (pnpm not required; npm resolves from package.json)

$ npx tsc --noEmit
βœ… Exit 0, strict mode, zero type errors

$ npm run build
βœ… Exit 0, dist/ emitted (act.js, cli.js, build/, render/, runtime/, etc.)

$ node --test --import tsx/esm 'src/**/*.test.ts'
βœ… 427 tests, 427 pass, 0 fail, 0 skipped (17.0s)

Pass rate: 5 of 5. The framework's structure, types, build, and full SDK test suite are all green on the host.

Full structure log β†’

Run B. Sandbox with deps preinstalled

$ node --test --import tsx/esm examples/get-to-know-you/src/skill.test.ts
βœ… 5 tests, 5 pass (after dist/ build)

$ node --test --import tsx/esm examples/ts-patterns/src/skill.test.ts
βœ… 5 tests, 5 pass

$ node --test --import tsx/esm examples/contentful-help/src/skill.test.ts
βœ… 5 tests, 5 pass (composite sub-skill routing)

$ npx skill-kit check examples/get-to-know-you/src/skill.ts
❌ 2 errors: no-host-tool-names in ask-stack and ask-hobby (flagged, exit 0)

Pass rate: 3 of 4. The three example suites pass once the library is built. The fourth check (the linter) is the one that flags Contentful's own example for portability violations, which is an honest finding rather than a test failure.

Run C. Functional verification (does it do what it claims?)

$ npx skill-kit build examples/get-to-know-you/src/skill.ts -o skill --mode node
βœ… Built: SKILL.md + package.json + bin/get-to-know-you.mjs + scripts/run + references/

$ cd skill && ./scripts/run start --session new
βœ… Returns JSON: step=greet, prompt, schema {name: string}, sessionId

$ ./scripts/run advance --session <id> --step greet --output '{"name":"Alice"}'
βœ… Transitions greet -> ask-role; session JSONL line 4 contains ask-role prompt
 with <ask-user> XML, 4 options, schema {role: enum}, completed greet step

$ printf initialize-request | ./scripts/run mcp --host claude-code
βœ… JSON-RPC response: protocolVersion 2025-06-18, serverInfo {get-to-know-you, 1.0.0},
 capabilities.tools.listChanged, instructions text

$ printf initialize + tools/list | ./scripts/run mcp --host claude-code
βœ… tools/list returns: start, advance (plus a namespaced tool)

$ ./scripts/run topics # reference skill (ts-patterns build)
βœ… Lists 4 topics: generics, discriminated-unions, builder-pattern, error-handling

$ ./scripts/run topic error-handling
βœ… Returns rendered markdown table (4 rows: try/catch, Result<T,E>, Custom Error, never)

Functional pass rate: 7 of 7. Every claim the README makes about the three invocation modes (CLI session, MCP stdio, reference progressive disclosure) and the build output was verified against real output. The bun standalone build mode was the only path not exercised (bun not installed on host).

Full functional log β†’

What the runs tell you

The framework installs cleanly with plain npm (pnpm is not required despite the README), the full test suite and typecheck pass, and the core claim (compile a typed state machine into a portable agent skill) works end to end across the CLI and MCP surfaces. The two real caveats are operational, not functional: you need Node 24 and you need to know to pass --mode node if bun is not installed. The lint errors in the flagship example are a self-consistency gap in an otherwise disciplined repo.

Setup Walkthrough

  1. Install Node 24 or newer. Verify with node --version (the test host ran 24.13.1).
  2. Clone the repo: git clone --depth 1 https://github.com/contentful/skill-kit && cd skill-kit.
  3. Install dependencies: npm install (the README says pnpm install and the lockfile is pnpm, but plain npm resolves from package.json without issue; 295 packages).
  4. Build the library: npm run build. This emits dist/, which the example tests and the build pipeline both need. Without this step, example tests fail with ERR_MODULE_NOT_FOUND for dist/test.js.
  5. Run the SDK tests: node --test --import tsx/esm 'src/**/*.test.ts' (427 tests).
  6. Build an example skill: node --import tsx/esm bin/skill-kit.js build examples/get-to-know-you/src/skill.ts -o my-skill --mode node. Omit --mode node only if you have bun installed and want standalone executables.
  7. Run the built skill: cd my-skill && ./scripts/run start --session new.

Post-install gotcha: the npm package (@contentful/skill-kit at 1.10.2) is ahead of the repo's package.json (1.10.1). If you install from npm you get the newer version; if you clone the repo you get the older declared version. There is no CHANGELOG entry reconciling the two at review time.

Alternatives

  1. Prose SKILL.md (Anthropic skills spec) - the default. A single markdown file with frontmatter that the agent reads. No build step, no types, no state machine. Prefer it for simple skills and for maximum portability across every agent that reads SKILL.md. skill-kit itself compiles down to this format, so it is the lower-level alternative.
  2. vercel-labs/skills (npx skills) - the package manager and runtime for the open agent skills ecosystem. It installs, locks, and scans skills across 73 agents but does not author them. Use it to distribute skills skill-kit builds (the output is agentskills.io compliant, which skills add understands). The two are complementary, not competing.
  3. FrancyJGLisboa/agent-skill-creator - a meta-skill for generating SKILL.md files across 17 platforms from a single source. It focuses on cross-platform scaffolding of prose skills rather than typed state machines. Prefer it if your goal is generating many simple skills for many agents rather than building one complex typed workflow.
// review provenance
reviewed by
GearScope
tested
2026-07-21 · macOS (Apple Silicon)
last verified
2026-07-21
depth
HANDS-ON
sponsorship
none, ever
// share this review
// feedback
was this review helpful?

Want the next one?

Five honest reviews and a verdict you can trust. Every Friday. No spam, no affiliate links.