# Unison (unisonweb/unison): content-addressed code and the ucm toolchain

> Unison identifies definitions by a hash of their implementation and stores code as an AST in a database, which removes builds and makes renaming non-breaking. Here is what the repository documents, how to build it with Stack, and where the design costs you.

**unisonweb/unison** — A friendly programming language from the future

- Repository: https://github.com/unisonweb/unison
- Website: https://unison-lang.org
- Stars: 6,740 · Forks: 308
- Language: Haskell
- License: NOASSERTION
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/unisonweb-unison

## What Unison is and who the repository is written for

Unison is a statically typed functional language with type inference, an effect system, and a codebase format that stores definitions as ASTs in a database. The README states the central idea plainly: functions are identified by a hash of their implementation rather than by name. That single decision produces the properties the project advertises, including what it calls perfect incremental compilation with a shared compilation cache that is part of the codebase format, instant non-breaking renaming, test caching that reruns deterministic tests only when dependencies changed, and a merge model that ignores import order, whitespace and formatting.

The audience is not someone looking for a first language. It is someone who already writes functional code, is comfortable with a Haskell build toolchain, and is willing to accept a different storage model in exchange for the properties above. The README also points at Unison Cloud for distributed systems, so there are two entry points: a general-purpose language, or a language paired with a hosted runtime.

## Content addressing, the codebase database, and what actually happens on rename

The mechanism is visible in the repository layout. The top level contains codebase2/, unison-core/, unison-runtime/, unison-syntax/, unison-merge/, unison-hashing-v2/ and parser-typechecker/, which is where parsing, typechecking and hashing live. A definition's identity is derived from its implementation, so the name attached to it is metadata rather than identity. Renaming a definition therefore cannot break a reference, because references point at the hash. The same property explains why merges do not produce conflicts over import order or formatting: those differences do not change the hash of anything.

Compilation is cached in the codebase format itself, which the README describes as a shared compilation cache. That is a different claim from a build daemon watching a filesystem. There is no separate build artifact directory to invalidate; the cache travels with the codebase. The trade-off is that the codebase is a database you manage, not a tree of files you can edit in any editor, and the repository includes unison-merge/ and unison-share-api/, which suggests merge and sharing are first-class parts of the model rather than add-ons.

## Building ucm from source with Stack

The README's only documented install path is a source build. It requires Stack; the README links to the Stack install instructions and offers `brew update && brew install stack` as a hint for macOS. Clone the repository, check the Stack version (the README says you will want to know it if you run into trouble), then build and run. The build is `--fast`, so expect a development profile rather than a release one.

```bash
git clone https://github.com/unisonweb/unison.git
cd unison
stack --version
stack build --fast --test && stack exec unison
```

If you want the browser UI while running from source, the README points to the `/dev-ui-install.sh` script, which downloads the latest release of unison-local-ui and places it where the Stack-built executable expects it. On startup you should see a URL printed for Unison Local UI. Note what is missing: the README does not give a package-manager or prebuilt-binary install for ucm, so the source build is the path the repository documents.

## Running ucm: codebase server, environment variables and the Docker image

When `ucm` starts, it also starts a Codebase web server used by Unison Local UI. The README states that it selects a random port and a unique token, and that both the port, the host and the token can be set with the environment variables `UCM_PORT`, `UCM_HOST` and `UCM_TOKEN`. Pinning those values is what makes the server usable from a container or a remote browser, because a random port is not something you can forward predictably.

The repository's Dockerfile shows the same variables in a concrete image. It is based on debian:stable, creates a `unison` user with home `/unison`, installs git, libncurses5, less, locales and fzf, copies a prebuilt `ucm` binary from `tmp/ucm/ucm` into `/usr/local/bin/ucm`, and sets `UCM_WEB_UI`, `UCM_PORT=8080` and `UCM_TOKEN=pub`. It exposes 8080 and runs `ucm --codebase /unison`.

```dockerfile
ENV UCM_WEB_UI=/usr/local/share/ucm
ENV UCM_PORT=8080
ENV UCM_TOKEN=pub
EXPOSE 8080
ENTRYPOINT ["/usr/local/bin/ucm"]
CMD ["--codebase","/unison"]
```

