Skip to content

Projects

Latet has one configuration for everything, config.yaml. A project can add to it in two ways:

Where Shared What it can do
The project file, latet.yaml in the project’s repository with everyone who works on it only add protection
Your settings for the project in your config.yaml, under projects: no anything, including turning Latet off there

The first is for what the whole team needs: the formats of the project’s own codes, the countries of its customers, a stricter profile. The second is for what is yours: the names of your clients, values that are not sensitive to you, a project where you do not want Latet at all.

On a computer connected to a Latet server, the project file is not applied: the server reads none of the computer’s files, and applies your own settings and the settings it shares. In such a project latet doctor and latet claude say so. To use its rules there, import the latet.yaml in your dashboard, on Rules with Import rules. See What stays on the computer.

A project's rules in the dashboard, in the tabs of the global rules: its Overview, with what is in effect there and your own settings for it as a whole A project's rules in the dashboard, in the tabs of the global rules: its Overview, with what is in effect there and your own settings for it as a whole
A project's rules: Rules, with the project picked at the top.

The folder the agent works in decides.

  • Claude Code: the plugin tells Latet.
  • An agent Latet starts (latet claude, latet codex, latet opencode, latet gemini, latet copilot): its launch key tells Latet, where the agent carries one.
  • Codex, OpenCode and Gemini CLI: they name the folder in their requests.
  • Any other client: it can send the header x-latet-project: <folder>.

A session whose folder is unknown uses your global settings.

The project of a folder is the folder of the nearest latet.yaml, from the folder up to the root of its git repository. Without one, it is the repository; outside a repository, the folder itself. Only the nearest file applies: a subfolder with its own file is a project of its own, and the two are not combined.

Latet trusts a session’s project only when it knows it for itself:

  • From the Claude Code plugin, for a folder Latet knows as a project (one with a latet.yaml, or with your own settings for it). The plugin binds the session to that project; each of its calls to Latet keeps the binding, which ends after 30 minutes without one.
  • From a launch key, for an agent Latet started in that folder.

A folder that only the request names (the header x-latet-project, or the working folder Codex, OpenCode and Gemini CLI write into their requests) is claimed. A claimed project’s rules that add protection apply: its terms, its recognizers, a stricter profile. Its loosenings do not: values and patterns never to mask, secret rules turned off, a weaker profile or policy, data_tools, the local reviewer’s guidance and images. A claimed project where Latet is off is refused all the same, and a request exception for one project applies only where its project is trusted. The dashboard shows each request’s project as trusted or claimed (Project claimed), and how its launch was decided.

  • Before the plugin binds a session. Claude Code makes a few calls as it starts, before the plugin’s first call to Latet: its model list, and on Bedrock its first requests. They are decided with your own rules alone, neither the project’s added rules nor its loosenings.
  • What the binding lets in. A binding is to a session’s id: an Anthropic Messages request that carries the id of a live session of yours that the plugin bound is decided with that project, its loosenings and exceptions included, whichever program of yours sends it. It is still read by the final check and never rewritten, and another person’s requests never reach it. A session that latet claude started needs its launch key instead: its id alone gets nothing of the project’s loosenings.

When Latet starts an agent, it opens a launch for the folder: a secret key drawn for that launch alone, bound to the folder’s project and to you. The agent sends it with its requests in a header, x-latet-launch-key, which Latet checks and takes off before anything is sent on, recorded or logged; Latet keeps only a keyed hash of it. The key ends with the launch: when the agent exits, or when the command that started it is stopped.

Command How the key travels
latet claude ANTHROPIC_CUSTOM_HEADERS, in the private settings file of that session
latet codex env_http_headers of a provider of model_providers, from Codex 0.115; none on Codex’s built-in providers (signed in with ChatGPT, or OpenAI’s own provider)
latet opencode options.headers of each provider it routes
latet gemini GEMINI_CLI_CUSTOM_HEADERS
latet copilot COPILOT_PROVIDER_HEADERS, to an OpenAI-compatible provider over Chat Completions; none over Responses, Anthropic’s API or a WebSocket
latet run none: a program it starts has no way to carry one

