Help us shape the future of Go! Take the 2026 Go Developer Survey

tenon

module
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 28, 2026 License: EUPL-1.2

README

CI Release Licence EUPL-1.2 Go 1.26 Documentation Made in Europe

tenon

An open-source coding agent for the terminal, built for Europe. It reads your project, proposes changes and runs commands, under your control.

  • European or local models: Mistral AI, Scaleway, OVHcloud, Albert API, Ollama, vLLM. Nothing leaves the EU without your consent.
  • You approve: writes, commands and MCP calls wait for your answer by default.
  • Confined commands: shell commands run in a system sandbox (Landlock, sandbox-exec): project-only writes, no network unless allowed.
  • Classified data stays home: DIFFUSION RESTREINTE content goes only to a local model.
  • Proof, not promises: a hash-chained audit log, RFC 3161 timestamps, and an HTML/JSON report for your DPO.
  • Organisation-ready: signed policies, compliance profiles, a Cyber Resilience Act assistant, CI templates.

Installation

Homebrew (macOS, Linux)
brew install tenon-code-eu/tap/tenon
Install script (Linux, macOS)
curl -fsSL https://raw.githubusercontent.com/tenon-code-eu/tenon/main/install.sh | sh

The script installs the latest version in ~/.local/bin (change the directory with TENON_INSTALL_DIR, pin a version with TENON_VERSION=vX.Y.Z). It always verifies the SHA-256 hash of the archive, and the minisign signature if minisign is installed (TENON_REQUIRE_SIGNATURE=1 makes it mandatory). To install from a mirror (sovereign forge, air-gapped network) instead of GitHub, set TENON_DOWNLOAD_BASE and TENON_VERSION=vX.Y.Z (the version is required). The mirror must serve <base>/<version>/<archive>, <base>/<version>/SHA256SUMS and <base>/<version>/SHA256SUMS.minisig; the base must be https (http is accepted only for localhost and 127.0.0.1). The hash and signature checks are unchanged. Read it before you run it: install.sh.

With Go
go install github.com/tenon-code-eu/tenon/cmd/tenon@latest
Binaries

Each version published on the GitHub Releases page provides:

  • one .tar.gz archive per platform: linux/amd64, linux/arm64, darwin/amd64, darwin/arm64;
  • .deb and .rpm packages for Linux (amd64, arm64);
  • a SHA256SUMS file, signed with minisign (SHA256SUMS.minisig);
  • a CycloneDX SBOM.

Verify the signature with the project's minisign public key, provided at the root of the repository (tenon.pub):

RWR+vfCWjGO42uRKOxNSrKz5afZPCWJf8iJPO04kFdkhLldZHhxo532F

Then verify the hashes:

minisign -Vm SHA256SUMS -p tenon.pub
sha256sum -c SHA256SUMS --ignore-missing   # macOS: shasum -a 256 -c SHA256SUMS --ignore-missing

Then copy the tenon binary to a directory in your PATH, or install the package:

sudo apt install ./tenon_*.deb   # Debian, Ubuntu
sudo dnf install ./tenon_*.rpm   # Fedora, RHEL
From source

You need Go 1.26 or later. Use the latest Go 1.26 patch release (≥ 1.26.10 as of 2026-10-22): earlier ones have known vulnerabilities in the standard library. The dependencies are included in the repository: no module proxy is contacted.

git clone https://github.com/tenon-code-eu/tenon.git
cd tenon
GOFLAGS=-mod=vendor go build -o tenon ./cmd/tenon

Quick start

tenon key set mistral                  # stores the key in the system keyring
tenon                                  # interactive interface, in the project directory
tenon -p "explain the project layout"  # one turn without the interface, for scripts
tenon skills                           # lists the skills found for this project
tenon agents                           # lists the sub-agents found for this project
tenon hooks                            # lists the hooks loaded from your own files
tenon rewind --list --resume last      # lists the restore points of a session

