Vibe — Architecture Documentation

1. Introduction and Goals

Vibe is Mistral’s minimal CLI coding agent: a terminal coding assistant that gives a conversational interface to a codebase, powered by Mistral’s models [pyproject.toml:5, README.md:20-22]. It ships two entry points — vibe/ (an interactive Textual TUI, also runnable non-interactively) and vibe-acp (an Agent Client Protocol server for editors and IDEs) [pyproject.toml:143-144].

1.1. Requirements Overview

The system lets a developer explore, modify and run a project through natural language, backed by a safe tool suite [README.md:92-109]. Its core capabilities:

The full functional specification — persona use cases and per-interface system use cases — is in ../../use-cases-vibe.adoc; the product framing is in ../../prd-vibe.adoc.

1.2. Quality Goals

The quality goals below are inferred from the emphasis the code and README place on them. The code cannot rank the eight ISO/IEC 25010 characteristics, so both the selection of these as the top goals and their priority ranking could not be recovered from code and are deferred — the Product Owner and Architect must confirm them before they can drive trade-off decisions.

Quality Goal Motivation Chapter 4 Approach

Security / Safety

"Safety first" is an explicit README theme; tool execution is gated by a tiered permission system and a trust-folder gate [README.md:108, vibe/core/tools/base.py:83-113, vibe/core/trusted_folders.py:75-122].

Tiered tool permissions, trust gate, workdir boundary (see Solution Strategy).

Usability

A rich Textual TUI, a first-run onboarding wizard and autocompletion target a low-friction developer experience [vibe/cli/textual_ui/app.py:327-348, vibe/setup/onboarding/screens/welcome.py:46-80].

Textual TUI, onboarding wizard, slash-command and path autocompletion.

Maintainability

Strict pyright and ruff gate CI; hexagonal ports decouple the engine from adapters [AGENTS.md:24-69, vibe/core/llm/backend/base.py:13-126].

Hexagonal ports/adapters, strict static analysis, test doubles.

Compatibility

The agent works against multiple LLM providers and integrates the MCP and ACP protocols and the agentskills.io standard [vibe/core/llm/backend/factory.py:7, vibe/acp/entrypoint.py:78].

LLM backend factory, MCP registry, ACP bridge.

Reliability

The LLM call retries with backoff and the loop recovers from context overflow and user interruption [vibe/core/llm/backend/mistral.py:212-222, vibe/core/agent_loop.py:1681-1749].

Retry/backoff, middleware limits, auto-compaction recovery.

Note
Chapter 10 covers all eight ISO/IEC 25010 characteristics in its quality tree and gives measurable six-part scenarios for the characteristics that concretise these top goals; this section names only the top goals that drive architecture decisions.

1.3. Stakeholders

Role Contact Expectations

Interactive developer

(team to supply)

A trustworthy conversational agent that explores and edits the codebase with explicit approval [vibe/cli/textual_ui/app.py:322].

Scripter / CI automation

(team to supply)

Deterministic non-interactive runs with turn and cost ceilings and machine-readable output [vibe/core/programmatic.py:27].

Editor / IDE integrator

(team to supply)

A stable ACP server to embed the agent in an editor [vibe/acp/entrypoint.py:78-108].

Product Owner

(team to supply)

Owns the deferred business questions: why Vibe was built, success KPIs, and segment priority.

Note
Open issues — deferred to the team

The following could not be recovered from code and are deferred:

  • The business rationale for building an open-source CLI agent and its relation to the paid Mistral Code / Vibe Code offering.

  • The success KPI (adoption, retention, task-completion, conversion).

  • Which user segment — interactive, programmatic or ACP — is the priority.

  • The selection and priority ranking of the quality goals above.

2. Architecture Constraints

2.1. Technical Constraints

Constraint Evidence / Rationale

Python >= 3.12

requires-python = ">=3.12" [pyproject.toml:6]; pinned in .python-version.

uv is the package and run manager

All commands go through uv; bare python/pip are forbidden [AGENTS.md:7-12].

Strict static typing

Pyright runs in strict mode and gates CI; no inline # type: ignore [AGENTS.md:24-46].

Ruff lint and format gate every change

ruff check and ruff format run after every code change [AGENTS.md:9-10].

No relative imports

ban-relative-imports = "all"; always from vibe.core.x import … [AGENTS.md:48-50].

asyncio is the orchestration runtime

The agent loop and tool execution are async; streaming surfaces return AsyncGenerator [AGENTS.md:62-69].

UNIX is the supported target