The key is added to the headers the agent already sends: yours stay as you wrote them, and still need an exception of their own. An agent that starts without a key is told why, in a sentence such as Latet: Codex older than 0.115 has no way to carry a launch key, so this session's project settings only add protection: their loosenings do not apply., and its project is claimed. A folder that is not one of your projects needs no key.

  • A secret to Latet. In a tool’s output or a message, a live key is masked like Latet’s own token; where Latet cannot mask it (a request it only checks), the request is refused, with words that say to rewind or start a new conversation.
  • Held, not bound to a process. Any program that holds the key counts as that launch. It runs as the same user, and Latet does not claim to tell programs apart.
  • Unknown, ended or someone else’s. A request with a key Latet does not know (its daemon restarted, say) is decided as claimed, never refused for that. A key whose launch ended, or one sent for another project or by another person, is refused.
  • In the address. On a computer, Latet also accepts the key at the start of the address’s path, a form no launcher uses; a Latet server refuses it.

The dashboard shows how each request’s launch was decided: Launched by Latet, key verified, Launched by Latet, key missing (an agent Latet started whose request came without a key Latet can check: decided as claimed), Bound by the Claude Code plugin (a Claude Code configured for good) or Not launched by Latet (claimed). latet doctor names each agent Latet started that was seen without its key, with its version.

latet project init writes one to start from, at the root of the repository. The dashboard’s Rules page writes it too: pick the project in the selector at the top. Its terms, recognizers and policies are rows of the Terms, Recognizers and Policies tables, marked latet.yaml, changed in their panel; a new one goes to the file when its panel’s Save to says latet.yaml. The Repository file tab holds the rest of the file, and creates it.

# yaml-language-server: $schema=https://docs.latet.ai/project.schema.json
profile: max
id_regions: [DE, FR]
terms:
- {value: Project Falcon, type: PROJECT}
recognizers:
- name: badge
description: Badge numbers, two letters, a dash and six digits
pattern: '\bBD-\d{6}\b'
examples:
match: ['badge BD-381904']
no_match: ['BD-12']
policies: {EMAIL: redact}

A value replaces yours only when it is stricter:

  • profile: secrets, then balanced, then max (which turns strict data mode on there, unless data is set);
  • policies: allow, then mask, then redact, against the policy in force there (a recognizer’s own included);
  • include_private_ips: only true;
  • ner: only auto;
  • data: only strict; images: only fewer, mask then block; ocr: only auto; dump_guard: only lower (see Production data);
  • llm_review: off, then background, then inline, when the reviewer is on (see Local reviewer).

A list is added to yours: pii, id_regions, phone_regions, terms, recognizers, data_files, data_hosts and fields (only rules that mask). A recognizer of your settings for the project whose name or type a global one of yours uses is turned off. One of the file whose name or type one of yours uses, global or for the project, applies all the same, under a name or a type of its own (badge-repo, BADGE_REPO): both apply; of one type, both types take the stricter of the two policies; and the project’s page says so, with the name and the type in use. For a field, the stricter of your rule and the file’s applies, yours when they are as strict.

What would leave values in clear there is set aside: a recognizer that lets what it finds through (policy: allow), and a recognizer, a term or a field rule of a type left in clear in that folder, by your policies or your settings for the project. latet project check and the dashboard say which, and where to put it instead: your own settings for the project, where a change that lowers protection waits for your approval. The dashboard does not write such an entry into the file; one the file holds already stays, for whoever does not let its type through.

What a repository file cannot set is ignored: values and patterns never to mask, secret rules turned off, the tools strict data mode covers (data_tools), Latet off, the Live Reviewer, guidance for the local reviewer, whether it sees the images, and the settings of the whole of Latet (port, history, identity…). latet project check and latet project show list what is ignored and why. A repository you clone cannot turn your protection down.

Things to know about the file:

  • It may hold up to 500 terms and 100 recognizers, in at most 256 KB.
  • A file of more than 20,000 YAML entries (keys, values and the lists and mappings around them; about four times what a full file of 500 terms and 100 recognizers holds) is not valid: nothing in it applies, and latet project check says so.
  • A file that cannot be read has no effect, and Latet keeps working.
  • Latet reads the file again when it changes: there is nothing to reload.
  • Terms in the file can be read by everyone who reads the repository. Put your clients’ names in your own settings instead.

latet project check exits with 1 when something in the file is ignored or an example fails, and with 2 when there is no file or it cannot be read, so a CI job can keep the file clean. Its JSON Schema (also latet config schema --project) lets editors complete and check it.

In config.yaml:

projects:
- path: C:\Users\you\dev\acme
terms:
- {value: Acme Logistica, type: CLIENT}
allow_values: [acme-dev]

Latet keeps the folder in canonical form: on Windows with backslashes and an upper-case drive letter, and with no trailing separator (C:/work/shop/ is kept as C:\work\shop). The project’s id does not change.