The key can also come from the MISTRAL_API_KEY variable. Without a key, use a local model: tenon --provider ollama.

The interface is in English by default. For French, run with --lang fr or set lang = "fr" in the configuration.

To mark the commits that contain code written by the agent:

tenon git install-hook

Why tenon

tenon Claude Code Aider OpenCode Mistral Vibe
Licence EUPL-1.2 Proprietary Apache-2.0 MIT Apache-2.0
European and local providers built in ✅ — via LiteLLM via 75+ providers Mistral
Consent before data leaves the EU ✅ — — — —
Approval before writes and commands ✅ by default ✅ partial configurable ✅
System sandbox for commands ✅ Landlock, sandbox-exec ✅ bubblewrap, Seatbelt — — via Docker Sandboxes
Classified data kept on a local model ✅ — — — —
Hash-chained, verifiable audit log ✅ — — — —
Compliance report and RFC 3161 timestamps ✅ — — — —
Signed organisation policy ✅ minisign managed settings — — —

“—” means not documented, to our knowledge, on 2026-10-24. Corrections are welcome: open an issue. Sources: Claude Code sandboxing, Aider, OpenCode, Mistral Vibe, Docker Sandboxes for Vibe.

Features

  • the preconfigured providers are European (Mistral AI, Codestral, Scaleway, OVHcloud, Albert API of the French State) or local (Ollama, vLLM);
  • any data sent outside the EU requires your explicit consent;
  • by default, writes, commands and MCP tool calls wait for your approval;
  • everything is recorded in a hash-chained, verifiable audit log;
  • secrets and some personal data are masked before anything is sent;
  • commits that contain code written by the agent can be marked;
  • reusable skills in the open Agent Skills format (SKILL.md), loaded by the model or with /<name>, never able to widen permissions;
  • sub-agents (.claude/agents/*.md format) that the model launches for a self-contained task, with the same permissions, masking and audit as the main agent;
  • hooks (Claude Code format) that run your commands before and after tools, on prompts and at session start and end, to block, ask, add context or change a tool input, without widening permissions; project hooks never run;
  • compliance profiles (eu-only, secnumcloud, strict-local): the provider and MCP servers are checked against the profile at startup and before each send, and the profile is recorded in the audit log; secnumcloud relies on a declared, never verified, qualification; a [provider_allowlist] restricts provider hosts;
  • system sandbox: shell commands and stdio MCP servers are confined by the system (Landlock and user namespaces on Linux, sandbox-exec on macOS): writes limited to the project, credentials directories unreadable, network closed unless a rule or your answer opens it; [sandbox] mode = "required" refuses to run without it (docs/usage.md, limits);
  • data-sensitivity routing: paths and markers (DIFFUSION RESTREINTE, EU RESTRICTED, your own) classify a session as sensitive, and from then on it is sent only to a local model, with an ordered fallback to other providers for the rest; the audit log proves each decision and the export flags any violation (docs/usage.md, limits);
  • signed organisation policy (minisign): an administrator imposes a floor (profile, allowed provider hosts, permission and redaction rules, audit level, MCP servers) that users cannot loosen; it is verified at every startup and recorded in the audit log (docs/policy.md);
  • RFC 3161 timestamping of the audit log: [audit.timestamp] has a timestamp authority sign the head hash, so a log rewritten afterwards is detected by tenon audit verify and by the export (no authority is built in, none is called unless you configure one);
  • governed memory: short notes kept between sessions (project, user, global), written by the model with approval or by you with /remember, loaded on demand from a short index; project entries are loaded only after you approve them on this machine, sensitive entries stay personal, personal entries expire, and tenon memory lists and erases everything (usage guide);
  • token sobriety: measured usage (an estimate, marked, when the provider reports none), a lighter view of the context (deduplication, masking under pressure, head-and-tail truncation) that never changes the history, a session cap with [budget], and small models for compaction and sub-agents ([routing] compaction, subagents); energy and CO2 appear in the export only with factors you declare (usage guide);
  • tenon audit export: an HTML and JSON compliance report built from the audit log (providers, consents, permissions, modified files, incidents), with no conversation data unless you ask for it;
  • Cyber Resilience Act assistant: tenon cra keeps an SBOM, a VEX, reporting deadlines (article 14) and an exportable technical dossier in the repository, with an offline OSV vulnerability scan usable in CI (tenon cra scan --fail-on open) and four built-in skills; nothing is sent to ENISA (docs/cra.md);
  • checkpoints: each prompt is a restore point, and /rewind (or Esc twice) restores the files an agent wrote, the conversation, or both, never overwriting a file you changed without asking.

Any OpenAI-compatible endpoint works. tenon runs on Linux and macOS.

Documentation

License

tenon is distributed under the EUPL-1.2 license.

En français

tenon est un agent de code en terminal, écrit en Go, pour Linux et macOS. Il lit votre projet, propose des modifications et exécute des commandes, sous votre contrôle. Les fournisseurs préconfigurés sont européens (Mistral AI, Codestral, Scaleway, OVHcloud, Albert API de l'État) ou locaux (Ollama, vLLM). Tout envoi hors de l'UE demande votre accord explicite, et tout est tracé dans un journal d'audit chaîné. Par défaut, les écritures, les commandes et les appels d'outils MCP attendent votre validation. Les skills au format ouvert Agent Skills (SKILL.md) sont chargés par le modèle ou avec /<nom>, sans jamais élargir les permissions. Les sous-agents (format .claude/agents/*.md) sont lancés par le modèle pour une tâche autonome, avec les mêmes permissions, le même masquage et le même audit que l'agent principal. Les hooks (format Claude Code) exécutent vos commandes avant et après les outils, à l'envoi d'un prompt et au début et à la fin d'une session, pour bloquer, demander, ajouter du contexte ou modifier l'entrée d'un outil, sans élargir les permissions ; les hooks d'un projet ne s'exécutent jamais. Chaque prompt est un point de restauration : /rewind (ou Échap deux fois) restaure les fichiers écrits par l'agent, la conversation, ou les deux, sans jamais écraser sans demander un fichier que vous avez modifié. Les profils de conformité (eu-only, secnumcloud, strict-local) contrôlent le fournisseur et les serveurs MCP au démarrage et avant chaque envoi, et le profil est enregistré dans le journal d'audit. secnumcloud repose sur une qualification déclarée, jamais vérifiée ; une [provider_allowlist] restreint les hôtes de fournisseurs. L'horodatage RFC 3161 du journal d'audit ([audit.timestamp]) fait signer le hash de tête par une autorité d'horodatage : un journal réécrit ensuite est détecté par tenon audit verify et par l'export. Aucune autorité n'est intégrée, et aucune n'est appelée sans configuration. L'isolation système confine les commandes shell et les serveurs MCP stdio (Landlock et espaces de noms sous Linux, sandbox-exec sous macOS) : écritures limitées au projet, dossiers d'identifiants illisibles, réseau fermé sauf si une règle ou votre réponse l'ouvre ; [sandbox] mode = "required" refuse de s'exécuter sans elle (utilisation, limites). Le routage par sensibilité des données classe une session comme sensible (chemins et marquages comme DIFFUSION RESTREINTE, EU RESTRICTED ou les vôtres) : elle n'est alors envoyée qu'à un modèle local, avec une bascule ordonnée vers d'autres fournisseurs pour le reste ; le journal d'audit prouve chaque décision et l'export signale toute violation (utilisation, limites). Une politique d'organisation signée (minisign) permet à un administrateur d'imposer un socle (profil, hôtes de fournisseurs autorisés, règles de permissions et de masquage, niveau d'audit, serveurs MCP) que les utilisateurs ne peuvent pas assouplir ; elle est vérifiée à chaque démarrage et tracée dans le journal d'audit (politique). La mémoire gouvernée garde de courtes notes entre les sessions (project, user, global), écrites par le modèle avec approbation ou par vous avec /remember, chargées à la demande depuis un court index ; les entrées de projet ne sont chargées qu'après votre approbation sur ce poste, les entrées sensibles restent personnelles, les entrées personnelles expirent et tenon memory permet de tout lister et tout effacer (utilisation). La sobriété en tokens mesure l'usage réel (repli sur une estimation marquée), envoie une vue allégée du contexte (déduplication, masquage sous pression, troncature début-fin) sans jamais modifier l'historique, plafonne la session avec [budget] et peut confier compaction et sous-agents à un petit modèle ([routing] compaction, subagents) ; l'énergie et le CO2 n'apparaissent dans l'export qu'avec des facteurs que vous déclarez (utilisation). tenon audit export produit un rapport de conformité HTML et JSON tiré du journal d'audit (fournisseurs, consentements, permissions, fichiers modifiés, incidents), sans données de conversation sauf si vous les demandez. L'assistant Cyber Resilience Act (tenon cra) tient dans le dépôt une SBOM, un VEX, les échéances de signalement (article 14) et un dossier technique exportable, avec un scan de vulnérabilités OSV hors ligne utilisable en CI (tenon cra scan --fail-on open) et quatre skills intégrés ; rien n'est envoyé à l'ENISA (assistant CRA). L'interface est en anglais par défaut : lancez tenon --lang fr ou mettez lang = "fr" dans la configuration.

Documentation en français : guide d'utilisation, sécurité et limites, politique d'organisation, tenon en CI, assistant CRA.

Directories

Path Synopsis
cmd
tenon command
internal
acp
Package acp implémente l'Agent Client Protocol (JSON-RPC 2.0, un objet JSON par ligne) pour que tenon soit lancé par un éditeur via stdio.
Package acp implémente l'Agent Client Protocol (JSON-RPC 2.0, un objet JSON par ligne) pour que tenon soit lancé par un éditeur via stdio.
agents
Package agents découvre les définitions de sous-agents (fichiers <nom>.md compatibles Claude Code) et construit leur prompt système.
Package agents découvre les définitions de sous-agents (fichiers <nom>.md compatibles Claude Code) et construit leur prompt système.
audit
Package audit writes a hash-chained JSONL audit log and verifies it.
Package audit writes a hash-chained JSONL audit log and verifies it.
checkpoint
Package checkpoint conserve le contenu des fichiers avant que l'agent les écrase, pour /rewind.
Package checkpoint conserve le contenu des fichiers avant que l'agent les écrase, pour /rewind.
classify
Package classify reconnaît les chemins, marqueurs de contenu et commandes shell classifiés (données sensibles) d'après les règles de configuration.
Package classify reconnaît les chemins, marqueurs de contenu et commandes shell classifiés (données sensibles) d'après les règles de configuration.
compliance
Package compliance construit le rapport de conformité à partir du journal d'audit.
Package compliance construit le rapport de conformité à partir du journal d'audit.
config
Package config charge la configuration globale et projet (TOML).
Package config charge la configuration globale et projet (TOML).
cra/dossier
Package dossier lit et écrit le dossier CRA d'un dépôt : cra/product.toml, VEX CycloneDX et signalements, ainsi que le calcul des échéances de signalement.
Package dossier lit et écrit le dossier CRA d'un dépôt : cra/product.toml, VEX CycloneDX et signalements, ainsi que le calcul des échéances de signalement.
cra/osv
Package osv lit la base de vulnérabilités OSV hors ligne (une archive all.zip par écosystème) et rapproche les composants d'un SBOM de ses entrées.
Package osv lit la base de vulnérabilités OSV hors ligne (une archive all.zip par écosystème) et rapproche les composants d'un SBOM de ses entrées.
cra/report
Package report produit le dossier technique CRA exportable (HTML et JSON).
Package report produit le dossier technique CRA exportable (HTML et JSON).
cra/sbom
Package sbom lit les SBOM CycloneDX JSON et analyse les package-URL (purl).
Package sbom lit les SBOM CycloneDX JSON et analyse les package-URL (purl).
cra/scan
Package scan rapproche les composants des SBOM de la base OSV et applique le VEX du dossier.
Package scan rapproche les composants des SBOM de la base OSV et applique le VEX du dossier.
cra/version
Package version compare des versions de composants selon les règles de leur écosystème (semver, PEP 440), pour évaluer les plages de versions OSV.
Package version compare des versions de composants selon les règles de leur écosystème (semver, PEP 440), pour évaluer les plages de versions OSV.
engine
Package engine contient la boucle agentique : il relie le fournisseur, les outils, les permissions, le contrôle sortant et l'audit, et émet des événements typés consommés par les interfaces.
Package engine contient la boucle agentique : il relie le fournisseur, les outils, les permissions, le contrôle sortant et l'audit, et émet des événements typés consommés par les interfaces.
event
Package event defines the session event log model.
Package event defines the session event log model.
frontmatter
Package frontmatter lit l'en-tête YAML minimal des fichiers Markdown (SKILL.md, agents) : scalaires, listes, blocs `>` / `|`.
Package frontmatter lit l'en-tête YAML minimal des fichiers Markdown (SKILL.md, agents) : scalaires, listes, blocs `>` / `|`.
gitmark
Package gitmark marque les commits qui contiennent du code écrit par l'agent : des trailers git (AI-Assisted-By, AI-Session) sont ajoutés au message par un hook commit-msg qui ne bloque jamais le commit.
Package gitmark marque les commits qui contiennent du code écrit par l'agent : des trailers git (AI-Assisted-By, AI-Session) sont ajoutés au message par un hook commit-msg qui ne bloque jamais le commit.
hooks
Package hooks charge, filtre et exécute les hooks utilisateur, au format compatible avec les hooks de Claude Code.
Package hooks charge, filtre et exécute les hooks utilisateur, au format compatible avec les hooks de Claude Code.
hostmatch
Package hostmatch porte la correspondance d'hôtes partagée par la politique d'organisation et la liste blanche de fournisseurs : hôte exact ou joker strict "*.x.eu" (sous-domaines uniquement, jamais "x.eu").
Package hostmatch porte la correspondance d'hôtes partagée par la politique d'organisation et la liste blanche de fournisseurs : hôte exact ou joker strict "*.x.eu" (sous-domaines uniquement, jamais "x.eu").
i18n
Package i18n fournit les chaînes FR/EN de la CLI, du mode headless et du prompt système.
Package i18n fournit les chaînes FR/EN de la CLI, du mode headless et du prompt système.
instructions
Package instructions charge AGENTS.md et TENON.md depuis la racine du projet pour les injecter dans le prompt système.
Package instructions charge AGENTS.md et TENON.md depuis la racine du projet pour les injecter dans le prompt système.
llm
Package llm defines the provider-neutral types exchanged with LLM backends.
Package llm defines the provider-neutral types exchanged with LLM backends.
mcp
Package mcp connecte tenon à des serveurs MCP (stdio et HTTP streamable) et expose leurs outils comme des tools.Tool.
Package mcp connecte tenon à des serveurs MCP (stdio et HTTP streamable) et expose leurs outils comme des tools.Tool.
mcp/mcptest
Package mcptest fournit le serveur MCP stdio des tests : le binaire de test relancé avec EnvServer=1 joue un serveur selon EnvMode.
Package mcptest fournit le serveur MCP stdio des tests : le binaire de test relancé avec EnvServer=1 joue un serveur selon EnvMode.
memory
Package memory range les entrées de mémoire gouvernée : un fichier Markdown à frontmatter par entrée, dans trois portées (project, user, global).
Package memory range les entrées de mémoire gouvernée : un fichier Markdown à frontmatter par entrée, dans trois portées (project, user, global).
orgpolicy
Package orgpolicy charge, vérifie et applique la politique d'organisation signée (policy.toml + signature minisign).
Package orgpolicy charge, vérifie et applique la politique d'organisation signée (policy.toml + signature minisign).
orgpolicy/orgpolicytest
Package orgpolicytest fournit des aides de test : génération d'une clé Ed25519 éphémère et écriture d'une politique signée au format minisign.
Package orgpolicytest fournit des aides de test : génération d'une clé Ed25519 éphémère et écriture d'une politique signée au format minisign.
policy
Package policy contient le moteur de permissions : chaque appel d'outil y est vérifié avant exécution.
Package policy contient le moteur de permissions : chaque appel d'outil y est vérifié avant exécution.
profile
Package profile porte les règles des profils de conformité (eu-only, secnumcloud, strict-local).
Package profile porte les règles des profils de conformité (eu-only, secnumcloud, strict-local).
provider
Package provider talks to LLM backends over HTTP.
Package provider talks to LLM backends over HTTP.
routing
Package routing ordonne les fournisseurs candidats et décide quelles erreurs déclenchent un repli.
Package routing ordonne les fournisseurs candidats et décide quelles erreurs déclenchent un repli.
safefile
Package safefile lit des fichiers réguliers de façon sûre (sans suivre de lien symbolique ni bloquer sur un FIFO).
Package safefile lit des fichiers réguliers de façon sûre (sans suivre de lien symbolique ni bloquer sur un FIFO).
sandbox
Package sandbox confine les commandes shell et les serveurs MCP stdio : écriture limitée à une liste de chemins, lecture interdite sur les secrets, réseau coupé par défaut.
Package sandbox confine les commandes shell et les serveurs MCP stdio : écriture limitée à une liste de chemins, lecture interdite sur les secrets, réseau coupé par défaut.
secrets
Package secrets recherche les clés API des fournisseurs : d'abord dans l'environnement, puis dans le trousseau système (Keychain sur macOS, Secret Service sur Linux).
Package secrets recherche les clés API des fournisseurs : d'abord dans l'environnement, puis dans le trousseau système (Keychain sur macOS, Secret Service sur Linux).
session
Package session persists a session's events as redacted JSONL and reloads them.
Package session persists a session's events as redacted JSONL and reloads them.
skills
Package skills découvre et charge les skills au format Agent Skills (SKILL.md).
Package skills découvre et charge les skills au format Agent Skills (SKILL.md).
tools
Package tools définit l'interface des outils de l'agent et les outils fichiers.
Package tools définit l'interface des outils de l'agent et les outils fichiers.
tsp
Package tsp décode et vérifie les jetons d'horodatage RFC 3161 (TSA), avec la seule bibliothèque standard.
Package tsp décode et vérifie les jetons d'horodatage RFC 3161 (TSA), avec la seule bibliothèque standard.
tsp/tsptest
Package tsptest fournit une fausse TSA RFC 3161 pour les tests : une CA et des signataires générés au test, de vrais jetons signés (ECDSA P-256 ou RSA 2048), des altérations ciblées et un serveur httptest.
Package tsptest fournit une fausse TSA RFC 3161 pour les tests : une CA et des signataires générés au test, de vrais jetons signés (ECDSA P-256 ou RSA 2048), des altérations ciblées et un serveur httptest.
ui/headless
Package headless exécute un tour d'agent sans interface interactive : toute demande de permission est refusée, la sortie est du texte ou du JSON.
Package headless exécute un tour d'agent sans interface interactive : toute demande de permission est refusée, la sortie est du texte ou du JSON.
ui/tui
Package tui contient l'interface interactive de tenon.
Package tui contient l'interface interactive de tenon.
ui/tui/diff
Package diff calcule l'aperçu des modifications affiché par la TUI avant qu'une écriture (write_file / edit_file) soit approuvée.
Package diff calcule l'aperçu des modifications affiché par la TUI avant qu'une écriture (write_file / edit_file) soit approuvée.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL