Skip to main content
This walkthrough assumes you’ve installed meow. By the end you’ll have a project that runs TypeScript directly, serves HTTP, installs a dependency, and passes a test — without configuring a single tool.

1. Scaffold a project

1

Initialize

mkdir hello-meow && cd hello-meow
meow init
meow init writes three files, generates the editor/TypeScript shims, and runs an initial install:
{ "mode": "strict-web" }
meow init defaults to strict-web mode — a deterministic, web-standard sandbox. Building a Next.js/Vite app instead? Run meow init --mode node-compat for the full Node.js surface. See Runtime modes.
2

Run it

meow dev
meow dev is shorthand for meow run dev — it runs the dev script from package.json. Your server is live on port 3000:
curl localhost:3000
# 🎀 🐾 Hello from meow! 🐾 🎀
No build step. No ts-node. No tsconfig.json to hand-write. meow strips the TypeScript types in place and runs the file.

2. Add a dependency

meow installs straight from the npm registry, verifies integrity, and writes a strict, merge-friendly lockfile.
meow add zod
╭─ meow install ──────────────────────────────╮
│ 🐾 1 package ready · 240ms                    │
│ materialized  1 package · 0 edges            │
│ disk          copy-on-write                  │
│ lockfile      meow.lock.jsonl                │
╰──────────────────────────────────────────────╯
Use it like any ESM import:
main.ts
import { serve } from "meow:http";
import { z } from "zod";

const Greeting = z.object({ name: z.string() });

serve(async (req) => {
  const body = Greeting.parse(await req.json());
  return new Response(`Hello, ${body.name}!\n`);
}, { port: 3000 });
meow add -D <pkg> adds a dev dependency. meow remove <pkg> removes it. Both update package.json and re-run the install. See the package manager.

3. Write a test

Create greet.test.ts. Test files import the matcher API from meow:test:
greet.test.ts
import { test, expect } from "meow:test";

function greet(name: string) {
  return `Hello, ${name}!`;
}

test("greets by name", () => {
  expect(greet("Ada")).toBe("Hello, Ada!");
});

test("is not empty", () => {
  expect(greet("Ada")).not.toBe("");
});
Run the suite. meow discovers every *.test.ts / *.spec.ts file and runs each in its own isolated, deterministic V8 isolate:
meow test
greet.test.ts
  ✓ greets by name
  ✓ is not empty
╭─ meow test ─────────────────────────────────╮
│ 🐾 2 passed · 1 file                          │
╰──────────────────────────────────────────────╯

4. Run the quality gate

Everything below shares the same parse of your code — no tool re-reads what another already parsed.
meow check

You’re up

In four steps you ran TypeScript, served HTTP, installed and verified a package, and tested it — touching exactly two project files you’d actually edit (package.json and your source).

How the two modes work

strict-web vs node-compat, and when to reach for each.

The omni-router

Why meow build, meow ./script.ts, and meow some-cli all just work.

Determinism by default

What “frozen clock, seeded RNG” means for your tests and CI.

Full CLI reference

Every command and flag.