They apply after the project file, and may also loosen it, in a session whose project Latet trusts:

  • values and patterns never to mask;
  • secret rules turned off;
  • a profile or a policy weaker than the global one;
  • fields kept in clear in strict data mode, strict data mode off (data: normal), images sent, the dump guard raised or off.

The text in images not read there (ocr: off) stops every request with an image in the project.

Only your own settings turn the Live Reviewer on or off in a project (live_review), and give the local reviewer guidance there (review_guidance, see Your guidance).

An entry applies to its folder and to everything in it; when two entries match, the nearer folder wins. latet rules add FILE --project FOLDER adds recognizers to it.

On the project’s Rules page in the dashboard, each list (terms, recognizers, values never to mask, policies) is a table of every rule that applies in the project, each row saying where it comes from: yours, for the project, latet.yaml, or global. A rule is changed where it is born: yours in the project’s tables, the global ones in the global rules (the panel of a global row is read only, with a link there). Add writes to your own settings for the project.

On the project’s Rules page in the dashboard, in the Protection tab, Protection is On, Secrets only or Off. Secrets only masks secrets and your terms there, and lets personal data and your identity through: the secrets profile, in your own settings for the project.

latet project off turns Latet off in the project of the current folder (or of the folder given). So does Protection: Off. Latet then sends none of the project’s requests:

  • each one is refused, over HTTP and over a WebSocket, whether the project is trusted or claimed, with words that say how to turn Latet on there or reach the provider directly (Upgrading to 0.11);
  • latet project off and the switch in the dashboard say so before they turn it off;
  • the dashboard marks those exchanges Latet off.

To let personal data through in a project, choose Secrets only: its requests keep going, with their secrets masked.

latet project on turns it on again. Only your own settings can turn it off, never a project file. Turned off by an agent, or in config.yaml by hand, it waits for your approval in the dashboard first (see Agents and your settings).

Latet remembers the folders of the last 2,000 repositories it has seen with a latet.yaml of their own, in repositories.json in its data folder. A change of config.yaml that would lower protection only where a project file is stricter then waits for your approval, even in a repository no conversation has reached since the daemon started. Their files are read again:

  • at a reload (latet reload, or a command that changes your settings) whose change could lower protection in a repository;
  • at a start that finds config.yaml changed in such a way since the settings you approved last;
  • at an import in the dashboard.

A change of what protects nothing in a project (the port, the history and how long it is kept), or one that only adds protection (a term), reads none. A helper process reads them, with 10 seconds for all of them and 2 for each. A repository that cannot be read now (on a share that does not answer, or a file you may not read) is never taken for one with nothing in it: a change that could lower its protection neither applies nor waits for you, and the reload says so.

To find such a repository, and take it out of the list:

Terminal window
latet repositories # each repository remembered, with its state
latet repositories forget C:\dev\old-app # takes one out of the list

latet repositories shows each one as read, nothing to weigh (not there now, not a regular file, not valid) or unavailable (not readable now, not read in time), never what its file holds. latet repositories forget lowers protection, so it refuses to run in an agent and asks you before it forgets one: run it yourself, in a terminal of your own. The repository is remembered, and weighed again, once a conversation reaches it.

When repositories.json itself cannot be read (a folder, a link or a file larger than the list may be in its place), a change that could lower protection in a repository neither applies nor waits for you, and latet repositories says so. If it stays so, move repositories.json aside, at your own terminal: Latet then remembers repositories again as conversations reach them.

Command What it does
latet project init [FOLDER] [--suggest] Writes a latet.yaml to start from; --suggest adds draft recognizers for the formats no rule covers there
latet project show [FOLDER] [--json] What applies in a project, and what is ignored
latet project check [FOLDER] Checks the project file, recognizers included
latet project off / on [FOLDER] Turns Latet off in a project, where its requests are then refused, or on again
latet repositories The repositories Latet remembers, each with its state
latet repositories forget FOLDER Takes one out of the list (yours alone: it refuses an agent)
latet rules add FILE --repo FOLDER Adds recognizers to the project file instead of config.yaml (--project: to your settings for the project)
latet config schema --project Prints the project file’s JSON Schema
  • The vault is the same for every project. A value masked once, in any project, is masked wherever it appears from then on.
  • Some settings stay global: the port, the history, your identity and Claude Code’s auto mode reviewer.
  • latet rules add --repo rewrites latet.yaml: only its first lines of comments are kept.
  • In Docker:
    • your own settings work, by the folder’s path;
    • the project file is read only when the project’s folder is mounted in the container at the same path.