# zero renders a 3D scene to your terminal through stdout, with no GPU involved

> A JavaScript rasterizer with programmable shaders, a depth buffer and a scene graph, packaged as zero-demo on npm and last pushed in July 2026.

**sinclairzx81/zero** — A 3D renderer written in JavaScript and rendered to the terminal.

- Repository: https://github.com/sinclairzx81/zero
- Stars: 2,460 · Forks: 144
- Language: TypeScript
- License: NOASSERTION
- Published: 2026-10-07 · Updated: 2026-10-07 · Language: en
- Canonical page: https://hysenlabs.com/projects/sinclairzx81-zero

## A software rasterizer that treats the terminal as its framebuffer

GitHub reports sinclairzx81/zero as a TypeScript project with 2459 stars and 144 forks, last pushed on 2026-07-20, with the default branch on master and only two open issues. The topic list names ascii-art, graphics, javascript, nodejs, rasterizer and terminal, which describes the project accurately in six words. The repository description says it is a 3D renderer written in JavaScript and rendered to the terminal.

The README states the constraint that makes the project interesting: no GPU required. Zero implements a 3D renderer in JavaScript and writes its output to a terminal through Node's stdout. Every pixel is a character cell, so the resolution is bounded by the size of your window rather than by a graphics card, and the framing buffer is a grid of terminal cells that get repainted as the frame changes.

That single design choice explains most of the feature list. The author describes zero as a small graphics demo written for fun and to push JavaScript performance, and the tree is correspondingly compact: src/, a scene/ directory, tasks.js, package.json, package-lock.json and a terminal.gif showing the result. There is no test directory and no continuous integration configuration in the tree, which is consistent with the framing.

The repository has a lowercase license file and no homepage configured, and it has published no GitHub releases at all. The npm package carries its own version, 0.8.8, which is the number to watch if you depend on the demo.

## The README and the build scripts describe two different pipelines

The building instructions in the README are three lines long, and they are not the same three lines you will find in package.json:

```bash
$ npm install
$ npm run build
# run it
$ node index
```

The npm scripts are thin wrappers around a tool called smoke-task, and the mapping is not described anywhere in the README:

```json
	"clean": "smoke-task clean",
	"build": "smoke-task build",
	"watch": "smoke-task watch",
	"pack": "smoke-task pack",
	"install_cli": "smoke-task install_cli"
```

So npm run build is not a TypeScript compiler invocation you can read off the page; it delegates to a pipeline definition that lives outside this repository. If you are trying to understand how the bundle is produced, the README will not tell you, and the smoke-task configuration is where you have to look. The same is true of the watch and pack targets.

The last line of the README block, node index, is consistent with package.json rather than a typo. The manifest declares main as index.js and maps the binary name zero-demo to ./index.js, so node index resolves index.js by extension. The npm package is named zero-demo, not zero, and it is published under that name with a npmjs.com/package/zero-demo badge in the README, which is worth knowing before you go looking for a package called zero.

One dependency sits outside the dev toolchain: jpeg-js, listed as a runtime dependency at version 0.4.4, with a matching type package in devDependencies. That is your texture decoder, and it tells you the demo loads JPEG images to map onto geometry rather than using procedural textures alone.

## Programmable shaders and a depth buffer, in plain JavaScript

The feature list in the README is short enough to read as a syllabus. Zero implements programmable vertex and fragment shaders written in JavaScript, perspective z-correct texture mapping, per pixel depth buffering, adaptive resolution on terminal resize, support for 24-bit color, matrix and vector math libraries, and a scene graph.

Two of those entries carry most of the weight. Programmable vertex and fragment shaders mean the pipeline is not hard-coded to one lighting model: the same renderer can present a flat-shaded scene or something with texture filtering because the shading stage is a function you supply rather than a fixed step. Written in JavaScript rather than a GPU shading language, they are also readable in a way that shader code normally is not, which is what makes the project a teaching artifact.

Per pixel depth buffering means the renderer resolves visibility per character cell, so geometry can intersect without the painter's algorithm artifacts you get from sorting whole triangles. Combined with perspective z-correct texture mapping, that gives you a pipeline where a surface can be textured and still be occluded correctly by something in front of it. Those two features together are the difference between a demo that shows a spinning object and one that shows a small scene.

The scene graph is why a scene/ directory exists at the repository root, and the matrix and vector libraries are the supporting arithmetic the transforms need. The README credits these as part of what zero implements rather than as borrowed dependencies, and the package.json dependency list supports that, since only jpeg-js appears at runtime.

## Terminal support is verified per platform, not assumed

The README makes two separate claims about where zero has been run, and the distinction matters. ASCII rendering has been tested on Windows, macOS and Linux terminals. ANSI 24-bit true color rendering has been tested on Cygwin under Windows and on Linux Mint, with the caveat that it should work on most terminals that support true color.

So the default mode is the portable one, and color is the conditional one. The README's feature list also notes that 24-bit color support requires a terminal that supports it, which is the real constraint: the renderer emits ANSI escape sequences and the terminal decides whether they mean anything.

Adaptive resolution on terminal resize is marked as TTY only. That restriction is worth pausing on, because it tells you how the renderer learns its available area. On a TTY it can observe the window size and adjust its grid, so resizing the terminal changes how much of the scene is drawn. Piped into something that is not a terminal, that signal is unavailable and the resolution stays fixed. If you plan to capture output into a file, expect different framing than an interactive run.

