Typst's workspace builds only the CLI by default, and its assets come from a pinned git revision
GitHub describes it as A markup-based typesetting system that is powerful and easy to learn.. The repository metadata lists Rust as its primary language. The metadata lists the Apache-2.0 license. This article stays within the project description and details documented in the GitHub repository README.
At a glance
- What is it?
- A read of typst/typst: what a bare cargo build in a fresh clone actually compiles, why the package manager route can lag the release, what the Fibonacci example reveals about identifier resolution in the markup, and how the container's cross build and static OpenSSL differ from a desktop build.
- Who is it for?
- Typst fits documents that need typesetting quality without a TeX installation, and the local CLI is the whole compiler, so offline work needs nothing else. Install from the releases page or a package manager and check the version, because the package managers can lag the release and the Docker latest tag moves.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
This repository is the compiler, and the editor is somebody else's service
The scope statement is short and load-bearing. The repository contains the Typst compiler and its CLI, which the readme calls everything needed to compile documents locally. Anything beyond compiling is out of scope: for the writing experience with autocompletion and instant preview, the readme points at a free collaborative online editor, and for an integrated IDE-like experience it names Tinymist, a community created language server that is integrated into various editor extensions.
That division has consequences for anyone planning a setup. Incremental compilation, watch mode and font discovery all live in the CLI, so a fully local workflow is complete for producing PDFs. Autocompletion and live preview are not, and they come either from a hosted application or from a third party editor extension whose release cadence is not tied to the compiler's. A team that wants no data leaving the machine can get that for compilation and still needs to decide separately whether the language server in their editor phones home.
The rest of the community surface sits outside this repository too. Templates and packages are shared through Typst Universe, with a package repository for submitting your own, and the forum and Discord are where questions go.
Six install routes, and the package managers can lag the release
The installation section opens with sources and prebuilt binaries for the latest release from the releases page, which you download, put on your PATH, and keep current with a single command.
typst updateEverything else is a shortcut with a caveat attached, and the caveat is stated once: the versions in the package managers might lag behind the latest release. On macOS that is `brew install typst`, on Windows `winget install --id Typst.Typst`, and on Linux the readme points at Repology and Typst's Snap rather than naming a single command. Rust users get two cargo routes, and the distinction matters: `cargo install --locked typst-cli` for the latest released version, and `cargo install --git https://github.com/typst/typst --locked typst-cli` for a development version, which installs whatever is at the tip of the repository rather than a release.
Nix has both a package and a flake, with `nix-shell -p typst` to run the packaged compiler and `nix run github:typst/typst-flake -- --version` to build and run the flake. Docker users get a prebuilt image via `docker run ghcr.io/typst/typst:latest --help`, where the latest tag is a moving pointer. So there are six routes and at least three different notions of current, which is the practical reason to check the version after installing rather than assuming the newest one arrived.
A bare multi-letter name is looked up as a definition, which changes how you write text
The readme dissects its own Fibonacci example line by line, and the language decisions are in the annotations. Configuration uses set rules to configure element properties such as page size or heading numbering, and `#set page(height: auto)` is what makes the page scale to fit its content. When set rules are not enough, show rules can completely redefine the appearance of an element. Headings come from markup rather than a function call, so one equals sign makes a top level heading and two make a subheading.
The part that catches new users is how bare words are treated. Mathematical equations sit between dollar signs, extra spaces around the contents push one into its own block, and multi-letter identifiers are interpreted as Typst definitions and functions unless they are put into quotes. The example then applies a modifier to a symbol with `phi.alt` to select a particular variant, and notes that this is why backslashes are not needed for things like `floor` and `sqrt`.
The consequence is a failure mode that has no analogue in a plain text format. A word you meant as prose can resolve to a binding and be typeset as a value, or fail as an unknown name, so anything that should stay literal has to be quoted, and the readme's own recommendation of calling `strip()` on inputs exists to keep stray whitespace from changing the result. Function calls work the way the example shows them, with `#let fib(n)` defining a recursive function, `align(center, table(...))` placing a table, and the spreading operator `..` used on both arrays because they are passed as individual arguments.
The workspace lists eighteen crates, but a plain cargo build compiles one of them
The manifest declares its members broadly, covering every crate in the tree plus `docs`, `tests`, `tests/fuzz` and `tests/wrapper`, and then narrows the default set to a single entry.
default-members = ["crates/typst-cli"]The effect is that `cargo build` in a fresh clone compiles the command line program and none of the library crates, and the test crates and fuzz targets are members but not defaults either. The split across the eighteen internal dependencies is itself a map of the compiler: `typst-syntax` and `typst-ast` style front end crates, `typst-eval` for evaluation, `typst-layout`, `typst-library` for the standard library, `typst-pdf` and `typst-svg` as two output back ends, `typst-html` for HTML output, `typst-ide` for editor support, `typst-timing` and the timing feature on `typst-syntax` for measurement, plus bundle, kit, macros, realize, render and utils. Two of them are declared with `default-features = false`, so their feature flags are chosen by whoever depends on them rather than by the crate's own default.
For a contributor this means the fast inner loop is the CLI alone, and testing a library crate means naming it or building the workspace. The categories entry is a single value, `compilers`, and the keywords list is one word, which is what package index listings for this project will show.
The assets crate is a git dependency pinned to one revision
Most internal dependencies in the workspace are path dependencies carrying the workspace version, 0.15.1, and two are not. One is declared as a git dependency pointing at a separate assets repository, with a revision given as a short hash rather than a branch or tag.
typst-assets = { git = "https://github.com/typst/typst-assets", rev = "94dcb99" }A second one follows the same pattern for development assets. Two things follow for anyone building the source. Fetching dependencies now requires network access to those repositories at those revisions, so an offline build from a warm Cargo cache works but a first build does not, and the `rev` means the asset content is deliberately frozen rather than tracking a branch. A Cargo.lock is committed at the top level, so a given checkout resolves to the same set, and changing the asset set means changing the hash in the manifest.
The release path sidesteps all of it. A user who downloads the prebuilt binary or uses a package manager never compiles this, which is the practical argument for treating the releases page as the primary route and the cargo route as something for people who need a build they can patch.
The manifest asks for Rust 1.92, and the container builds on 1.98
The workspace pins its own floor twice over. The package edition is 2024, and the minimum compiler is declared as rust version 1.92, with a comment attached that says to change it in ci.yml as well.
rust-version = "1.92" # also change in ci.ymlThat comment is a small piece of evidence about how the project handles a toolchain bump: the number is duplicated outside the manifest, so the two have to be kept in step by hand. The container does not use the floor. Its build stage is a Rust 1.98 image on Alpine 3.23, and the cross compilation is done with a dedicated helper image so one Dockerfile can produce binaries for other platforms, with clang and lld added and the crate dependencies fetched through cache mounts before the build runs.
The runtime stage is Alpine 3.23 with a non root user created at uid and gid 1000, and the readme's note in the file says that user can be activated with `--user typst`. OpenSSL is linked statically with its headers installed for the target, so the produced binary carries its own TLS stack rather than depending on the host's. A binary built that way is not the same artefact as one built on a desktop with a glibc system library, which is one reason to treat the container and the release binaries as separate paths rather than as equivalents.
The default output name is a side effect, and the full flag list is two commands away
The usage section is deliberately small, which means a few behaviours are inherited rather than explained. Compiling a source file writes a PDF into the working directory, taking its name from the source.
typst compile file.typPassing a second path chooses the output instead, which is the line any build script needs.
typst compile path/to/source.typ path/to/output.pdfWatch mode recompiles on changes, and the reason it is faster is incremental compilation rather than a smaller document.
typst watch file.typFont handling is the other place the CLI is opinionated, with a flag for adding directories and a subcommand for listing what was found.
typst fonts --font-path path/to/fontsThe same thing can be set through an environment variable, shown in Linux syntax, and the readme does not describe the order in which the default font directories are searched, so a font that resolves on one machine and not another is a question for `typst fonts` rather than for the documentation. For anything beyond these, the readme points at two commands, `typst help` for the list of subcommands and options and `typst help watch` for the detailed usage of one of them.
Editorial conclusion
Typst fits documents that need typesetting quality without a TeX installation, and the local CLI is the whole compiler, so offline work needs nothing else. Install from the releases page or a package manager and check the version, because the package managers can lag the release and the Docker latest tag moves. Before writing code against it, remember that identifiers are resolved as definitions, that a bare cargo build gives you the CLI only, and that building from source pulls a pinned git revision of the assets repository.
Frequently asked questions
What is Typst used for?
It is a markup based typesetting system, so typesetting documents: the feature list names built in markup for common formatting, functions for everything else, an integrated scripting system, math typesetting and bibliography management, with incremental compilation for fast rebuilds.
How do I install Typst on Windows?
The readme gives `winget install --id Typst.Typst` for Windows, and warns once that versions in package managers can lag the latest release, with the releases page binaries plus a `typst update` command as the route that tracks releases directly.
How do I use the Typst CLI to compile and watch a document?
`typst compile file.typ` writes a PDF named after the source into the working directory, a second path argument chooses the output, and `typst watch file.typ` recompiles on changes using incremental compilation. `typst help` and `typst help watch` list the subcommands and the detail for one of them.
Can I use Typst locally without an online account?
Yes for compiling. The readme says the repository contains the compiler and its CLI, which is everything needed to compile documents locally, and lists watch mode, font paths and a font listing among the CLI's features. Autocompletion and instant preview come from the free web app or from the community language server instead.
Why is Typst better than LaTeX?
The readme claims Typst is designed to be as capable as LaTeX while being easier to learn and use, and backs that with built in markup, incremental compilation and error messages meant to be friendly. It offers no benchmark or feature comparison, so the claim is the project's own framing rather than a measured result.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/typst-typst)