# Projects and brine.toml

> What brine new and brine init create, every brine.toml key, the target/ folder layout, the build cache, and running single files instead of projects.

Source: https://docs.brinelang.org/tooling/projects/

A Brine project is a folder with a `brine.toml` at its root and its main file at `src/main.br`. Commands run inside the folder (or any folder below it) work on the project without arguments. A single `.br` file works too: every command takes a file instead, and its build goes to a cache folder in your temp directory.

## brine new and brine init

[Section titled “brine new and brine init”](#brine-new-and-brine-init)

```sh
brine new hello
```

```text
   Created project `hello`


    cd hello
    brine run
```

```text
hello/
├── .git/
├── .gitignore
├── AGENTS.md
├── README.md
├── brine.toml
└── src/
    └── main.br
```

| File          | Contents                                                                                         |
| ------------- | ------------------------------------------------------------------------------------------------ |
| `brine.toml`  | the project’s name and version                                                                   |
| `src/main.br` | a starter program with a `par` comprehension and a test                                          |
| `AGENTS.md`   | instructions for coding agents: the commands to run and the rules that most often trip people up |
| `README.md`   | a title and the two commands to build and test                                                   |
| `.gitignore`  | `/target`                                                                                        |

`brine new <name>` makes the folder; `brine init` uses the current one, names the project after it, and keeps any of these files that already exist. Both run `git init` unless the folder is already inside a Git repository (and skip it quietly if `git` isn’t installed).

The starter program:

src/main.br

```brine
# Welcome to brine! Run this program with `brine run`.


fn greet(name: str) -> str:
    return f"Hello, {name}!"


fn main():
    print(greet("brine"))


    # parallel by default: this runs across all your cores
    let squares = par [i * i for i in 0..10]
    print(squares)


test "greeting":
    assert greet("you") == "Hello, you!"
```

```sh
cd hello
brine run
```

```text
     Built hello v0.1.0 [dev] in 2.05s
   Running target/dev/hello.exe
Hello, brine!
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
```

## brine.toml

[Section titled “brine.toml”](#brinetoml)

The file `brine new` writes:

brine.toml

```toml
[package]
name = "hello"
version = "0.1.0"
```

These are all the keys Brine reads:

| Section     | Key       | Default         | Meaning                                                                                         |
| ----------- | --------- | --------------- | ----------------------------------------------------------------------------------------------- |
| `[package]` | `name`    | (required)      | the project’s name: the executable is `target/<profile>/<name>`, and it appears in status lines |
| `[package]` | `version` | `"0.1.0"`       | shown in status lines (`Built hello v0.1.0`)                                                    |
| `[build]`   | `main`    | `"src/main.br"` | the main file, relative to `brine.toml`                                                         |
| `[check]`   | `typed`   | `false`         | `true` requires a written type on every `let`, `var` and `for` variable                         |

A project that uses all of them:

brine.toml

```toml
[package]
name = "tool"
version = "1.2.0"


[build]
main = "app/cli.br"


[check]
typed = true
```

### package

[Section titled “package”](#package)

`name` is required:

```text
error: brine.toml: missing `name` in [package]
```

`version` is free text. Brine doesn’t compare versions yet (there is no package manager; `brine add` is on the [roadmap](/reference/roadmap/)).

### build

[Section titled “build”](#build)

`main` names the file that holds `fn main`. Modules load relative to the main file’s folder: with `main = "app/cli.br"`, `import util` loads `app/util.br`.

### check

[Section titled “check”](#check)

`typed = true` makes every variable need a written type, for teams and agents that want types spelled out. It applies to `check`, `build`, `run` and `test`; the `--typed` flag does the same for one command, or for a single file. A missing type is [E0337](/reference/errors/#e0337):

```text
error[E0337]: `s` has no written type
 --> sum.br:2:9
  |
2 |     var s = 0
  |         ^ add `: int`
  |
  = note: this project asks for a type on every variable (`typed = true` in brine.toml, or `--typed`)
  = run `brine explain E0337` for more about this error
```

The value must be `true` or `false`:

```text
error: brine.toml: `typed` in [check] must be true or false, not `yes`
```

### Syntax

[Section titled “Syntax”](#syntax)

Brine reads a small subset of TOML: `[section]` headers and `key = "string"` or `key = value` lines, with `#` comments. Keys it doesn’t know are ignored, so a newer `brine.toml` still works with an older Brine.

## Finding the project

[Section titled “Finding the project”](#finding-the-project)

Without a file argument, Brine looks for `brine.toml` in the current directory, then in each parent. So `brine run` works from `src/` or any subfolder. A file or directory argument overrides this:

| Command                  | Builds                                                               |
| ------------------------ | -------------------------------------------------------------------- |
| `brine run`              | the project around the current directory                             |
| `brine run tools/gen.br` | that one file, as its own program                                    |
| `brine run ../other`     | the project in `../other` (it has a `brine.toml`)                    |
| `brine run scripts`      | `scripts/main.br`, if `scripts/` has a `main.br` and no `brine.toml` |

## The target folder

[Section titled “The target folder”](#the-target-folder)

Project builds go to `target/`, one folder per profile:

```text
target/
├── cache/                    objects and the compiled runtime
│   ├── obj-0548db582edbf74a/
│   ├── rt-2fdf516b1c19bd8c/
│   └── ...
├── debug/
│   ├── hello.brine-hash
│   └── hello.exe
├── dev/
│   ├── hello.brine-hash
│   └── hello.exe
└── release/
    ├── hello.brine-hash
    └── hello.exe
```

| Folder                                                                 | Made by                                          |
| ---------------------------------------------------------------------- | ------------------------------------------------ |
| `target/dev/`                                                          | `brine run`, `brine build` (the default profile) |
| `target/release/`                                                      | `--release`                                      |
| `target/debug/`                                                        | `--debug`, `brine debug`                         |
| `target/dev-c/`, `target/release-c/`, `target/debug-c/`                | a build with `BRINE_BACKEND=c`                   |
| `target/dev-native/`, `target/release-native/`, `target/debug-native/` | a build with `BRINE_BACKEND=native`              |
| `target/cache/`                                                        | intermediate files for every profile             |

Test builds sit next to the program as `<name>-tests` (`target/dev/hello-tests.exe`). On Linux and macOS executables have no `.exe`.

A build with [`BRINE_BACKEND`](/tooling/environment-variables/) set always gets its own folder, even when it picks the backend the profile would use anyway, so it can never replace an executable a default build is running.

### The cache

[Section titled “The cache”](#the-cache)

`target/cache/` holds:

* `rt-<hash>/`: the runtime (`brine_rt.c`, `brine_rt.h`) and its object file, compiled once per runtime version, C compiler and flags. This is why the first build in a new project takes about two seconds and later ones a fraction of one.
* `obj-<hash>/`: the object files of one output, each named by a hash of what it was made from. An edit recompiles only the objects whose input changed. Old objects are pruned once there are many more than the build needs.

Next to each executable, `<name>.brine-hash` records a hash of the objects and runtime it was linked from. When a build produces the same hash and the executable exists, Brine skips the link and prints `Fresh` instead of `Built`.

Deleting `target/` is always safe: the next build makes it again.

## Single files

[Section titled “Single files”](#single-files)

Every command takes a `.br` file instead of a project. Imports load next to that file.

```sh
brine run panic.br
brine check sum.br
brine test t.br
brine build tool.br          # writes ./tool.exe (./tool on Linux and macOS)
```

`brine build` writes a single file’s executable in the current directory, the way a C compiler does. `brine run`, `brine test` and `brine debug` put theirs in a cache folder under your temp directory:

```text
<temp>/brine-cache/
├── 465ef71a47ea2199/        one folder per source file (a hash of its absolute path)
│   ├── dev/argv.exe
│   └── debug/argv.exe
├── obj-.../                  object files, shared by all single-file builds
└── rt-.../                   the compiled runtime
```

`<temp>` is `%TEMP%` on Windows (`GetTempPath2W`) and `$TMPDIR` (else `/tmp`) on Linux and macOS. Nothing removes old folders from `brine-cache`; delete it whenever you like.

|                               | Project                         | Single file                                  |
| ----------------------------- | ------------------------------- | -------------------------------------------- |
| main file                     | `src/main.br` or `[build] main` | the file you pass                            |
| executable name               | `[package] name`                | the file name without `.br`                  |
| `brine build` output          | `target/<profile>/<name>`       | `./<name>`                                   |
| `brine run` output            | `target/<profile>/<name>`       | `<temp>/brine-cache/<hash>/<profile>/<name>` |
| cache                         | `target/cache/`                 | `<temp>/brine-cache/`                        |
| `[check] typed`               | from `brine.toml`               | only with `--typed`                          |
| `brine fmt` without arguments | every `.br` file in the project | every `.br` file under the current directory |

## Related

[Section titled “Related”](#related)

* [The brine command](/tooling/cli/)
* [Builds, backends and performance](/tooling/builds-and-backends/)
* [Modules](/language/modules/)
