Beta · changes weekly
Status & feedback.
#What's Skipper's current status?
Skipper is in active beta — not production-ready. The CLI, the generator, the prompts, and even this page change week to week. Expect bugs; expect things to move. SkipLabs relies on user feedback to find and fix them.
See also
#How do I send feedback or file a bug?
We want to hear from you, especially during beta. The fastest channel is our Discord:
For a useful bug report, please include:
- Your
prompt.md(or the smallest one that reproduces). - The generated
openapi.jsonandextra.json. - Trace files from
.cache/(prompts & AI responses). - The error output, or a description of what went wrong.
Tip: skipper report bundles all of the above into a single archive (you choose exactly what goes in, and it never includes your .env unless you ask) so you can attach it in one drag-and-drop.
Feature requests and broader feedback are welcome in the same place — tag the channel clearly so we can sort.
What Skipper is
Overview.
#What is Skipper?
Skipper is a coding agent that operates in a closed loop. Tools like Claude Code or Codex keep you in the loop — you prompt, review the output, give feedback, iterate. Skipper does that back-and-forth internally. The result feels like a compiler: you define an input, run Skipper, and get a working service — without worrying about what the generated code looks like.
Concretely, it turns a plain-language description (or an OpenAPI spec) into a complete, working Skip Runtime service — routes, data mappers, validators, unit tests, and TypeScript types — and runs it in a container.
#How is it different from Claude Code or Codex?
Those tools keep the human in the loop. Skipper takes the human out of the iteration: the review-and-refine cycle happens inside the agent itself, so the experience is closer to compilation than to conversation.
#Is Skipper actually a compiler?
No. It isn't deterministic, and the semantics of the input aren't rigorously defined. It feels like a compiler in the workflow sense — define input, run, use the result — but it isn't one in the formal sense.
#What is Skipper good at?
Two things especially: talking to the outside world (for example, fetching data from external APIs) and managing state. That makes it a strong fit for multi-user, stateful, real-time, and collaborative applications — things like a small social network or other collaborative tools.
#What kind of thing does Skipper build?
Today it focuses on generating services — the backend, where the logic and state live. Any program can be structured as a service, so the services focus is an implementation detail rather than a hard limit. You can pair the backend with a frontend generated separately (for example with Vercel, Lovable, Replit, or local UI tools).
#Why is Skipper expensive right now?
While Skipper is in beta, the focus is correctness, not cost — getting the maximum number of examples to work, sometimes at a high price. Cost reduction is planned once the system is more stable. Caching already removes the cost of re-running unchanged work.
Get running in 60 seconds
Quickstart.
#Install and run your first service
You need Docker running locally — that is the only prerequisite. You can install the CLI globally (npm i -g @skiplabs/skipper) if you prefer, but the rest of this page sticks to npx: it always fetches the latest published version, leaves nothing behind globally, and makes every example copy-pasteable as-is.
# 1. Authenticate (one-time) npx @skiplabs/skipper login # 2. Describe a service in plain English mkdir my-counter && cd my-counter echo "# Counter service with increment/decrement" > prompt.md # 3. Generate and run it npx @skiplabs/skipper create . npx @skiplabs/skipper run .
The service is served at http://localhost:3000 by default; if that port is taken Skipper scans 3001–3009 for a free one and prints the actual URL. The shortcut npx @skiplabs/skipper auto chains login → prompt → create → run for an even tighter loop. Pass a path — npx @skiplabs/skipper auto my-service — to skip the catalog/editor and use an existing directory containing a prompt.md; omit it to pick from the catalog and run out of $TMPDIR.
#Can I interrupt it safely?
Yes. Press Ctrl + C. Skipper will stop queuing tasks, wait for running tasks, then report status. Completed work is cached, so resuming is cheap.
Under the hood
How it works.
#What are the three components of Skipper?
A harness, a runtime, and tooling.
| Component | Role |
|---|---|
| harness | Skipper's own agent loop — it talks to the AI directly rather than going through Claude Code or Codex. |
| runtime | A reactive programming runtime the generated service runs on. |
| tooling | Feedback for the AI as it iterates — most importantly a type checker. |
#What does “multi-model” mean here?
Skipper doesn't use a single model for everything. It routes each task to the best-fit model.
See also
#What is the reactive runtime?
A runtime for JavaScript where the program is defined as a declarative graph of computation from inputs to outputs. The AI never worries about updates, cache invalidation, or concurrency — the runtime handles all of that. It's the same idea as React, applied to a service instead of a UI.
#What is Skip?
Skip is a programming language developed at SkipLabs, designed specifically for reactive programming. The runtime is implemented in Skip and then injected into JavaScript.
Inputs and outputs live in the Skip heap; JavaScript is used only to compute the links between graph nodes, so only ephemeral objects are allocated in the JavaScript heap. Skip provides the garbage collector and the machinery that makes this possible.
#What is the type checker, and why does it matter?
It's a from-scratch reimplementation of TypeScript that is sound and incremental. Sound means you can trust the types. Incremental means it can re-check quickly when something changes, without restarting from scratch. Both are essential to giving the AI fast, reliable feedback.
#Can I use Skipper's strict TypeScript for my own projects?
It's not designed for that. Making a subset of TypeScript sound requires strict rules that almost no existing libraries respect — even in strict mode — so the ecosystem isn't really ready for it today. You'd have to write all your TypeScript from scratch in that subset, which is why it's built as a development environment for an AI rather than a general-purpose tool.
#How does Skipper handle JavaScript that doesn't fit the sound subset?
Through an escape hatch: that code is sandboxed in a separate process with no access to anything else, and inputs and outputs are serialized in and out. Unsafe JavaScript can't break the rest of the environment.
#Why does Skipper need immutability guarantees?
Reactive programming — breaking code into a graph of computation — depends on immutability, just as React does. Much of Skipper's tooling exists to ensure that objects which must be immutable genuinely are.
The mental model
Core concepts.
#What inputs does Skipper need?
A project directory containing at least one of:
| File | Purpose |
|---|---|
| prompt.md | Natural-language description |
| openapi.json | OpenAPI 3.1 specification |
If prompt.md is present, Skipper generates openapi.json from it via AI — even if openapi.json already exists (it will be overwritten). To hand-edit the spec, remove prompt.md first.
#What does Skipper produce?
A self-contained TypeScript project under <path> — sources, tests, and the two generated specs (openapi.json and extra.json).
When you start it with npx @skiplabs/skipper run <path>, the directory is bind-mounted into a Skipper Docker image that hosts the Skip Runtime server. No local Node or Bun toolchain is needed to run the service.
See also
#What is prompt.md and how do I write one?
A Markdown file describing the service. It can be one line or hundreds. Key sections: Data models, Business rules, API behavior, Storage.
Example
# Counter Service ## Domain Counter (id, value) with increment/decrement operations. ## API behavior RESTful endpoints with JSON responses. ## Storage In-memory, ephemeral.
#What is openapi.json and when do I need one?
An OpenAPI 3.1 spec defining the HTTP API. You need one if you have an existing API design, want precise control, or are iterating on a generated spec (edit openapi.json, delete extra.json, re-run).
If only prompt.md is provided, Skipper generates openapi.json for you.
#Path vs tracked project vs container
A path is a directory on disk. A tracked project is an entry in ~/.skipper/config.json keyed by that path. They're related but independent — and a third concept, the container, is keyed off the same path too.
| Concept | Lives in | Identity |
|---|---|---|
| path | your filesystem | directory with prompt.md / .cache/ |
| tracked project | ~/.skipper/config.json | absolute path (the map key) |
| container | Docker | name derived from sha256(path) |
The path is the join key for all three. Commands divide cleanly: create, iterate, run, and auto operate on a path and record the project entry as a side effect. projects and the interactive picker show tracked projects. stop and logs find the container via the path. untrack removes only the config entry; files and container are left alone. delete tears down all three.
This is why an untracked project still works if you re-run create / iterate / run against the same path, and why delete keeps prompt.md: the on-disk path can survive without tracking, and tracking can survive after the directory is gone.
See also
#How does caching affect costs?
Skipper caches every AI call in <project>/.cache/. On re-run: unchanged prompts return the cached response at zero cost; editing prompt.md regenerates OpenAPI; deleting .cache/ forces a full re-generation.
See also
Recipes
How do I…
#…use Skipper from my coding agent?
Install the Skipper skills into any classic coding agent — Claude Code, Cursor, Codex, and others — so it can drive Skipper for you:
npx skills add skiplabs/skipper-skills
Your agent can then generate and run services on your behalf, using the same npx @skiplabs/skipper commands described below.
#…update a service without regenerating?
On re-run, only changed steps call the AI. To modify: edit openapi.json (remove prompt.md so it isn't overwritten), delete extra.json if the runtime spec needs to change, then re-run.
npx @skiplabs/skipper iterate my-project
You can change the prompt and re-run: iterate opens your $EDITOR on prompt.md (it aborts if you leave the file unchanged) and regenerates, reusing cached steps that didn't change. What it does not yet do is apply a prompt change as a surgical, incremental diff — today a prompt edit triggers a fresh generation pass rather than a targeted patch. That finer-grained iteration is in development.
#…reset a project?
Full teardown — stops the container, untracks the project, and wipes generated files. Keeps prompt.md.
npx @skiplabs/skipper delete my-project
Untrack only — forgets the project from ~/.skipper/config.json. Files and container are left alone.
npx @skiplabs/skipper untrack my-project
Clear AI cache only — re-run with a cache miss (everything else preserved):
rm -rf my-project/.cache npx @skiplabs/skipper iterate my-project
#…know if the generated API is correct?
Skipper validates automatically: type checking (TypeScript), unit tests (generated & executed), and a retry loop (fixes up to 8 attempts).
Review process:
- Check
openapi.json(API contract) - Check
extra.json(reactive graph) - Run
bun test - Manual smoke test
#…run the unit tests?
cd my-project bun test
#…customize the generation?
Not directly. Skipper derives everything from openapi.json and extra.json. To influence output: control naming via operationId in OpenAPI, control types via precise schemas, or post-process the generated code.
No hooks, plugins, or config files for generation-time customization.
#…integrate with an existing codebase?
The generated service is a standalone Express app using Skip Runtime's in-memory reactive collections.
Integration options: standalone microservice (deploy alongside, communicate via HTTP), module (import into your Express app), or external resources (via useExternalResource()).
For database integration, add your own persistence layer.
#…run Skipper in CI/CD?
A temperature of 0.3 makes output mostly consistent but not byte-for-byte deterministic. For CI/CD, commit the .cache/ directory (SHA-256 keyed, re-runs identical with cache) and commit the generated code (treat it as source). There is no --ci flag.
#…structure multiple services?
One service per directory. Each gets its own generated code, dependencies, and cache.
npx @skiplabs/skipper create services/users npx @skiplabs/skipper create services/orders npx @skiplabs/skipper create services/notifications
No cross-service coordination — services are independent.
Lookups
Reference.
#CLI commands
Usage: npx @skiplabs/skipper [command] [path] Commands: login / logout Auth (one-time) create [path] Generate a project from prompt.md iterate [path] Re-generate an existing project run [path] Start the project container stop [path] Stop the project container logs [path] Tail container logs projects / ls List tracked projects status Show CLI + Docker state balance Show remaining balance auto [path] One-shot: login + prompt + create + run untrack [path] Forget a project (keeps files) delete / rm [path] Tear down (keeps prompt.md) help [command] Show help for a command
#Run flags
Defaults to http://localhost:3000. If 3000 is taken Skipper scans 3001–3009 and uses the first free port. Pass --port 4000 to bind a specific port — when set explicitly there is no fallback: if 4000 is busy the command errors. Add --dev to disable auth and CORS for local work.
Running in a container (the default for run) is safer than running the service directly, and is the recommended path. In dev mode the service also exposes an openapi.json endpoint with the full spec, which a UI generator can consume.
#Does Skipper support authentication?
Yes. By default it's set up for Google, but you can use any provider. For local development, run with --dev to disable auth — Skipper uses a generated dev token, which should never be used in production.
#Generation phases
1. Unit test environment Setup TypeScript test runner 2. OpenAPI specification prompt.md → openapi.json 3. Runtime specification openapi.json → extra.json 4. Reactive graph Builds Skip service from specs 5. Code generation Generate, type-check, fix (8 attempts) 6. Unit test generation Generate and verify tests 7. Dataset generation Generate test data from schemas 8. Save Write files with Prettier formatting
Steps 5–7 run in parallel using all CPU cores.
#Output file structure
| Path | Description |
|---|---|
| openapi.json | OpenAPI 3.1 spec |
| extra.json | Skip runtime spec |
| package.json | Dependencies |
| src/index.ts | Entry point |
| src/service.ts | Service definition |
| src/routes.ts | Route handlers |
| src/types.ts | TypeScript types |
| src/mappers/ | Data mappers |
| src/reducers/ | Aggregations |
| src/resources/ | State entities |
| src/tests/ | Unit tests |
| tests.spec.ts | Test entry |
| helpers/ | Runtime helpers |
| .cache/ | LLM cache & traces |
#.cache/ on-disk format
Contains cached LLM responses (hash.cch) and trace files (hash/000.trace). The cache key is the SHA-256 of the prompt. A cache hit is instant and zero cost.
# Inspect cached calls cat my-project/.cache/*.trace | head -100
#Environment variables
EDITOR (used when editing prompt.md interactively).
Auth is handled by npx @skiplabs/skipper login — no API key env var to set.
#Which AI model does Skipper use?
Skipper is multi-model — it routes each task to the best-fit model rather than using one model for everything. There is no CLI flag to switch — model selection is configured in code.
See also
When things go wrong
Troubleshooting.
#What does “generation failed” mean?
error Generation failed in 0.2s, cost $0.82 - Error: At least one Code with imports shall be defined
Common causes: the AI produced invalid code (8-attempt limit), openapi.json or extra.json has structural issues, or TypeScript found unfixable errors.
Platforms & boundaries
Compatibility & limits.
#What versions of Node / Bun are required?
Bun 1.x is recommended (primary runtime). Node.js 18+ also works. Generated code targets ES2021.
#Does Skipper work on Windows?
macOS and Linux natively. On Windows, use WSL.
#Is there a project size limit?
No hard-coded limits. Practical limits: AI context window (~200K tokens) and per-entity output cap (~16K tokens). Very large APIs (50+ endpoints) may hit token limits.