Vibe runs on Windows but UNIX environments are the officially supported and targeted platform [README.md:24-26].

2.2. Organisational and Convention Constraints

Constraint Evidence / Rationale

Hexagonal module conventions

Abstract interfaces use the port.py suffix; private modules are -prefixed; Pydantic models live in models.py [AGENTS.md:13-23].

Pydantic for all external data

External data is parsed via model_validate / validators, never ad-hoc getattr/hasattr [AGENTS.md:53-61].

Conventional Commits, no force-push

git commit --amend, git push --force and force-with-lease are forbidden; rebase, never merge, on rejected push [AGENTS.md:81-86].

Apache-2.0 licence

The project is licensed Apache-2.0 [pyproject.toml:7, LICENSE].

2.3. Conventions

Documentation follows Docs-as-Code with AsciiDoc built by docToolchain; this architecture document is the arc42 template filled in place. Code conventions are recorded in AGENTS.md at the repository root and are binding for both human and AI contributors [AGENTS.md:1-12].

3. Context and Scope

Vibe is a client-side tool that runs on the developer’s machine. The system boundary in this chapter is the same one used in Building Block View: the building blocks there are internal to this boundary, the systems below sit outside it.

3.1. Business Context

context business

The developer states a coding goal; Vibe turns it into LLM calls and tool executions and reports the result. A scripter drives the same engine non-interactively. An integrator embeds the agent in an editor through the ACP server. The LLM Provider supplies the agent’s reasoning; Vibe Code / Nuage optionally continues a session in the cloud [vibe/core/programmatic.py:27, vibe/acp/entrypoint.py:78-108, vibe/core/teleport/teleport.py:46-150].

3.2. Technical Context

context technical
External System Channel Code Evidence

LLM Provider API

HTTPS (Mistral SDK or generic HTTP)

vibe/core/llm/backend/factory.py:1-7, vibe/core/llm/backend/mistral.py:268-335

Mistral Datalake

HTTPS POST to api.mistral.ai/v1/datalake/events

vibe/core/telemetry/send.py:30-31

GrowthBook

HTTPS POST to the eval endpoint; fails open on error

vibe/core/experiments/client.py:17-81

MCP Servers

http, streamable-http or stdio

vibe/core/tools/mcp/registry.py:80-150

Vibe Code / Nuage

HTTPS + Server-Sent Events

vibe/core/nuage/client.py:22-100, vibe/core/nuage/remote_events_source.py:33-120

GitHub

OAuth device flow; release lookups

vibe/core/auth/github.py:117-184, vibe/cli/update_notifier/adapters/github_update_gateway.py

PyPI

HTTPS version lookup, cached 24 h

vibe/cli/update_notifier/adapters/pypi_update_gateway.py, vibe/cli/update_notifier/update.py:82

4. Solution Strategy

The table maps each Chapter 1 quality goal to the concrete approach the code uses to reach it. The approaches themselves are visible in code; the reason each was chosen over alternatives is deferred — recorded as Architecture Decisions in Architecture Decisions with status "Accepted (inferred)".

Quality Goal Approach in the code

Security / Safety

Every tool call resolves to a permission tier — ALWAYS / ASK / NEVER — before it runs; file tools enforce a working-directory boundary; a folder must be trusted before its project config loads [vibe/core/tools/base.py:83-113, vibe/core/tools/utils.py:64-125, vibe/core/trusted_folders.py:75-122]. The active agent profile (plan, accept-edits, auto-approve) bounds how much the agent may do without asking [vibe/core/agents/models.py:110-199].

Usability

A Textual TUI renders the conversation with key bindings, slash commands and @-path / /-command autocompletion; a first-run wizard handles API-key setup [vibe/cli/textual_ui/app.py:327-348, vibe/cli/commands.py:39, vibe/setup/onboarding/screens/welcome.py:46-80].

Maintainability

The engine is structured as hexagonal ports (*_port.py) with adapters at the edges, so LLM providers, audio, TTS and gateways are swappable; strict pyright and ruff gate every change [vibe/core/llm/backend/base.py:13-126, AGENTS.md:24-69].

Compatibility

An LLM backend factory selects a provider-specific backend, and API-style adapters cover OpenAI, Anthropic and Vertex shapes; an MCP registry and the vibe-acp server integrate the MCP and ACP protocols [vibe/core/llm/backend/factory.py:7, vibe/core/llm/format.py:58-185, vibe/core/tools/mcp/registry.py:21].

Reliability

