qip CLI
qip is the command-line host in this repo. QIP is the broader standard: the component contract, execution shape, and architecture.
This page is about CLI behavior: commands, file and network access by the host process, runtime guardrails, and implementation details that should not be mistaken for the whole QIP standard. This repo also contains browser JavaScript hosts such as <qip-edit> and <qip-play>. Native hosts such as the Swift implementation should follow the same component contract but may expose different application APIs.
Names #
Use these names consistently:
- QIP: the component contract, execution shape, and design philosophy.
qip: the CLI executable implemented in this repo.
- QIP component: a WebAssembly module that follows the QIP contract.
- QIP host: any implementation that loads a component, writes input bytes, calls exports, and reads output bytes.
- Browser hosts: this repo's
<qip-edit> and <qip-play> JavaScript runtimes.
Commands #
The CLI is the operational tool for local development, CI, benchmarking, and static-site workflows:
| Command | Use |
qip run | Run a chain of QIP components on input bytes. |
qip bench | Compare one or more components for output parity and performance. |
qip image | Run RGBA image filter pipelines. |
qip comply | Validate a component and run compliance modules. |
qip score | Statically score Wasm control-flow, call cost, recursion, and loop-bound evidence. |
qip dev | Serve a content directory with routing and recipes. |
qip router | Resolve routes and export route artifacts such as WARC. |
qip form | Run an interactive QIP form component in the terminal. |
For the portable component ABI, see QIP Component Contract. For route behavior, see Router. For compliance testing, see qip comply.
Runtime Boundary #
The CLI is designed to run untrusted QIP components with a narrow host interface.
Components execute inside wazero and interact with the CLI only through exported function calls and linear memory.
Current host behavior:
qip does not provide WASI to components.
qip does not register custom host functions for module imports.
- Components that depend on unavailable imports fail instantiation.
Practical effect:
- Module code has no direct API to read files, open sockets, or make HTTP requests.
What The Host Process Can Do #
The CLI process itself can still perform host I/O:
- Read input files via
-i and module files from disk.
- Fetch component bytes from
https://... URLs.
- Write output to stdout (
run) or output files (image).
- Serve localhost HTTP in
qip dev (127.0.0.1:<port>).
So trust in components is separate from trust in the CLI process and its environment.
Supply Chain Notes #
Remote modules:
- Are fetched over HTTPS at runtime.
- Are not currently digest-pinned/enforced.
- Can have their SHA-256 printed in verbose mode for inspection.
Recommendation:
- Prefer pinned/local module artifacts for repeatable production pipelines.
Resource Controls #
Current CLI guardrails:
run executes under a 5000ms context timeout by default (configurable via --timeout-ms).
image executes under a 4000ms context timeout by default (configurable via --timeout-ms).
- Each
dev request executes under a 100ms context timeout.
- Input size is checked against module-advertised input capacity.
- Output size is checked against module-advertised output capacity when output buffers are exported.
run, bench, and image can reject modules whose declared memory exceeds a byte cap with --max-memory <bytes>.
run, bench, and image can enforce fixed memory with --fixed-memory, rejecting modules that can grow linear memory while they run.
qip score reports fixed_bound_loops: PASS when loop backedges match the accepted fixed-counter pattern, and WARN when the bound is not proven.
modules/application/wasm/wasm-strict-profile.wasm enforces the strict artifact profile's factual rules (imports, memory shape, banned instructions, recursion) as a QIP component; modules/application/wasm/wasm-bounded-loops.wasm proves loop bounds. Pipe through both for the full strict tier.
The browser JavaScript hosts expose a matching policy shape with max-memory="<bytes>" and fixed-memory; see Browser Elements and Interactive ABI.
Current limitations:
- Memory policy is opt-in. It is not enabled by default for existing pipelines.
- A module can declare large initial linear memory; instantiation may still reserve significant address space.
Recommendation:
- Components should declare a fixed memory maximum at build time. Zig components should use
--max-memory=<bytes>; see Writing QIP Components In Zig.
- Use
--max-memory when running unreviewed modules or CI checks. A module with memory but no declared maximum is rejected when this flag is set.
- Use
--fixed-memory when you want the module to stay within the linear memory it starts with.
- Use
qip score <component.wasm> when you want a readable static report before deciding whether to enforce the stricter safety checker.
- See Hard Limits for build flags and language-specific guidance.
Data Safety Expectations #
- Module output should be treated as untrusted bytes.
- A module trap or runtime error aborts that stage/request.
qip does not validate semantic correctness of module output beyond contract bounds checks.