This document describes the current Grinta architecture for maintainers.
For historical context and design rationale (not current spec), see docs/journey/README.md.
Grinta is a local-first terminal coding agent with four visible layers:
- Interface: console-script launcher, Textual TUI for TTYs, non-interactive runner for piped input.
- Orchestration: session loop, safeguards, retries, finish validation.
- Execution: local runtime actions (commands, file ops, tool interaction).
- Durability: event stream and persisted state for recovery/replay.
Grinta executes on the local host.
- Default runtime is in-process local execution.
hardened_localapplies stricter policy checks.hardened_localis not sandboxing or host isolation.sandboxed_localreuses the hardened policy and adds OS-native, process-scoped isolation for supported non-interactive subprocess commands (bwrapon Linux, AppContainer on Windows,sandbox-execon macOS).- Interactive PTY sessions remain outside the
sandboxed_localprocess boundary. The profile is not a VM, container boundary, or complete host isolation.
Use Grinta in trusted environments.
User (terminal)
-> backend.cli.entry
-> Textual TUI when stdin is a TTY
-> non-interactive runner when stdin is piped
-> SessionOrchestrator
-> Engine (planning + tool intent)
-> Operation pipeline and safety checks
-> RuntimeExecutor (commands/files/tools)
-> Observations
-> EventStream (durable history)
-> Task validation before finish
backend/
cli/ Console entrypoints, Textual TUI, non-interactive runner, slash commands
context/ Memory and compaction
core/ Config, constants, logging, shared utilities
engine/ Agent reasoning, prompt assembly, and tool implementations
evaluation/ Agent eval pack and related evaluation helpers
execution/ Local runtime, shell/session plumbing, and executor internals
inference/ Provider routing and direct LLM clients
integrations/ External integration adapters (MCP; see docs/INFERENCE_AND_INTEGRATIONS.md)
knowledge/ Optional retrieval and knowledge features
ledger/ Event types, serialization, stream infrastructure
orchestration/ Session orchestrator and focused services
persistence/ Storage and state persistence
playbooks/ Playbook definitions and helpers
security/ Command risk analysis and policies
telemetry/ Lightweight instrumentation
tools/ Repo maintenance utilities (not the model-facing tool API)
utils/ Shared helpers (imports, LSP, HTTP, etc.)
validation/ Completion and quality validation
The public console script is launch.entry:main, which resolves the installed
or editable project entry file without relying on whatever backend/ package
may be present in the user's working directory. The resolved path runs
backend.cli.entry.
backend.cli.entry handles global flags and subcommands:
grintastarts the app in the current project.grinta init(or first interactivegrinta) writes user configuration.grinta sessions ...lists, shows, exports, deletes, and prunes persisted sessions.--project,--model,--theme,--minimal,--accessible, and--cleanup-storagecustomize startup.
backend.cli.main then selects the runtime surface:
- TTY stdin ->
backend.cli.tui.main, the Textual application with transcript cards, HUD, dialogs, and keyboard shortcuts. - Non-TTY stdin ->
backend.cli.repl.noninteractive, for scripted/piped one-shot runs.
Interactive UX is the Textual TUI only. The backend/cli/repl/ package holds slash-command handlers and the non-interactive runner.
| Surface | Path | Role |
|---|---|---|
| Textual TUI (product) | backend/cli/tui/ |
Default when stdin is a TTY. Full HUD, slash commands, sessions dialog, mode/autonomy controls. |
| Slash-command layer | backend/cli/repl/slash_command_* |
Shared /help, /mode, /health, etc. Used by TUI and tests. |
| Non-interactive | backend/cli/repl/noninteractive.py |
Piped stdin / one-shot automation. |
New UX work lands in the TUI; keep slash-command handlers thin when parity is required (for example /mode, /autonomy, /health).
The orchestrator delegates to focused services under backend/orchestration/services/.
Current service modules include:
action_execution_service.py- Executes agent actions via the runtimeaction_service.py- Action lifecycle managementautonomy_service.py- Controls agent autonomy and delegationcircuit_breaker_service.py- Prevents cascading failuresconfirmation_service.py- Handles user confirmation flowsevent_router_service.py- Routes events to appropriate handlersexception_handler_service.py- Centralized exception handlingguard_bus.py- Pub/sub guard rail for system eventsiteration_guard_service.py- Prevents infinite loopsiteration_service.py- Manages iteration counting and limitslifecycle_service.py- Manages agent lifecycle transitionsobservation_service.py- Processes observations from actionsorchestration_context.py- Shared service wiring and context objectpending_action_service.py- Tracks in-flight actionsrecovery_service.py- Error recovery and retry logicretry_service.py- Handles retry policiessafety_service.py- Validates actions against safety policiesstate_transition_service.py- Manages valid state transitionsstep_decision_service.py- Decides whether to continue or finishstep_guard_service.py- Pre-step validation checksstep_prerequisite_service.py- Ensures prerequisites are metstuck_detection_service.py- Detects stuck agentstask_validation_service.py- Validates task completion
Design intent:
- split control-plane concerns into testable units
- classify errors into recoverable vs terminal paths
- reduce false completion with explicit task tracking and completion-quality validation signals
The orchestrator uses a middleware pipeline (assembled in
backend/orchestration/mixins/_session_orchestrator_lifecycle_mixin.py)
for cross-cutting concerns:
middlewares = [
SafetyValidatorMiddleware(self), # Validate action safety
BlackboardMiddleware(self), # Track action context
CircuitBreakerMiddleware(self), # Prevent cascading failures
ProgressPolicyMiddleware(), # Progress indicators
CostQuotaMiddleware(self), # Budget tracking
ContextWindowMiddleware(self), # Context window management
RollbackMiddleware(), # State rollback support
DestructiveCommandMiddleware(), # Block dangerous commands
PreExecDiffMiddleware(), # Generate diffs before edits
AutoCheckMiddleware(), # Post-execution validation
PostEditDiagnosticsMiddleware(), # Diagnostics after edits
FileStateMiddleware(), # File-state tracking
LoggingMiddleware(self), # Request/response logging
TelemetryMiddleware(self), # Metrics collection
ToolResultValidator(), # Validate tool outputs
]Middleware execution order matters - safety checks run first, telemetry runs last.
orchestrator.step()called- Acquires
self._step_lock(asyncio.Lock) - Calls
services.pending_action.set(action) - Middleware pipeline processes action
- Action executed via
services.action_execution - Observation processed by
services.observation - State updated via
state_tracker - Releases lock, updates metrics
- Exception occurs during step
services.recovery.react_to_exception(e)called- Error classified as recoverable or terminal
- Recoverable: retry with backoff via
services.retry - Terminal: emit error observation, transition to CLOSING
- INITIALIZING → ACTIVE: After service initialization
- ACTIVE → CLOSING: On agent finish or error
- CLOSING → CLOSED: After cleanup and checkpoint
Execution is implemented in backend/execution/.
Important components:
action_execution_server.py: runtime executor implementation used by the local runtimesecurity_enforcement.py: policy checks for command/path behaviorbrowser/: native browser session and CDP helpersdap/: debugger adapter protocol integrationmcp/: MCP bootstrap/proxy support for runtime-connected external toolsutils/: command helpers, diffing, session handling, monitoring
Events flow through backend/ledger/ and persistence modules.
Key properties:
- event-oriented state history
- replay-friendly serialization
- backpressure and stream controls
- persistence support for reliable recovery paths
Default local setup uses:
- installed
~/.grinta/settings.json, or repositorysettings.jsonwhen running from source, for user-facing model/provider keys - environment variables for automation and secret injection
~/.grinta/workspaces/<id>/storagefor runtime/session state
Minimal fields in settings.template.json:
llm_providerllm_modelllm_api_keyllm_base_url
The package metadata reports 1.0.0.
Core runtime protections include:
- retry and recovery services
- circuit breaker and stuck detection
- task tracking and completion-quality validation signals before finish
- security policy checks in execution path
These controls are designed to reduce false-success runs and uncontrolled loops while keeping the local workflow fast.
For detailed reliability patterns, see RELIABILITY.md. For performance considerations, see PERFORMANCE.md.