The Mistral backend retries with exponential backoff; a middleware pipeline enforces turn and price limits and triggers auto-compaction when the context nears the model threshold; user interruption cancels in-flight tool tasks cleanly [vibe/core/llm/backend/mistral.py:212-222, vibe/core/middleware.py:49-96, vibe/core/agent_loop.py:1244-1259].

4.1. Key architectural patterns

5. Building Block View

5.1. Whitebox Overall System

bbv level1
Motivation

The system separates the two front ends (CLI, ACP) and the first-run wizard (Setup) from a shared core engine. Inside the engine the Agent Loop is the orchestrator; the Tool Subsystem, LLM Backend Layer, Config Subsystem and Session Persistence are the capabilities it composes. The Remote block is an optional path that hands a session off to the cloud.

Contained Building Blocks

The nine blocks below. The external systems are the same set named in Context and Scope.

Important Interfaces

AgentLoop.act() is the engine’s entry point; BackendLike is the LLM port; BaseTool.run() is the tool contract; ConfigOrchestrator builds configuration.

5.1.1. Agent Loop

Responsibility: Orchestrate one conversation turn — run middleware, call the LLM, parse and execute tool calls concurrently, update stats, repeat until the assistant emits no tool call.
Interface: AgentLoop.act() [vibe/core/agent_loop.py:632-649].
Source: vibe/core/agent_loop.py, vibe/core/loop.py, vibe/core/middleware.py.
Runtime scenarios: all of Runtime View.

5.1.2. LLM Backend Layer

Responsibility: Present a uniform BackendLike protocol — complete, complete_streaming, count_tokens — over Mistral and OpenAI-compatible providers, with API-style adapters for OpenAI, Anthropic and Vertex.
Interface: BackendLike [vibe/core/llm/backend/base.py:13-126], selected by BACKEND_FACTORY [vibe/core/llm/backend/factory.py:7].
Source: vibe/core/llm/.
Runtime scenarios: Conversation Turn, LLM Rate-Limit.

5.1.3. Tool Subsystem

Responsibility: Discover, filter, instantiate and permission-check tools — builtin, MCP and connector — and expose them to the loop.
Interface: ToolManager.available_tools / .get() [vibe/core/tools/manager.py:72-447]; BaseTool.run() [vibe/core/tools/base.py:122-152].
Source: vibe/core/tools/.
Runtime scenarios: Conversation Turn, Tool Approval.

5.1.4. Config Subsystem

Responsibility: Discover config layers (project .vibe/ then ~/.vibe/), merge them field-by-field into a validated VibeConfig.
Interface: ConfigOrchestrator [vibe/core/config/orchestrator.py:10-46].
Source: vibe/core/config/, vibe/core/paths/.
Runtime scenarios: Startup & Resume.

5.1.5. Session Persistence

Responsibility: Persist a session as meta.json + messages.jsonl, load and migrate past sessions, support --continue/--resume and rewind-to-message.
Interface: SessionLogger, SessionLoader, RewindManager [vibe/core/session/session_logger.py:36-97, vibe/core/rewind/manager.py:35-165].
Source: vibe/core/session/, vibe/core/rewind/.
Runtime scenarios: Startup & Resume, Context Auto-Compaction.

5.1.6. CLI / Textual UI

Responsibility: Render the interactive chat TUI, route key bindings, dispatch the 23 slash commands; also host the non-interactive runner.
Interface: VibeApp [vibe/cli/textual_ui/app.py:322-558]; run_programmatic() [vibe/core/programmatic.py:27].
Source: vibe/cli/.
Runtime scenarios: Conversation Turn, Tool Approval, User Interruption.

5.1.7. ACP Bridge

Responsibility: Expose the engine over the Agent Client Protocol, with ACP-specific tools that delegate file and terminal operations to the ACP client.
Interface: VibeAcpAgentLoop [vibe/acp/acp_agent_loop.py:267-289].
Source: vibe/acp/.
Runtime scenarios: ACP Session.

5.1.8. Remote (Teleport + Nuage)

Responsibility: Validate the git repo, ensure the commit is pushed, start a remote Vibe Code workflow, and stream its events back.
Interface: TeleportService, WorkflowsClient, RemoteEventsSource [vibe/core/teleport/teleport.py:46-150, vibe/core/nuage/remote_events_source.py:33-120].
Source: vibe/core/teleport/, vibe/core/nuage/.
Runtime scenarios: Teleport to Cloud.

5.1.9. Setup / Onboarding