The scene/ directory and the resize handling together point to an interactive viewer rather than a batch renderer, and the demo commands in the README match that. They are the shortest useful entry point:

```bash
# start the demo in ascii mode (default)
$ npx zero-demo@latest

# start the demo in 24-bit true color mode (experimental)
$ npx zero-demo@latest --color
```

Note that the project marks the color path as experimental in the command comment itself, not only in the feature list. The default requires no flags and no install, which makes it the right first thing to try.

## Where the README and the repository disagree

Two things in this repository do not line up, and neither is worth resolving by picking a side.

The first is licensing. The README states Licence MIT and package.json declares MIT in its license field. GitHub, however, reports the license as NOASSERTION rather than MIT. That classification means GitHub found a license file it could not automatically map to a known license identifier, which is the expected outcome of naming that file license in lowercase rather than LICENSE. The MIT claim from both human-readable sources is well supported; what GitHub is telling you is that no machine-readable identifier was detected. For your own compliance, treat the package.json field and the license file as the sources to read, and do not rely on the repository's license badge.

The second gap is between what the README documents and what the scripts require. The README's local build is npm install, npm run build, node index, and it never mentions smoke-task, smoke-run, typescript-bundle or the install_cli script, even though all four appear in devDependencies and the scripts block. The README also says nothing about the TypeScript side of the project even though GitHub classifies it as TypeScript and the devDependencies pin typescript at ^3.6.4 with types from @types/node at ^12.7.12, which are old version ranges.

Neither gap suggests the project is broken. They suggest the README is written for someone who wants to see the renderer, not for someone who wants to contribute to it. If you are evaluating it as a dependency, the two facts that matter are the 0.8.8 version and the two open issues. If you are evaluating it as a codebase to read, the gaps are not in your way at all.

## What this project is, and what it is not

Zero is a rasterizer, not a game engine and not a terminal UI toolkit. Nothing documented in the repository suggests scene loading, animation authoring, audio, input handling or a plugin surface, and the README describes it in the plainest possible terms: a small graphics demo written for fun and to push JavaScript performance. Its value is that the pipeline is short enough to read end to end and standard enough that the reading transfers to other rasterizers.

The most useful way to approach it is as a working reference for the parts of 3D that are usually hidden by a graphics API. Perspective correction in texture coordinates, depth testing per pixel, vertex and fragment stages you can read as ordinary functions, and a scene graph holding transforms are all here in a form you can step through in a debugger. When a tutorial explains why a perspective divide belongs where it does, this repository shows the code that does it.

Activity has slowed but not stopped. The last recorded push was 2026-07-20, roughly two months before the material was collected, against 2459 stars, and the version in package.json has reached 0.8.8. The version is pre-1.0, which in practice means the API surface of the demo package may still shift. Two open issues against that star count is a very light maintenance load, so plan on reading the source rather than filing issues and waiting.

If you want to see whether the aesthetic appeals to you before reading any of it, the terminal.gif at the repository root is the fastest evidence available, and the npx zero-demo command in the README is a one-line way to get it live on your own machine.

## Conclusion

zero is a demo that happens to contain a complete small 3D pipeline, and it is most useful when you read it as an explanation rather than as infrastructure. The feature list in the README maps cleanly onto the classic stages of a software rasterizer: vertex and fragment shading, perspective-correct texture mapping, a depth buffer, a scene graph, and a matrix library to hold the transforms. What it deliberately skips is the GPU, which is why the resolution adapts to the window instead of being set by a graphics card.

The practical caveats are ordinary for a project at version 0.8.8 with two open issues and no published releases. The build runs on smoke-task, the color path is marked experimental in the demo command itself, and terminal support is verified on specific platforms rather than assumed. Run it through npx before you clone anything, and read the source under src/ if you want to see how a given stage is done. The screenshots in the README and the terminal.gif at the repository root will tell you faster than any description whether the result appeals to you.

## FAQ

### Does zero need a GPU or a display to run?

No. The README states no GPU required, and zero implements its 3D renderer in JavaScript, writing output to a terminal through Node's stdout. Every pixel is a terminal character cell, so the resolution is bounded by the window size rather than by graphics hardware.

### Which terminals and platforms are supported?

ASCII rendering has been tested on Windows, macOS and Linux terminals. ANSI 24-bit true color rendering has been tested on Cygwin under Windows and on Linux Mint, and should work on most terminals that support true color. Adaptive resolution on terminal resize works on a TTY only.

### What license is zero released under?

The README and the package.json license field both say MIT, and a license file sits in the repository root. GitHub reports the license as NOASSERTION, which means no machine-readable identifier was detected from the file. Read the license file and the manifest for your own compliance rather than the repository badge.

### Is zero still actively maintained?

Slowly rather than not at all. GitHub reports a last push on 2026-07-20, a package version of 0.8.8 in package.json, no published GitHub releases, and two open issues against 2459 stars. Because the version is pre-1.0, expect the demo package API to change.

### How do I build zero locally from source?

Clone the repository, then run npm install, npm run build and node index. Be aware that npm run build is a wrapper around the smoke-task pipeline rather than a plain compiler command, and that the README does not document smoke-task or the install_cli script, so consult the pipeline configuration if you need to know how the bundle is produced.

## Sources

- [Issues](https://github.com/sinclairzx81/zero/issues)
- [README](https://github.com/sinclairzx81/zero/blob/master/README.md)
- [sinclairzx81/zero on GitHub](https://github.com/sinclairzx81/zero)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/sinclairzx81-zero