The important detail is `COPY tmp/ucm/ucm /usr/local/bin/ucm`: the Dockerfile expects a binary to already exist at `tmp/ucm/ucm`. It is not a self-contained build recipe, so you have to produce or obtain that binary yourself. Configuration beyond these variables is documented separately in docs/configuration.md.

## Editor and agent integrations the repository documents

The README lists a Language Server Protocol implementation with setup instructions in docs/language-server.markdown, and an AI Agent Server (MCP) with instructions in docs/mcp.md. Both are pointers to files in the repository rather than descriptions in the README, so the practical question is whether your editor's LSP client can talk to it and whether the documented setup matches your setup.

The presence of an MCP server is worth noting on its own: it means the project expects tooling to query the codebase, not just a human typing at a prompt. That fits the content-addressed model, where a tool can ask about definitions by hash. It also means the surface area you have to trust is larger than the language itself. The README does not describe the MCP server's capabilities, so read docs/mcp.md before enabling it.

## Where Unison is the wrong tool, and how it differs from conventional functional languages

The clearest limitation is operational. There is no documented install path in the README other than building from source with Stack, and the Dockerfile requires a prebuilt binary at `tmp/ucm/ucm`. If your environment cannot run a Haskell Stack build, or if you need a distribution package, the repository does not document one. That is a real adoption cost, not a footnote.

The second limitation follows from the design. Content-addressed code is stored as ASTs in a database, so the codebase is the unit you back up, share and merge. Teams whose review process is built around diffs of text files, or whose CI expects a source tree it can compile with an ordinary compiler, are working against the model rather than with it. The README's claim that merges avoid spurious conflicts from import order and formatting is only valuable if you accept the database as the source of truth.

Compare that with a conventional statically typed functional language such as Haskell or OCaml, where a definition is identified by a module path and a name, code lives in files, and the build tool recompiles based on file timestamps or hashes of modules. Unison moves the hashing down to the definition and makes the name a label. You give up familiarity with files and the existing package ecosystem in exchange for renames that cannot break and a cache that is part of the codebase.

## Licence, release cadence and upgrade cost

GitHub reports the licence as NOASSERTION, which means the platform could not classify the LICENSE file automatically. The README does not restate the licence terms. If you need to know what the terms permit, read the LICENSE file at the repository root directly; this article cannot tell you what it says, and the NOASSERTION label is not itself a licence.

On cadence, the most recent release listed is release/1.4.0 on 2026-08-19, with release/1.3.0 on 2026-05-20 and a trunk-build development build on 2026-08-19. The last push to the repository was on 2026-08-19. There is a development build published alongside tagged releases, so you can track trunk if you want, but the repository does not document a support window or a deprecation policy for either. Upgrading means rebuilding from source with `stack build --fast --test` unless you have your own binary pipeline, and the codebase format is the thing to check when moving between versions, since the README ties the compilation cache to that format.

## Conclusion

Unison suits engineers willing to run a Haskell Stack build and work inside a codebase database rather than a filesystem of source files, and teams that want renames and test caching to be structural rather than tooling conventions. It is the wrong choice if you need a packaged binary from the repository, a documented install path for the ucm executable, or a licence you can read off the README. Verify three things before committing: whether the LICENSE file resolves the NOASSERTION status GitHub reports, whether docs/language-server.markdown covers your editor, and whether `stack build --fast --test && stack exec unison` completes on your machine.

## FAQ

### How do I install Unison?

The README documents a source build: clone the repository, install Stack, then run `stack build --fast --test && stack exec unison`. It does not document a package-manager or prebuilt-binary install for the ucm executable.

### How do I use Unison (the language)?

Start `ucm`, which also starts a Codebase web server used by Unison Local UI. The README's sample code shows signatures before definitions, arguments separated by spaces, recursion for loops, and pattern matching with `match <expr> with <cases>`.

### What is the meaning of Unison in this project?

Unison is the name of a statically typed functional language with type inference, an effect system, and content-addressed code, where definitions are identified by a hash of their implementation rather than by name.

## Sources

- [Issues](https://github.com/unisonweb/unison/issues)
- [Project website](https://unison-lang.org)
- [README](https://github.com/unisonweb/unison/blob/trunk/README.md)
- [Releases](https://github.com/unisonweb/unison/releases)
- [unisonweb/unison on GitHub](https://github.com/unisonweb/unison)

---

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