Responsibility: Walk a first-run user through Welcome → auth-method → (browser sign-in or manual API key) and persist the key.
Interface: OnboardingScreen flow [vibe/setup/onboarding/base.py:6-14].
Source: vibe/setup/.
Runtime scenarios: First-Run Onboarding.

5.2. Level 2 — White Box: Tool Subsystem

bbv tools

The ToolManager scans search paths for BaseTool subclasses and merges in MCP and connector proxy tools [vibe/core/tools/manager.py:120-383]. Each tool declares a BaseToolConfig permission tier; before execution the loop resolves a PermissionContext and consults the PermissionStore for session-remembered approvals [vibe/core/tools/base.py:83-113, vibe/core/tools/permissions.py:47-68]. The numeric limits each builtin tool enforces are listed as system use cases in ../../use-cases-vibe.adoc and as quality scenarios in Quality Requirements.

6. Runtime View

Nine scenarios cover the system at runtime. Three are error or recovery scenarios: Context Auto-Compaction, User Interruption and LLM Rate-Limit. Together the scenarios exercise every building block from Building Block View.

6.1. Startup and Session Resume

On launch the front end resolves the working directory and trust, builds configuration, then either starts fresh or restores a past session.

6.2. Conversation Turn (happy path)

rt turn

_conversation_loop appends the user message, runs the middleware pipeline, performs the LLM turn, and executes any tool calls as concurrent asyncio tasks before looping again [vibe/core/agent_loop.py:855-937, vibe/core/agent_loop.py:1217-1259].

6.3. Tool Approval Interception

Before a tool runs, _execute_tool_call resolves its permission. An ASK tier invokes the approval callback into the UI; a rejection increments tool_calls_rejected and feeds a rejection result back to the LLM so the conversation continues [vibe/core/agent_loop.py:1071-1167, vibe/core/tools/permissions.py:47-68]. Approved patterns are remembered in the PermissionStore for the rest of the session.

6.4. Context Auto-Compaction (recovery scenario)

rt compact

When context_tokens crosses the model’s auto_compact_threshold, AutoCompactMiddleware returns COMPACT; the loop summarises the history into [system, summary], forks to a new session id linked to its parent, and recounts tokens [vibe/core/middleware.py:81-96, vibe/core/agent_loop.py:1681-1749].

6.5. User Interruption (error / recovery scenario)

rt interrupt

Escape raises a user-cancellation event; in-flight tool tasks receive asyncio.CancelledError, the cancellation is recorded as a tool result, and the loop breaks without corrupting the message history [vibe/core/agent_loop.py:897-906, vibe/core/agent_loop.py:1170-1178, vibe/core/agent_loop.py:1244-1259].

6.6. LLM Rate-Limit / Context-Too-Long (error scenario)

_chat catches rate-limit and context-too-long errors raised by the LLM Backend Layer and surfaces them distinctly; the Mistral backend retries transient failures with exponential backoff before the error propagates; the ACP Bridge maps a context-too-long failure to a JSON-RPC ContextTooLongError [vibe/core/agent_loop.py:1365-1374, vibe/core/llm/backend/mistral.py:212-222, vibe/acp/exceptions.py:107].

6.7. Teleport to Cloud

/teleport (gated by plan eligibility) validates the git repository, confirms the working commit is pushed, then starts a remote Vibe Code workflow; RemoteEventsSource attaches and streams the cloud workflow’s events back into the UI [vibe/core/teleport/teleport.py:46-150, vibe/core/teleport/git.py:27-100, vibe/core/nuage/remote_events_source.py:33-120].

6.8. ACP Session

vibe-acp runs VibeAcpAgentLoop, the ACP agent (see Building Block View), as an ACP agent over stdio. The agent holds one AcpSessionLoop per ACP session: new_session creates a fresh AcpSessionLoop with the default agent; load_session replays a past conversation. ACP-specific tools delegate file and terminal operations to the connected ACP client [vibe/acp/session.py:11, vibe/acp/acp_agent_loop.py:614-648, vibe/acp/acp_agent_loop.py:869-920, vibe/acp/tools/base.py:13-54].

6.9. First-Run Onboarding

When no API key is configured, the Setup block walks the user through Welcome → auth-method → browser sign-in or manual API key, then persists the key to ~/.vibe/.env (or keyring) [vibe/setup/onboarding/screens/welcome.py:46-80, vibe/setup/auth/api_key_persistence.py:38-64].

7. Deployment View

7.1. Infrastructure Level 1

deploy level1
Motivation

