CLI tool
FStarLang/FStar avatar
FStarLang/FStar

F*: A Proof-Oriented Language That Verifies Before It Compiles

A Proof-oriented Programming Language. [fstar-mode.el]: Emacs mode for F* [fstar-vscode-assistant]: VS Code plugin for F* More details on [editor support] are available on the [F\* wiki].

3,104 stars265 forksF*Apache-2.0

At a glance

What is it?
F* is a proof-oriented programming language that verifies code before execution, with extraction to OCaml, F#, C, and Rust. It suits teams that need machine-checked guarantees, but the verification-first workflow and DSL ecosystem demand a steep learning curve.
Who is it for?
Adopt F* if your team builds security-critical or correctness-critical software where machine-checked proofs are worth the cost, and if you can invest in learning dependent types and the Pulse or Vale DSLs. Do not adopt it for general-purpose development where runtime performance or rapid iteration matters more than formal guarantees.
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 last received commits 1 day ago.
What is it written in?
Mainly F*, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 14, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The Problem: Code That Carries Its Own Proof

F* addresses a specific gap in software development: how to write programs whose correctness is not just tested but mathematically established. The README describes it as a proof-oriented programming language, which means the language is designed so that you can state properties about your code and have the compiler check them. This is for teams working on security protocols, cryptographic implementations, or system components where a bug is not a minor inconvenience but a vulnerability. The target user is not a casual programmer. It is an engineer who is willing to trade the speed of write-compile-run for the assurance that the code satisfies its specification. The proof-oriented approach is different from testing because it does not sample the behavior of the program. It reasons about all possible executions. That is the core value proposition, and it is also the source of the difficulty.

How F* Works: Verification Before Execution

The key mechanism in F* is that verification and execution are separate steps. The README states that by default F* only verifies the input code, it does not compile or execute it. This is a deliberate design choice. The language is built around a dependent type system that allows you to write specifications as types. When you write a function, you can annotate it with preconditions and postconditions, and the F* type checker attempts to prove that the function meets those conditions. If the proof fails, the code is rejected. Only after verification succeeds can you extract executable code. The extraction facility is invoked with the command line argument `--codegen OCaml` or `--codegen FSharp`. This workflow means that the act of writing a program is also the act of writing a proof. The proof is not a separate artifact. It is embedded in the types. This is a significant departure from conventional languages where types are mostly about data shape, not behavior.

Getting Started: Installation and Editors

Installation instructions are in the INSTALL.md file in the repository, but the README does not show the exact commands. The online book, titled Proof-oriented Programming In F*, is available as a PDF and also as an interactive tutorial page where you can try examples and exercises in the browser. This is the recommended starting point because it lets you experiment without installing anything locally. For editing F* code, the README points to two main options: fstar-mode.el for Emacs and fstar-vscode-assistant for VS Code. Both provide syntax highlighting, code completion, navigation, and incremental interactive development. The interactive development is important because verification is not always automatic. You often need to guide the prover with intermediate steps, and the editor support is designed for that workflow. There is also an online F* editor at fstar-lang.org/run.php, which is useful for quickly checking whether a problem still exists on the master branch without doing a full build. The README advises against using old releases and suggests using the online editor or the GitHub sources to verify issues.

Extraction: From Proof to Executable

Because F* does not execute code directly, you must extract to another language. The README mentions OCaml and F# as the primary targets, invoked with `--codegen OCaml` or `--codegen FSharp`. There is also a wiki page on executing F* code via OCaml. Beyond that, the README describes two DSLs that extend F* to other domains. Pulse is a DSL for concurrent, imperative programming, and its code can be extracted to C or Rust by the KaRaMeL tool. Vale is an ASM-like deeply embedded DSL that can be extracted to assembly. This is a layered approach. The core language handles pure functional code, and the DSLs handle more specific low-level or concurrent scenarios. The trade-off is that you are not writing one language. You are writing F* plus a DSL, and you must learn the extraction tooling for each target. The README does not specify how mature or battle-tested each extraction path is, so you should verify that before relying on it for production.

Limitations and Failure Modes

The most obvious limitation is that verification is hard. The README does not promise automation. It says that F* only verifies the input code, not that it does so without user effort. In practice, you will spend time writing proofs and interacting with the prover. The editor support for incremental development exists precisely because you cannot always write a proof in one shot. Another limitation is that the language is not designed for runtime performance. The README does not mention any performance characteristics, but the extraction to OCaml or F# means you inherit the performance of those runtimes, and the verification step adds no runtime cost because it happens before extraction. That is a benefit, but the development cycle is slower because every change requires re-verification. A failure mode is that you might choose F* for a project that does not actually need formal verification. The overhead of learning dependent types and writing proofs will slow you down compared to a conventional language with tests. The README also notes that old releases are not maintained, so you must stay on the master branch or the latest release, which can be a maintenance burden if you need stability.

Alternatives: Coq and the Proof Assistant Family

F* is not the only proof-oriented language. Coq is a well-known proof assistant that also allows you to write programs and prove properties about them. The difference is in the approach. Coq is a proof assistant first, and you write programs as terms in a calculus of inductive constructions. F* is designed as a programming language with a proof-oriented type system, and it emphasizes extraction to mainstream languages like OCaml and F#. Coq also extracts to OCaml and Haskell, but its workflow is more centered on the proof script. F* integrates the proof more directly into the function definitions, and it offers DSLs like Pulse for imperative concurrency, which Coq does not have in the same way. Another difference is that F* uses an SMT-based solver to automate many proofs, whereas Coq relies more on manual proof tactics. This means F* can be more automatic for certain properties, but the SMT solver can also be unpredictable when it fails. The choice between F* and Coq depends on whether you want a language that feels like a programming language with proof features, or a proof assistant that can also extract code.

Maintenance and Upgrade Cost

The release cadence is weekly, based on the recent releases listed: v2026.08.23, v2026.08.16, and v2026.08.09. This is a fast-moving project, and the README explicitly says that old releases are not maintained. If you file an issue, you are asked to check whether it still exists on the master branch. That means you are expected to keep up with the latest version, which can be a burden for a project that relies on a stable toolchain. The license is Apache-2.0, which is permissive for commercial use, but you should read the LICENSE file for details. The README does not mention any migration guides or compatibility guarantees between releases. The weekly releases suggest that breaking changes could land at any time. The project has a Zulip forum for questions, which is a good sign for community support, but it also implies that documentation may lag behind the code. The online book is updated periodically, but the wiki is described as especially useful for topics not yet covered by the book, which suggests that the book is not comprehensive. Before adopting F*, you should budget time for tracking upstream changes and for reading the wiki and the book.

Editorial conclusion

Adopt F* if your team builds security-critical or correctness-critical software where machine-checked proofs are worth the cost, and if you can invest in learning dependent types and the Pulse or Vale DSLs. Do not adopt it for general-purpose development where runtime performance or rapid iteration matters more than formal guarantees. Before committing, verify that your target extraction path (OCaml, F#, C, Rust) is supported for your use case and that your team can handle the interactive proof workflow. Check the online book and tutorial first to gauge the learning curve, and confirm that the editor support in Emacs or VS Code meets your needs. F* is not a drop-in replacement for a conventional language; it is a tool for projects where a failed proof is a failed build.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
Community notes

Community notes