QIP Docs

The Problem With Software Today #

Much software is built as layers of frameworks, packages, platforms, and operating-system features. The result is often non-deterministic in practice: behavior can depend on installed packages, environment variables, filesystem layout, network services, locale, clocks, and the exact setup of the machine around it.

Containers can package that environment, which is useful for full applications. For a content transform, validator, image filter, or small interactive tool, it is often more machinery than the work needs.

AI coding raises the stakes. Agents can generate useful code quickly, but that code is easier to review and test when its inputs, outputs, memory, and host access are explicit.

The QIP Values #

QIP is named for the constraints we want every component to keep:

Names In These Docs #

QIP is the portable standard of component contracts, documented in these pages.

qip is the command-line host implemented in this repo. It also serves as a reference implementation of QIP. This repo also contains browser JavaScript hosts such as <qip-edit> and <qip-play>. Native implementations such as in Swift are also available on request.

QIP Spec #

If you want to send someone the current QIP spec, send them these pages:

Then add the relevant extension specs for the component type:

qip CLI, Router, Recipes, and Browser Elements are reference implementation and tooling docs. They are useful when building with this repo, but they are not the core QIP component spec.

Why WebAssembly #

WebAssembly gives QIP a compact execution target with wide runtime support.

A QIP component is a WebAssembly binary with explicit exports and no imports. By default, QIP gives it no filesystem, network, environment, clock, or secrets. The host writes input bytes into component memory, calls a known export such as render(input_size), then reads output bytes back.

That shape gives the host a deterministic execution boundary: the same component bytes and input bytes are guaranteed produce the same output bytes. Components stay small enough to test, benchmark, and replace when better code appears.

PDF/A, PDF/X, and PDF/UA are not replacements for PDF; they are constrained ways to use PDF for archiving, print exchange, and accessibility. QIP plays the same role for WebAssembly: every QIP component is a WebAssembly module, but not every WebAssembly module is a QIP component.

Why Not WASI #

WASI helps WebAssembly programs behave more like portable command-line or server programs. That is the right shape when code needs file descriptors, clocks, randomness, environment variables, sockets, or a virtual filesystem.

QIP is deliberately narrower. QIP is for components that should not need those capabilities. If a component transforms Markdown, validates UTF-8, renders an image tile, or emits an interactive frame, the host can pass the required bytes in and read bytes back out. The component does not need to explore the filesystem, network, clock, environment, or secrets around it.

That narrower subset is easier to run in browsers, easier to inspect, easier to reproducibly test by comparing outputs, and easier to use safely with AI-generated code. If a component needs database access, user settings, or files, your app should fetch that data and pass in the specific bytes the component is allowed to see.

For the concrete runtime limits, see Hard Limits. For the boundary model, see Architecture And Boundaries.

Content-First Not File-First #

QIP treats content as bytes with MIME types, not as files with special build-system meaning.

That is why recipes are selected by MIME type, why Content components can convert/assert/refine, and why our router works with application/warc instead of a particular static-file layout.

For example, qip router warc ./site produces a application/warc Web Archive. Another component can check for broken links, add extra endpoints, insert meta tags or stylesheets, and turn the archive into a static tarball to be deployed.

Adopting QIP In An Existing App #

QIP fits into existing apps when a small content transform should work the same across platforms, or when generated code should run without filesystem, network, environment, or secret access.

Keep the app in charge of routing, auth, storage, and product workflow. Move a small deterministic transformation into a QIP component: render Markdown, validate HTML, normalize an identifier, transform an image, or generate a QR code. The component gets only the bytes the app passes in, and the app gets portable behavior it can test by comparing output bytes.

See Adopting QIP In Existing Apps for the practical checklist.