Vibe is a client-side tool. The only "deployment" is the package installed on the developer’s machine; there is no server component owned by this bounded context. All server-side systems are external (Context and Scope).

Quality and/or Performance Features

The process is single-user and single-process. State lives under ~/.vibe/ (overridable with VIBE_HOME): config.toml, .env, session logs, the trust list, plans and the update cache [vibe/core/paths/_vibe_home.py:19-36].

Mapping of Building Blocks to Infrastructure

All nine building blocks run inside the single vibe/ (or vibe-acp) process on the developer machine. The Remote block additionally talks to the Vibe Code / Nuage cloud.

7.2. Infrastructure Level 2 — Distribution channels

Channel Evidence

PyPI package mistral-vibe, installed via uv tool install or pip

README.md:45-55, pyproject.toml:143-144

One-line scripts/install.sh (Linux / macOS)

README.md:27-33

Standalone binary built with PyInstaller

vibe-acp.spec, pyinstaller/runtime_hook_truststore.py, .github/workflows/build-and-upload.yml

Packaged GitHub Action (uv sync + uv run vibe/ -p)

action.yml:1-60

Zed editor extension

distribution/zed/extension.toml

Releases are cut by the .github/workflows/release.yml workflow; CI runs in .github/workflows/ci.yml [.github/workflows/].

8. Cross-cutting Concepts

8.1. Threat Model (STRIDE)

Warning

No STRIDE threat model exists in the code base. The threats below are candidate threats, derived in Phase 2 from the code-visible risk surfaces (see Risks and Technical Debts). The completeness of this catalogue and the validation of each threat are deferred to the Architect and Operations — see ADR review and OPEN_QUESTIONS.adoc.

T-ID STRIDE Candidate Threat Risk

T-001

Tampering, Elevation

The LLM emits a destructive shell command and bash runs it [vibe/core/tools/builtins/bash.py:480-530].

R-001

T-002

Information Disclosure

A file tool reads a secret file such as .env [vibe/core/tools/builtins/read_file.py:60-66].

R-002

T-003

Tampering

A file write or patch lands outside the working directory [vibe/core/tools/utils.py:64-125].

R-003

T-004

Information Disclosure

webfetch is pointed at an internal/loopback URL (SSRF) [vibe/core/tools/builtins/webfetch.py:62-119].

R-002

T-005

Elevation of Privilege

An untrusted project’s .vibe/ config (tools, hooks, agents) executes on first entry [vibe/core/trusted_folders.py:19-32].

R-004

T-006

Spoofing, Information Disclosure

The Mistral API key leaks from disk [vibe/setup/auth/api_key_persistence.py:14-16].

R-005

T-007

Tampering

A malicious hook command runs as a shell subprocess [vibe/core/hooks/executor.py:11-55].

R-006

8.2. Security

Every mitigation references the T-IDs it closes.

Mechanism Description Closes

Tiered tool permissions

Each tool resolves to ALWAYS / ASK / NEVER; ASK prompts the user before executing [vibe/core/tools/base.py:83-113].

T-001, T-004

Command allow/deny lists + arity

bash matches command prefixes against allow/deny lists; sudo always asks [vibe/core/tools/builtins/bash.py:228-243, vibe/core/tools/arity.py:145-158].

T-001

Sensitive-pattern gating

File and search tools treat */.env as sensitive and force an approval prompt [vibe/core/tools/builtins/read_file.py:60-63].

T-002

Working-directory boundary

File tools require paths inside the working directory (or an --add-dir root); otherwise an extra approval is required [vibe/core/tools/utils.py:64-125].

T-003

Trust-folder gate

A folder containing .vibe//AGENTS.md triggers a trust prompt; untrusted folders do not load project config [vibe/core/trusted_folders.py:75-122].

T-005

Secret storage

API keys are stored in ~/.vibe/.env or the OS keyring; encrypted payloads use RSA-OAEP-SHA256 + AES-256-GCM; browser sign-in uses PKCE [vibe/core/auth/crypto.py:13-137, vibe/setup/auth/browser_sign_in.py:173-184].

T-006

Read-only agent profiles

The plan and chat profiles are read-only, enforced by ReadOnlyAgentMiddleware [vibe/core/middleware.py:174-216] — see ADR-003.

T-001, T-003

Experimental-hooks gate

Hooks are disabled unless enable_experimental_hooks is set, so a project’s hook commands do not run as shell subprocesses by default [vibe/core/config/_settings.py:534, vibe/core/hooks/config.py:78].

T-007

8.3. Test

