qip
vibe fast zig/c as composable wasm
qip lets you compose vibe-coded WebAssembly modules that process text/image/data in a secure pipeline.
These modules cannot access fs/network/env. They focus on one job: parser, validator, image shader, converter, renderer. Every module’s input & output is explicit making everything deterministic. You then compose them into ever greater units using the cli, custom elements, or built-in web router.
Think of them as “React components for anything that run anywhere.” Everything on this site has been made using qip and its router.
Install
go install github.com/royalicing/qip@latest
Examples
Word count (same wc.wasm running via cli)
echo -n "There are eight words here. Try typing more… " | qip run modules/utf8/wc.wasm
Recolor svg icon as orange and convert to favicon (cli)
curl https://unpkg.com/lucide-static@0.575.0/icons/smile.svg \
| qip run modules/image/svg+xml/svg-recolor-current-color.wasm '?color_rgba=0xff7722ff' \
modules/image/svg+xml/svg-rasterize.wasm \
modules/image/bmp/bmp-to-ico.wasm \
> cog.ico
Markdown to HTML (cli)
echo '# Write some CommonMark *Markdown*' | qip run modules/text/markdown/commonmark.0.31.2.wasm
Generate wasm modules as specs for your agents to iterate
How we implemented full CommonMark using Codex and qip comply:
- Download the CommonMark spec.txt.
- Ask a coding agent like Codex or Claude Code to generate a qip compliance module from the spec. This creates cases with inputs and expected outputs in fast WebAssembly.
- Ask your coding agent to implement a new CommonMark wasm from scratch and iterate until
qip comply passes.
curl -L https://raw.githubusercontent.com/commonmark/commonmark-spec/0.31.2/spec.txt -o compliance/commonmark-spec-0.31.2.txt
agent 'Create a `qip comply` module `compliance/commonmark-spec-0.31.2.wasm` in zig from `commonmark-spec-0.31.2.txt`. Run `qip help comply` to learn how to create a compliance module.'
agent 'Implement a CommonMark implementation in zig using the comply module to check'
qip comply modules/text/markdown/commonmark.0.31.2.wasm \
--with compliance/commonmark-spec-0.31.2.wasm
echo '# It works!' | qip run modules/text/markdown/commonmark.0.31.2.wasm
Router
$ ls -R1 site
about.md
favicon.ico
index.md
docs:
first.md
second.md
third.md
$ ls -R1 recipes
recipes/text/markdown:
10-markdown.wasm
10-markdown.zig
20-highlight-syntax-highlight-bash.wasm
20-highlight-syntax-highlight-bash.zig
29-add-highlight-stylesheet-night-owl.wasm
29-add-highlight-stylesheet-night-owl.zig
70-add-fathom-analytics-script.wasm
70-add-fathom-analytics-script.zig
80-html-page-wrap.wasm
80-html-page-wrap.zig
footer.html
header.html
highlight-night-owl.css
styles.css
$ qip route warc ./site --recipes recipes \
| qip run modules/application/warc/warc-to-static-tar-no-trailing-slash.wasm \
> site-static.tar
$ mkdir -p site-static && tar -xvf site-static.tar -C site-static
Philosophy
Good tools should be:
- easy to compose
- secure by default
- cheap to replace
- rapid to test and iterate
- work on the web, on native, and as a cli
- runnable by both agents and users
The problems with software today
Software today is like Matryoshka dolls, frameworks that depend on libraries that depend on libraries that depend on OS libs and so on. This can be incredibly productive for building, but has lead to increasingly complex and bloated end-user apps.
This has expanded the surface areas for security attacks, due to the large number of moving parts and countless dependencies prone to supply-chain attacks. It also means that software is less predictable and harder to debug. Any line of a dependency could be reading SSH keys & secrets, mining bitcoin, remotely executing code. This gets worse in an AI world, especially if we are no longer closely reviewing code.
Two key technologies combined
There are two recent technologies that change this: WebAssembly and agentic coding.
With WebAssembly we get light cross-platform executables. We can really write once, run anywhere. We can create stable, self-contained binaries that don’t depend on anything external. We can sandbox them so they don’t have any access to the outside world: no file system, no network, not even the current time. This makes them deterministic, a property that makes software more predictable, reliable, and easy to test.
AI needs hard boundaries
With agentic coding we get the ability to quickly mass produce software. But most programming languages today have wide capabilities that make untrustworthy code risky. Any generated line could read SSH keys or talk to the network or mine bitcoin. We need hard constraints.
Coding agents are now good enough that you can vibe C or Zig modules that run super fast, as long as there are clear boundaries.
qip forces you to break code into boundaries. Most modules follow a simple contract: there’s some input provided to the WebAssembly module, and there’s some output it produces. Since this contract is deterministic we can then cache easily using the input as a key. Since modules are self-contained and immutable we can also use them as a cache key. Connect these modules together and you get a deterministic pipeline. Weave these pipelines together and you get a predictable, understandable system.
Old guardrails
Paradigms like functional or object-oriented or garbage collection become less relevant in this new world. These were patterns that allowed teams of humans to consistently make sense of the modular parts they wove into software. To a LLM, imperative is just as easy as any other paradigm to author. Static or bump allocation is no harder than malloc/free.
Memory is only copied between modules so within it can mutate memory as much as it likes, which lets you (or your agent) find the most optimal algorithm. If we align code written to the underlying computing model of the von-Neumann-architecture we can get predictably faster performance. We get pockets of speed safely sewn together.
Content-first: formats & encodings
We believe in using formats that have stood the test of time. Need a simple uncompressed image format? image/bmp. Need vector graphics? image/svg+xml. Need a snapshot of a directory of files? application/x-tar. Need a snapshot of a website? application/warc. Need a collection of structured data? application/vnd.sqlite3. Need some text? UTF-8.
The philosophy of qip is to prefer adding functionality via swappable modules rather than building it into qip itself. This then means qip’s aim is to output open formats that are easily consumed.
For example, our static site builder produces a Web Archive — it’s up to you to decide how that would be turned into a collection of files. Perhaps you want trailing/ slashes/ in your URLs. Perhaps you don’t. Maybe you want to upload the content straight to a S3 bucket with no intermediate files touching disk. Or you prefer running it using Nginx. This is left up to you. qip produces a simple archive of every page route, and then it’s up to you and the ecosystem to determine how to use that.
Another belief is qip is content-first, not file-first. Web pages are made of served content, and that content might be dynamic: there might not be a file representation backing what users see. This unlocks flexibility with the ability to pipeline any content together. Files need a name, permissions, a file system for it to live in. We just want the content inside, because then we can create modules that consume and produce that type of content.
Benefits
- Composable: swappable units that you author either with AI or by hand.
- Secure: isolated from fs/network/env.
- Small: lean core instead of giant runtime or framework.
- Deterministic: input/output contracts that are easy to test and cache.
- Portable: execution that works identically across platforms.
- Boring: simple conventions, predictable, reproducible, maintainable.
Tech choices
qip favors explicit simple contracts and plain directory layouts over magic.
The qip cli is built in Go using its venerable standard library for file system access, HTTP server, and common format decoding/encoding. The wazero library is used to run WebAssembly modules in a secure sandbox. WebAssembly modules can be authored in C, Zig, WAT, or any language that targets wasm32.
It decidedly does not use WASI. This standard has ballooned in complexity and scope creep. To get stuff done and to support browsers we use a much smaller contract between hosts and modules.
Vibe once, run everywhere
TODO: explain why we’d want to invest into a particular implementation and run that everywhere.