Tacit is an AI-first programming language: a language designed for models to read and write, not for humans to type by hand.
The project starts from a different assumption than mainstream languages. If human readability is not the primary constraint, a language can optimize for three things at once:
- token efficiency for AI generation and consumption
- runtime performance via strong compile-time guarantees
- safety and security through explicit, structural semantics
Tacit compiles to LLVM IR and then native code. The current Tacit-Lite compiler can parse, typecheck, inspect, compile, test, lock-package, and execute the frozen Phase 6 language surface, and is shippable as a versioned toolchain that drives Tacit projects outside this repository.
- The AST is the source of truth. Tacit does not treat a human-oriented surface syntax as the authoritative program representation.
- Programs have multiple lossless views. A dense authoring view is optimized for AI token efficiency, while an inspection view is optimized for debugging and human review.
- Canonical text is byte-exact. Every valid AST has exactly one canonical serialization, which removes stylistic variance and formatter debates.
- Definitions are content-addressed. Functions, types, and values are identified by the BLAKE3 hash of their canonical text, so identity is structural rather than name-based.
- Names are metadata, not identity. Variable references use DeBruijn indices in canonical form; display names are advisory sidecar data.
- Errors stay structural. Malformed code becomes typed
Holenodes with structured diagnostics instead of opaque parse failures. - Effects are explicit. Tacit-Lite tracks effects in function signatures so important behavioral facts remain visible without whole-program analysis.
Tacit deliberately strips out many human conveniences:
- free-form formatting
- comments in source
- human-readable identifiers as semantic identity
- syntactic sugar and multiple spellings for the same construct
- prose-first error reporting
In exchange, it adds machinery that is useful for AI authoring:
- canonical AST storage
- purpose-built authoring and inspection views
- structural typing and explicit effect tracking
- content-addressed definitions and modules
- explicit recursion grouping and evaluation structure
The default target is Tacit-Lite, a smaller practical variant with structural types, simple effect tracking, and single-threaded execution. Tacit-Full is a longer-term research path that adds refinement types, capability-based security, and richer effect systems.
plans/- project vision, phase plans, and frozen specs (canonical text format, inspection view, sidecar, toolchain export)docs/- supporting design notes (compiler architecture, effect system, installation)decisions/- ADR-style design decisions (0001 onward)crates/- Cargo workspace:tacit-canonical,tacit-views,tacit-typecheck,tacit-codegen,tacit-cliexamples/- Phase 1 smoke corpus undersmoke/, plus Phase 3, Phase 4, and Phase 6 examples (typed memory, fixed-int, data layout, package tests, embedding demo)corpus/- Phase 3 evaluation corpus, with sealed held-out subsetstdlib/- source-level Tacit stdlib packages undertacit/(core,bytes,array,text,collections,io) pluslibc-effects.tomlfor the typecheckertools/- one-shot generators and dev utilitiesscripts/- release scripts (e.g.build-release.sh)share-assets/- assets bundled into the toolchainshare/tacit/tree (e.g. agent workflow)impls/- auxiliary implementations (e.g.py-canonicalizer)tacit-toolchain-release.toml- workspace-level release metadata pinning toolchain, primer, LLVM, and schema versions
Phase 6 is frozen by ADR 0089 and the toolchain export plan completed on 2026-05-17 under ADR 0090. The shippable Tacit-Lite surface now includes:
unitartifacts with hash-addressed imports/exports, visibility, and explicit boundary signatures (Phase 6)- multi-unit project graphs with package manifests, lockfiles, a local hash-indexed cache, and package tests (Phase 6)
- fixed-width integers (
i8/u8throughi64/u64), wrapping/checked/saturating arithmetic, shifts, rotates, masks, byte-order helpers (Phase 6) - typed mutable-memory handles, bounds-checked vector access, byte-bus load/store, and CPU/memory data-layout examples (Phase 6)
- source-level stdlib packages (
tacit.core,.bytes,.array,.text,.collections,.io) consumed through ordinary package resolution (Phase 6) - a constrained host-interface ABI with generated C headers and Rust bindings, plus a working Rust embedding demo (Phase 6)
- record products, first-class closures, and compiler-recognized
@map/@fold/@for-eachoverI64Vecprefixes (Phase 4 carry-over) - a versioned toolchain release with embedded release manifest,
tacit init,tacit-toolchain-pin-v1enforcement, bundled stdlib seeding, and a Linux x86_64 GitHub Actions release pipeline (toolchain export)
Phase 5 (the bounded maintenance/debugging validation gate) is frozen by ADR 0078, which accepted proceeding to Phase 6 without a pre-Phase-6 tooling spike. Phase 7 is the next planned phase. Debugger, diff/blame, IDE, public registry, arbitrary FFI, and broad package-tooling work are deliberately out of scope until a later ADR reopens a bounded slice.
Start with:
plans/tacit-plan.mdfor the full project visionplans/phase-6-plan.mdanddecisions/0089-phase-6-frozen.mdfor the frozen Phase 6 baselineplans/toolchain-export-plan.mdanddecisions/0090-toolchain-release-contract.mdfor the toolchain release contractdocs/installation.mdfor installing a published toolchain archiveCLAUDE.mdfor the working rules used in this repo
The toolchain is shippable as a self-contained Linux x86_64 archive. A new project does not need to clone this repository, install LLVM, or know the internal repo layout.
The first export targets Linux x86_64. The tacit binary links statically
against LLVM 19, so no LLVM runtime is required. Runtime deps (libc,
libstdc++, libgcc_s, libm, libz, libzstd, libffi) are present on a
default Debian-bookworm / Ubuntu-22.04+ install. Published release artifacts
are built on Ubuntu 22.04, so the glibc compatibility floor is 2.35.
Download tacit-<version>-x86_64-unknown-linux-gnu.tar.gz and its .sha256
companion from the release pipeline, then:
sha256sum -c tacit-<version>-x86_64-unknown-linux-gnu.sha256
tar -xzf tacit-<version>-x86_64-unknown-linux-gnu.tar.gz
sudo cp tacit-<version>-x86_64-unknown-linux-gnu/bin/tacit /usr/local/bin/
sudo cp -r tacit-<version>-x86_64-unknown-linux-gnu/share/tacit /usr/local/share/
tacit version --format jsonFor a per-user install with no root, use ~/.local/bin and ~/.local/share
instead. tacit version --format json should report
installed_manifest.status: "matched". If you would rather build from source,
see docs/installation.md.
In a directory outside this repository:
tacit init my-project --with-stdlib
cd my-projecttacit init writes a canonical project layout:
my-project/
tacit-toolchain.toml # pins toolchain, primer, and bundled stdlib hashes
tacit.toml # package manifest
tacit.lock # hash-pinned dependency lockfile
AGENTS.md
CLAUDE.md
src/
main.tac # canonical text (authoritative)
main.tacd # JSON sidecar (display names, field order, hints)
--with-stdlib adds hash-pinned dependencies on the bundled stdlib packages
and seeds them into .tacit/cache/. Use --template library instead of the
default executable template if you want a library project that can emit a
host-interface library.
All package-aware commands verify the project's toolchain pin before doing any
work, so mismatches surface as structured toolchain-pin-* diagnostics:
tacit check . # parse, canonicalize, typecheck, effect-check
tacit test . --format json # run package tests
tacit lock # regenerate tacit.lock after editing tacit.toml
tacit compile . # build the executable (or library)For a library project, tacit interface . --emit-library emits the C header
and Rust bindings for the constrained host-interface ABI. See
examples/phase-6/embedding-demo/ for a Rust host program that links a Tacit
kernel as a static library.
Agents and humans can discover the exact bytes of the Tacit-Lite primer and the agent workflow doc through the installed toolchain itself, so prose never needs to be copied out of this repository:
tacit primer # print the primer markdown
tacit primer --format json # primer id, version, hash, token count
tacit primer --check primer.md # verify a copy matches the installed bytes
cat $(dirname $(which tacit))/../share/tacit/workflow/agent-workflow.mdThe primer is pinned per ADR 0090, so a published toolchain release always teaches the exact language surface it implements.
For more detail (archive layout, environment variables, tacit doctor, source
builds), see docs/installation.md.