The test concept is a pytest suite (pytest + pytest-asyncio
respx + pytest-textual-snapshot) with test doubles named Fake* in tests/stubs/ [AGENTS.md:84-92]. CI runs the suite plus strict pyright and ruff [.github/workflows/ci.yml].

Warning

Tests are not traced to use cases or business rules, and the pyramid shape (unit / integration / end-to-end proportions) is not declared. Establishing per-use-case traceability — each test naming the ../use-cases-vibe.adoc use case it covers — is deferred to the Developer.

8.4. Observability

  • Tracing. OpenTelemetry spans wrap the agent invocation and each tool execution, with the conversation id propagated as OTEL baggage; the OTLP exporter is enabled only when telemetry and OTEL config are present [vibe/core/tracing.py:23-137].

  • Logging. Structured stdlib logging writes to ~/.vibe/logs/vibe.log; level and rotation size are env-configurable [AGENTS.md:68-69].

  • Usage telemetry. Usage events go to the Mistral datalake, gated by enable_telemetry and the presence of an API key [vibe/core/telemetry/send.py:58-95].

  • ACP message log. When VIBE_ACP_LOGGING_ENABLED is set, every ACP protocol message is recorded [vibe/acp/acp_logger.py:17-59].

8.5. Error Handling

8.6. Configuration

Configuration is layered and merge-aware: project .vibe/config.toml directories are walked breadth-first (up to four levels) and then the user ~/.vibe/config.toml layer is applied; layers merge field-by-field with declared strategies (replace, concat, union, shallow, conflict) [vibe/core/config/builder.py:24-122, vibe/core/paths/_local_config_walk.py:132-168]. VIBE_HOME relocates the entire user state directory [vibe/core/paths/_vibe_home.py:19-25]. This concept is listed because the system genuinely has a configuration concern that crosses every building block.

9. Architecture Decisions

The decisions below are recovered from code. The rationale — why each was chosen over alternatives — could not be recovered, so each ADR has status Accepted (inferred) and its Pugh Matrix marks team-judgment cells with ?. The full ADRs are in the register at ../../adrs/.

9.1. ADR Index

ADR Title Status

ADR-001

Hexagonal Ports and Adapters

Accepted (inferred)

ADR-002

Pluggable LLM Backend Abstraction

Accepted (inferred)

ADR-003

Conversation Middleware Pipeline

Accepted (inferred)

ADR-004

File-based Session Persistence

Accepted (inferred)

9.2. Summary

ADR-001 — Hexagonal Ports and Adapters. The engine isolates the domain behind *_port.py interfaces with adapters at the edges [AGENTS.md:13-23]. Concretised in Cross-cutting Concepts (Configuration, Observability).

ADR-002 — Pluggable LLM Backend Abstraction. BACKEND_FACTORY maps a provider enum to a backend, and API-style adapters cover OpenAI, Anthropic and Vertex shapes [vibe/core/llm/backend/factory.py:7, vibe/core/llm/format.py:58-185]. Concretised by the Compatibility goal in Solution Strategy.

ADR-003 — Conversation Middleware Pipeline. A before_turn pipeline enforces turn/price limits, auto-compaction and read-only agent modes [vibe/core/middleware.py:218-247]. Concretised by the Security and Reliability mechanisms in Cross-cutting Concepts.

ADR-004 — File-based Session Persistence. Sessions persist as a folder of meta.json + messages.jsonl, with a v1→v2 migration in code [vibe/core/session/session_logger.py:62-97, vibe/core/session/session_migration.py:16-41].

Note

The "why" behind all four decisions is deferred to the Architect (see OPEN_QUESTIONS.adoc). Until answered, the inferred status and the ? cells in each Pugh Matrix must not be read as confirmed rationale.

10. Quality Requirements

10.1. Quality Requirements Overview

The quality tree covers all eight ISO/IEC 25010 characteristics. Each is marked either as concretising a Chapter 1.2 top goal or as derived (a quality requirement visible in code but not among the top goals).

Characteristic Relation to Chapter 1.2 Note

Security

Concretises Security / Safety

Permission tiers, trust gate, secret storage.

Usability

Concretises Usability

TUI, onboarding, autocompletion.

Maintainability

Concretises Maintainability

Hexagonal ports, strict static analysis.

Compatibility

Concretises Compatibility

Multi-provider, MCP, ACP.

Reliability

Concretises Reliability

Retry, limits, recovery.

Functional Suitability

Derived

Tool suite + agent loop deliver the stated function.

Performance Efficiency

Derived

Concurrent tools, streaming, bounded I/O.

Portability

Derived

Cross-platform; UNIX is the supported target.

Warning

Both the selection of the Chapter 1.2 top goals — and therefore the concretises / derived split in the table above — and the priority ranking of the quality goals are deferred to the Product Owner and Architect: the code cannot rank the eight ISO/IEC 25010 characteristics (Question Tree Q4.9). The scenarios below are testable on their own, but which to favour when they conflict is an unresolved decision.

10.2. Quality Scenarios

Each scenario is in the six-part form. Every response measure is recovered from code — a literal figure where the code defines one, otherwise the observable outcome (a clean cancellation, the model-supplied compaction threshold) — so the requirement is testable.

Source Stimulus Artifact Environment Response Response Measure

LLM

Emits a shell command

bash tool

Interactive session, default agent

Tool prompts for approval, then runs the command with a timeout

Default timeout 300 s (overridable); stdout+stderr captured to a 16 000-byte cap [vibe/core/tools/builtins/bash.py:222-226] — Security.

LLM

Requests a code search

grep tool

Large repository

Search returns within the timeout, capped

Timeout 60 s; at most 100 matches and 64 000 output bytes [vibe/core/tools/builtins/grep.py:43-51] — Performance Efficiency.

LLM

Reads a large file

read_file tool

Any session

File content is returned truncated, with was_truncated set

Read cap 64 000 bytes per call [vibe/core/tools/builtins/read_file.py:65-66] — Performance Efficiency.

Conversation

Context tokens approach the model limit

Agent Loop + compaction

Long interactive session

History is summarised and the session forks

Triggered at the model’s auto_compact_threshold; a warning is injected at 50 % of that threshold [vibe/core/middleware.py:81-126] — Reliability.

LLM Provider

Returns a transient error

Mistral backend

Network instability

The request is retried with exponential backoff

500 ms initial delay, 1.5x exponent, 300 s cap [vibe/core/llm/backend/mistral.py:212-222] — Reliability.

MCP Server

Is slow to start or respond

MCP registry

External tool provider configured

Startup and per-call are bounded by timeouts

Startup 10 s, tool call 60 s (defaults) [vibe/core/config/_settings.py:231-237] — Compatibility.

Developer

Presses Escape mid-turn

Agent Loop

Tool tasks running

In-flight tool tasks are cancelled and the turn ends cleanly

All running tasks receive CancelledError; no partial message is persisted [vibe/core/agent_loop.py:1244-1259] — Reliability.

Hook author

Configures a slow hook

Hooks manager

POST_AGENT_TURN event

The hook is killed on timeout and retried a bounded number of times

Default timeout 30 s; at most 3 retries [vibe/core/hooks/models.py:30, vibe/core/hooks/manager.py:28] — Reliability.

Maintainer

Submits a code change

CI pipeline

Pull request

Pyright (strict) and ruff must pass before merge

Zero type errors, zero lint errors [AGENTS.md:24-46] — Maintainability.

11. Risks and Technical Debts

11.1. Risks

Risks are ordered by priority (highest first). Priority is derived from probability × impact. The probability and impact values are inferred in Phase 2 and must be confirmed by a security review — see ADR review and OPEN_QUESTIONS.adoc (Q3.8.1).

ID Risk Prob. Impact Priority Mitigation

R-007

No STRIDE threat model backs the security mechanisms, so threat completeness is unverified (no code evidence — deferred).

High

Medium

High

Author a STRIDE threat model (deferred — Architect, Operations). The candidate threats T-001..T-007 in Cross-cutting Concepts are the starting point.

R-001

The LLM emits a destructive shell command and bash executes it (threat T-001).

Medium

High

High

Tiered tool permissions + command allow/deny lists (Cross-cutting Concepts Security); bash timeout scenario in Quality Requirements.

R-004

An untrusted project’s .vibe/ config (tools, hooks, agents) executes on first entry (threat T-005).

Medium

High

High

Trust-folder gate (Cross-cutting Concepts Security).

R-002

A secret file is read, or webfetch is used for SSRF (threats T-002, T-004).

Medium

Medium

Medium

Sensitive-pattern gating and ASK permission on webfetch (Cross-cutting Concepts Security).

R-003

A file write or patch lands outside the working directory (threat T-003).

Low

High

Medium

Working-directory boundary (Cross-cutting Concepts Security).

R-005

The Mistral API key leaks from disk (threat T-006).

Low

High

Medium

Keyring storage and RSA+AES payload encryption (Cross-cutting Concepts Security).

R-006

A malicious hook command runs as a shell subprocess (threat T-007).

Low

High

Medium

Experimental-hooks gate (Cross-cutting Concepts Security) — hooks run only when enable_experimental_hooks is set; bounded 30 s timeout and 3 retries (Quality Requirements).

R-008

A large pinned dependency surface (~80 direct dependencies) carries supply-chain exposure; no SBOM or scanning config is in the bounded context [pyproject.toml:30-141].

Medium

Medium

Medium

uv.lock pins every transitive dependency; exclude-newer constrains new releases. Adding an SBOM / scan is unmitigated — deferred.

R-009

Behaviour on a sustained LLM-provider outage (beyond retry exhaustion) is not specified in code (deferred).

Medium

Low

Low

Retry/backoff scenario in Quality Requirements; the intended end-state is deferred to Operations.

R-010

No performance budget exists in code for very large repositories (deferred).

Low

Low

Low

Byte-capped file reads and auto-compaction bound growth; an explicit budget is deferred.

11.2. Technical Debt

Each item names the Chapter 5 building block it burdens.

ID Burdened Building Block Debt Evidence

TD-001

Agent Loop

session_cost is a self-described rough estimate that ignores prompt caching, so the --max-price ceiling is approximate.

vibe/core/types.py:102-115

TD-002

ACP Bridge

acp/tools/ re-implements several builtins (bash, read_file, write_file, search_replace, grep, …) that already exist in core/tools/, duplicating maintenance.

vibe/acp/acp_agent_loop.py:650-666

TD-003

Session Persistence

A v1→v2 session-format migration is carried in code; it can be removed once all users have migrated.

vibe/core/session/session_migration.py:16-41

TD-004

CLI / Textual UI

The TUI widget layer is large (~70 widget modules) and untiered, which makes the front end the least diffable part of a recovery run.

vibe/cli/textual_ui/widgets/

TD-005

CLI / Textual UI

Voice mode is shipped but marked experimental and "may change".

README.md:284-285

12. Glossary

Term Definition

Agent

A configured run profile of the engine; built-in profiles are default, plan, chat, accept-edits, auto-approve, explore, lean [vibe/core/agents/models.py:38-45].

Subagent

An agent of type SUBAGENT (e.g. explore) spawned by the task tool to do isolated work [vibe/core/agents/models.py:152].

Agent Profile

The data record for an agent: name, safety tier, agent type and config overrides [vibe/core/agents/models.py:48-94].

Agent Loop

The orchestrator that runs a conversation turn — LLM call plus tool execution — until no tool call remains [vibe/core/agent_loop.py:855-937].

Tool

A BaseTool subclass with a Pydantic args model, a result model and an async run() generator [vibe/core/tools/base.py:122-152].

Tool Permission

The tier — ALWAYS, ASK or NEVER — that decides whether a tool runs without asking [vibe/core/tools/base.py:83-96].

Skill

A reusable component declared by a SKILL.md file; can add slash commands and behaviours [vibe/core/skills/manager.py:91-117].

MCP Server

An external tool provider reached over the Model Context Protocol (http, streamable-http or stdio) [vibe/core/tools/mcp/registry.py:80-150].

Connector

A remote tool source registered through the connector registry [vibe/core/tools/connectors/connector_registry.py].

Hook

A TOML-declared shell command run on a lifecycle event such as POST_AGENT_TURN [vibe/core/hooks/models.py:19-38].

Session

A persisted conversation: a folder of meta.json + messages.jsonl [vibe/core/session/session_loader.py:16-17].

Compaction

Summarising the conversation history when the context nears the model’s token threshold [vibe/core/agent_loop.py:1681-1749].

Plan Mode

The read-only plan agent that drafts a markdown plan before execution [vibe/core/plan_session.py:11-42].

Teleport

Handing a local session to a remote Vibe Code workflow [vibe/core/teleport/teleport.py:46-150].

Nuage

The remote cloud workflow backend (French for "cloud") [vibe/core/nuage/client.py:22-100].

Trust Folder

A directory the user has explicitly trusted; only trusted folders load project .vibe/ config [vibe/core/trusted_folders.py:75-122].

ACP

Agent Client Protocol — the JSON-RPC-style protocol the vibe-acp server speaks to editors [vibe/acp/entrypoint.py:78-108].

VIBE_HOME

The user-state directory, ~/.vibe by default, relocatable via the VIBE_HOME env var [vibe/core/paths/_vibe_home.py:19-25].