Metadata-Version: 2.4
Name: travis234
Version: 2.5.3
Summary: Terminal coding agent with persistent sessions and bounded tool execution.
License-Expression: MIT
Requires-Python: <3.14,>=3.13
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE.md
Requires-Dist: boto3<2,>=1.35
Requires-Dist: google-auth<3,>=2.35
Requires-Dist: httpx>=0.27
Requires-Dist: jsonschema<5,>=4.23
Requires-Dist: psutil>=6.1
Requires-Dist: PyYAML<7,>=6
Requires-Dist: websockets<17,>=15
Requires-Dist: zstandard<1,>=0.23
Provides-Extra: browser
Requires-Dist: playwright>=1.59; extra == "browser"
Dynamic: license-file

<p align="center">
  <img src="docs/assets/travis234-banner.svg" alt="Travis234 cybernetic terminal coding agent" width="100%" />
</p>

```text
TRAVIS234 // NEURAL TERMINAL ONLINE
[AGENT:READY] [CONTEXT:COMPACT] [TOOLS:BOUNDED] [RUNTIME:PERSISTENT]
```

<p align="center">
  <a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-39e6c7?style=for-the-badge&labelColor=10182b"></a>
  <img alt="Python 3.13" src="https://img.shields.io/badge/Python-3.13-63a7ff?style=for-the-badge&labelColor=10182b">
  <img alt="Version 2.5.3" src="https://img.shields.io/badge/version-2.5.3-bd6cff?style=for-the-badge&labelColor=10182b">
  <img alt="Terminal first" src="https://img.shields.io/badge/interface-terminal-ff7ac6?style=for-the-badge&labelColor=10182b">
</p>

<p align="center">
  <strong>A persistent, provider-neutral coding agent built for real development work.</strong><br>
  Bounded tools, managed processes, extensible workflows, and context compaction in one responsive terminal UI.
</p>

<p align="center">
  <a href="#quick-start">Quick start</a> ·
  <a href="#travis234-offsec">OffSec</a> ·
  <a href="#inside-the-runtime">Architecture</a> ·
  <a href="#extensions">Extensions</a> ·
  <a href="#durable-multi-travis-orchestration">Orchestration</a> ·
  <a href="#context-and-compaction">Compaction</a> ·
  <a href="#production-sandbox">Sandbox</a> ·
  <a href="#verification">Verification</a>
</p>

---

## Built to keep working

Travis234 is designed for developers who want an agent to carry a task—not one they must constantly babysit. Sessions persist, long-running commands remain controllable, tool execution stays bounded, context can be compacted without switching the active coding model, and one Travis session can safely hand bounded work to another durable Travis session.

<table>
  <tr>
    <td width="50%" valign="top">
      <h3>⚡ Responsive runtime</h3>
      Ordered tool results, bounded parallel execution, recoverable failures, cancellation, and repeated Ctrl-C escalation.
    </td>
    <td width="50%" valign="top">
      <h3>🧠 Durable context</h3>
      Persistent sessions, manual and automatic compaction, real-usage verification, and an optional dedicated summary model.
    </td>
  </tr>
  <tr>
    <td width="50%" valign="top">
      <h3>🔌 Provider neutral</h3>
      Per-model runtime bindings and provider-scoped credentials across OpenAI-compatible and native provider transports.
    </td>
    <td width="50%" valign="top">
      <h3>🧩 Extensible by design</h3>
      Global and project extensions, reloadable commands, lazy skills, custom tools, and bounded subagent workflows.
    </td>
  </tr>
  <tr>
    <td width="50%" valign="top">
      <h3>🛠 Managed processes</h3>
      Polling, streaming output, acknowledged stdin, interrupts, terminal-state recovery, and explicit cleanup.
    </td>
    <td width="50%" valign="top">
      <h3>🛡 Isolated execution</h3>
      An optional unprivileged Docker sandbox with dropped capabilities, isolated state, and explicit-only dotenv forwarding.
    </td>
  </tr>
</table>

## Travis234 OffSec

### A persistent AI terminal for investigation work

Travis234 OffSec is the Kali-ready product lane for DFIR, authorized labs,
security research, and private-environment investigation. It keeps the same
persistent session and compaction runtime while working where the evidence,
tools, and network routes already live.

| Work where the evidence is | Keep the investigation moving |
| --- | --- |
| Run host-native on Kali for VPN routes, private ranges, local artifacts, and installed tools. | Use managed PTYs, follow-up input, tmux, long-running processes, persistent sessions, and compaction for work that exceeds one context window. |

| Bring your model and provider | Sandbox when it fits |
| --- | --- |
| Use supported providers or an OpenAI-compatible proxy such as 9router. Model choice improves reasoning; Travis234 keeps process and session control dependable. | Launch a prebuilt unprivileged Kali image through npx when a disposable environment is useful. |

Install host-native on Kali:

```bash
uv tool install --python 3.13 travis234-offsec
travis234 --cwd ~/casework
```

Or launch the Kali sandbox:

```bash
npx @htooayelwinict/travis234-offsec --cwd ~/casework
```

For an OpenAI-compatible proxy in the sandbox, explicitly supply its dotenv
file. On Docker Desktop, use `host.docker.internal` rather than `localhost` in
the proxy base URL:

```bash
npx @htooayelwinict/travis234-offsec \
  --cwd ~/casework \
  --dotenv ~/.config/travis/9router.env
```

The operator supplies the workspace, network route, target scope, credentials,
and authorization. Use the host-native path when a VPN route or local evidence
must be visible directly. See the [OffSec operator manual](https://github.com/htooayelwinict/travis234/blob/offsec-agent/docs/offsec/manual.md).

## Quick start

### Install from PyPI

Install the persistent CLI with [uv](https://docs.astral.sh/uv/):

```bash
uv tool install --python 3.13 travis234
travis234 --cwd .
```

Run it once without a persistent installation:

```bash
uvx --python 3.13 travis234 --cwd .
```

Or install it with pip:

```bash
python3.13 -m pip install travis234
travis234 --cwd .
```

Upgrade an existing uv tool installation with `uv tool upgrade travis234`. The public Python package is available at [PyPI](https://pypi.org/project/travis234/) and requires Python 3.13.

### Run from source

Travis234 requires Python 3.13.

```bash
git clone https://github.com/htooayelwinict/travis234.git
cd travis234
python3.13 -m venv .venv
.venv/bin/pip install -e .
.venv/bin/travis234 --cwd .
```

Inside the TUI, use `/login` to authenticate, `/model` to select a model, and `/help` to see the complete command set.

### Automation and controlled startup

All transports use the same `CodingApp`, `AgentSession`, persistence, trust, tool, and compaction owners:

```bash
# Final assistant text only
.venv/bin/travis234 --cwd . --mode print "Inspect the failing test"

# Versioned JSON Lines lifecycle stream
.venv/bin/travis234 --cwd . --mode json "Inspect the failing test"

# Newline-delimited request/response RPC on stdin/stdout
.venv/bin/travis234 --cwd . --mode rpc
```

Machine modes never prompt for project trust. Unknown projects remain untrusted unless `--approve`, `--no-approve`, or a saved policy decides them. `--offline` disables catalog refresh, OAuth refresh that requires a network, and non-local package acquisition while retaining cached models, stored credentials, and local resources.

Tool and resource controls are applied before the system prompt and context envelope are built:

```bash
.venv/bin/travis234 --cwd . --tools read,grep,find --exclude-tools bash \
  --extension ./trusted-extension.py --skill ./skills/review/SKILL.md \
  --prompt-template ./prompts/audit.md --theme ./themes/night.json \
  --mode print '@README.md review this file'
```

`--tools` and `--exclude-tools` are repeatable comma-separated lists; `--no-tools` disables every tool unless an explicit allowlist adds one back. Explicit resource paths are operator-authorized for that process and are validated without fallback searching. `@file`, quoted `@"path with spaces"`, and repeatable `--image PATH` inputs are expanded with read-tool size bounds before provider submission. The legacy `--plain` interactive alias remains for compatibility and is planned for removal in 3.0.

Browser-development support is optional:

```bash
.venv/bin/pip install -e '.[browser]'
```

### Run through the npm sandbox launcher

```bash
npx @htooayelwinict/travis234 --cwd .
```

The npm package exposes only the `travis234` command and launches the release container with isolated Travis234 state. To provide credentials or an OpenAI-compatible proxy explicitly, add `--dotenv /path/to/.env`; Docker receives it as an environment file without mounting it or forwarding its host path to the Python CLI. A proxy running on the host must use a container-reachable address such as `host.docker.internal`, not `localhost`.

## Everyday controls

| Command | Purpose |
|---|---|
| `/login` | Authenticate with a supported provider |
| `/model` | Search and select the active model |
| `/params [name [value] \| reset [name]]` | Inspect or change durable model parameters for the active session |
| `/session` | Inspect the current persistent session and context usage |
| `/name`, `/fork`, `/clone`, `/tree` | Name, branch, clone, or navigate the JSONL v3 session tree |
| `/resume`, `/new` | Switch to another indexed session or start a new one |
| `/export`, `/import`, `/copy`, `/share` | Move or present session data through explicit local/platform adapters |
| `/compact [focus]`, `/compress [focus]` | Safely summarize older history while retaining a recent raw suffix; skip when compression would grow context |
| `/compact deep [focus]`, `/compress deep [focus]` | Create an aggressive bounded generational checkpoint with no retained raw suffix |
| `/reload` | Reload project and global extensions without restarting |
| `/theme` | Select a discovered theme |
| `/motion [on\|off]` | Inspect or change restrained State Signals for the current TUI process |
| `/trust` | View or change project trust; reload before newly trusted code runs |
| `/packages` | List installed resource packages (`--local` selects project scope) |
| `/install`, `/remove`, `/update` | Confirm and manage local, Git, or Python resource packages |
| `/processes` | Inspect managed and user-command processes |
| `/memory status` | Inspect opt-in explicit-memory settings, availability, limits, and counts without displaying facts |
| `/operations [operation-id]` | Inspect bounded operation-journal metadata for the active session |
| `/agents [status\|inspect\|steer\|cancel]` | Inspect or control session-owned delegated agents |
| `/help` | Show available commands and shortcuts |
| `/exit` | Shut down cleanly and terminate owned work |

User `!command` and `!!command` run asynchronously. Output from `!command` is added to context; `!!command` output remains outside model context.

### Explicit opt-in memory

Travis234 includes a disabled-by-default private fact store under its existing
`~/.travis234` state root. When the global user enables it, one
policy-controlled `memory` tool can explicitly retain, recall, inspect, or
delete project-scoped facts; global scope requires a separate explicit
allowance. Facts are never retained automatically and recalled facts are never
injected automatically.

Recall labels every fact as untrusted data, rejects credential-shaped
retention, bounds results, and promotes larger complete output to a session
artifact. The tool conservatively declares both read and write effects, so an
enforced policy may require approval even for recall. `/memory status` displays
configuration and counts only—never facts, queries, paths, session identity, or
credentials. See [settings](docs/settings.md#explicit-memory) for the exact
limits and tradeoffs.

### Observe-only operation journal

Travis234 keeps a separate SQLite intent/effect/settlement journal at
`~/.travis234/agent/operations.sqlite3`. It complements the existing JSONL
conversation history; it does not replace it. JSONL remains authoritative for
resuming conversation, while the journal makes an interrupted provider or tool
boundary visible after a process crash.

The journal defaults to `observe` mode with a 1 GiB cap. It records bounded
identifiers, state, timestamps, counters, sanitized effect names, and usage
totals. It never records prompts, completions, tool arguments or results,
environment values, credentials, steering text, or subagent goals. An intent
owned by a provably dead runtime becomes `uncertain` on startup and always has
`replay=never`; Travis does not infer success and does not automatically retry
it. This exposes the unavoidable uncertainty window rather than claiming
exactly-once execution.

Use `/operations` or `/operations <operation-id>` to inspect only the active
session's hashed identity. Other sessions appear unknown even when an opaque ID
is supplied. Inspection is read-only and never prunes data. Journal corruption
or capacity failure disables observation without preventing JSONL conversation
recovery or the coding turn.

### Session generation parameters

`/params` is a direct, non-picker session control. It reports the active provider/model, thinking level, effective generation parameters, value sources, and any provider-capability warnings.

```text
/params
/params temperature
/params temperature 0.2
/params thinking high
/params stop END,STOP
/params reset temperature
/params reset
```

The editable generation fields are `temperature`, `top_p`, `max_tokens`, `timeout_seconds`, `frequency_penalty`, `presence_penalty`, `seed`, `parallel_tool_calls`, `tool_choice`, `stop`, and `provider_sort`. `thinking` uses the model-aware session reasoning control and stays independent from the generation override map.

Generation changes are local to the active JSONL session, survive resume and branch operations, and apply on the next Agent turn. A resumed session wins only for fields explicitly changed there; untouched fields continue to inherit the current provider, dotenv, and startup CLI configuration. `/params reset <name>` removes one session override and reveals the inherited value, while `/params reset` removes every generation override without changing thinking. Use explicit `reset` syntax—`none`, `null`, and empty values are rejected.

Writes are rejected while an Agent turn is active, but read-only `/params` queries remain available. Valid settings that the selected provider cannot use remain saved and are reported as `dropped`; switching to a compatible model can activate them later. Context and output safety remain authoritative, so request-time limits may lower `max_tokens`. These session overrides affect the interactive main Agent turn, including its tool continuations and retries; compaction and auxiliary summarizer calls keep their existing parameter policy.

### Model roles

Travis234 can route focused work to already configured models without changing the active
conversation model. Add any of the four optional roles to
`~/.travis234/agent/settings.json`:

```json
{
  "modelRoles": {
    "compression": "provider/summary-model:low",
    "worker": "provider/fast-model:medium",
    "reviewer": "provider/review-model:high",
    "vision": "provider/image-model"
  }
}
```

A trusted project can override the same keys in `.travis234/settings.json`. The suffix
after the final colon is an optional thinking level. Missing roles fall back to the active
primary model; `reviewer` first falls back to `worker`. The `vision` route must select a
model that advertises image input and fails before a provider call when none is available.
`/model` changes the implicit primary fallback only and never rewrites an explicit role.
External Codex subagents keep their own explicit model contract and do not consume these
Travis model-role settings.

### Typed subagent roles

Optional role resources let a delegation inherit a named, reviewable contract.
Global JSON roles live in `~/.travis234/agent/roles/`; trusted projects may
override them from `.travis234/roles/`, and packages may contribute roles through
the shared capability registry. A role can narrow tools and effects, choose the
existing `worker` or `reviewer` model route, add bounded relative context, lower
the timeout, require a JSON-schema result, and allow declared artifacts.

Role permissions are intersections, never grants: the child receives only tools
already active for its parent, with declared effects inside the role ceiling.
Explicit empty tool or effect lists grant none. The existing scheduler remains
capped at three concurrent children and one child level, so a role cannot enable
recursive delegation. Missing role definitions preserve the established
untyped behavior. See [settings](docs/settings.md#typed-agent-roles) for the JSON
fields and failure semantics.

The native TUI exposes `/agents status`, `/agents inspect <id>`, `/agents steer
<id> <message>`, and `/agents cancel <id>`. Immutable roster snapshots show
bounded status and summary previews without goals, role context, raw traces, or
host paths. `/subagents` still selects the delegation skill for the next prompt.

### Terminal history and selection

Travis234 renders complete logical output into the terminal's normal buffer. The terminal—not the agent—owns wheel and touchpad scrolling, drag selection, clickable links, and terminal or tmux history. PageUp, PageDown, Home, and End are passed to the focused TUI component; Shift+PageUp and Shift+PageDown follow the terminal's own configuration.

Real PTY resize events are tracked through `SIGWINCH`; the active screen repaints at the new width without erasing native scrollback.

Mouse reporting is disabled by default, including in the release sandbox, so ordinary text selection remains available. `TRAVIS234_TUI_MOUSE=1` is an explicit diagnostic opt-in; many terminals disable normal selection, URL interaction, and tmux scrollback while mouse reporting is active.

### Themes and multiline input

The built-in semantic themes are **Signal Glass**, **Black Ice**, **Neon Oni**, **Blood Circuit**, **Reactor Gold**, and **Polar Ghost**. Run `/theme` to open the live preview: arrow keys preview without persistence, Escape restores the exact original palette, and Enter returns the selection to the existing `/theme` command for the single persisted commit.

External Pi-compatible JSON themes may provide any subset of the semantic colors. Missing roles inherit from Signal Glass. Values may be strict `#RRGGBB`, xterm indices `0..255`, an empty string for the terminal default, or references into `vars`; malformed roles fall back locally and never enter the agent context. `NO_COLOR=1` or `TERM=dumb` keeps the same semantic text with no ANSI color.

State Signals add one restrained animated indicator after the existing activity label while Travis234 is actively working. Active provider turns render `Thinking...`: all three suffix dots stay at a fixed width while their highlight travels. Tool activity uses one fixed-width suffix spinner, and the telemetry footer remains static. At most one signal moves, parallel tools share it, and idle sessions schedule no animation work. Use `/motion off` or `/motion on` for the current process, or start with `TRAVIS234_MOTION=0`; `NO_COLOR=1` and `TERM=dumb` automatically retain a static semantic indicator. Motion stays inside the differential TUI renderer and never enters prompts, messages, context accounting, compaction, provider requests, or session files.

Extensions can keep compact provider or system telemetry in the existing footer with `ui.setStatus(key, text)`. An optional `{"state": "working"}` third argument participates in the shared State Signal, but extensions cannot define animation loops or frame rates. For example, a monitor extension may publish `CPU 42% · RAM 61%` once per second; Travis234 does not sample CPU or memory in core.

The main prompt is multiline. Enter submits the complete prompt; Shift+Enter inserts a newline when the terminal reports modified Enter, and Alt+Enter is the portable fallback. Arrow keys move through lines while preserving the visual column. Dialog, search, password, and picker fields remain single-line.

## Inside the runtime

```mermaid
flowchart LR
    U[Developer] --> T[Terminal UI]
    T --> S[Persistent session]
    S --> L[Agent loop]
    L <--> P[Provider adapters]
    L <--> X[Tools and processes]
    S <--> E[Extensions and skills]
    S <--> C[Context compaction]
    S <--> D[(Session store)]

    classDef core fill:#13213f,stroke:#63a7ff,color:#f4f7ff
    classDef edge fill:#10243a,stroke:#39e6c7,color:#f4f7ff
    classDef memory fill:#261b43,stroke:#bd6cff,color:#f4f7ff
    class T,S,L core
    class P,X,E edge
    class C,D memory
```

The core iteration loop owns ordering and bounded execution. Provider adapters translate model protocols without owning session policy. Extensions add commands, tools, hooks, providers, and subagents through explicit session-owned registrations. Compaction and persistence remain separate context owners.

### Tool effect policy

Coding tools declare `read`, `write`, `execute`, and/or `network` effects. The
default `toolPolicy` mode is `audit`, so existing behavior continues while
Travis234 records sanitized decisions and identifies legacy extension tools
that have not declared effects. Set `mode` to `enforce` to auto-allow the
configured effects (read only by default) and require native-TUI approval for
other declared tools; undeclared tools are denied. Machine modes never prompt
and deny approval-required work without reading stdin.

TUI approvals can allow one call, grant the tool's exact effect set for the
current session, or deny it. Grants are never persisted and do not survive
resume, fork, clone, session replacement, or restart. Project policy applies
only after project trust and can tighten, never loosen, the global policy. See
[settings](docs/settings.md#tool-effect-policy) for the complete merge and
failure semantics.

### Bounded language services

Travis234 can use user-installed language servers through one optional `lsp`
tool. Configure an explicit executable plus argument vector in
`languageServers`; project definitions load only after project trust. Servers
start lazily on the first semantic action, remain capped at three active
instances, and close with their owning session. `/lsp status` is a local-only
snapshot and does not start a server.

Semantic reads include diagnostics, symbols, hover, definition, references,
and code actions. Rename and editable code actions use a two-step workflow:
first generate a bounded diff preview without changing files, then apply its
short-lived token after tool-policy approval. Apply rechecks exact file hashes
and reports any paths it changed, restored, or could not restore. Large
completed results use the existing durable artifact boundary. See
[settings](docs/settings.md#language-servers) for configuration, fixed limits,
coordinate rules, policy effects, and troubleshooting constraints.

### Python SDK surfaces

`AgentHarness` is the async composition root for applications that need the same session, resource, tool, and compaction owners without a TUI. `Models.async_api()` provides event-loop-safe model discovery, `stream_proxy()` provides ordered transform/callback forwarding, and the optional image registry remains separate from chat-model selection.

```python
from travis import AgentHarness, AgentHarnessConfig

async with AgentHarness.create(
    AgentHarnessConfig(cwd=".", model=model, trust_override=False)
) as harness:
    message = await harness.prompt("Inspect the failing test")
```

`AgentHarness.subscribe()` delivers an independent dictionary snapshot to each observer. An
observer exception is reported through logging without interrupting the agent, session commit,
or later observers. `close()` gives an active operation ten seconds to cooperate with abort; if
ownership cannot be obtained, it raises `TimeoutError` while leaving the harness open so cleanup
can be retried after the operation exits.

Image APIs are exported from `travis.ai`: `ImageModel`, `ImageGenerationOptions`, `generate_images`, and `register_image_provider`. They do not load an image provider or add image-model schemas to ordinary chat requests unless explicitly invoked.

## Providers and credentials

Provider credentials should be configured through `/login` or the provider's standard environment variable. Credentials loaded from `--dotenv` are registered only for the provider that declares them; switching models cannot reuse another provider's key.

`/login` stores the selected provider's key locally and intentionally does not make a paid test request. The TUI reports that the key will be verified on the first real prompt. Provider failures are shown with useful status and error detail, but credential-shaped JSON fields, the active request credential, bearer tokens, and `sk-...` token strings are redacted before they reach the TUI or session history.

For direct Kimi Code, MiniMax, and OpenCode routes, use these standard variables in an ignored dotenv file:

```dotenv
KIMI_API_KEY=...
MINIMAX_API_KEY=...
MINIMAX_CN_API_KEY=...
OPENCODE_API_KEY=...
```

One OpenCode key works across the `opencode` and `opencode-go` catalogs. Travis234 chooses authentication from the selected model's actual protocol: OpenAI routes use bearer auth, Anthropic-compatible routes use `x-api-key` plus the Anthropic protocol version, and Google routes use `x-goog-api-key`. Direct Kimi requests identify the caller as `Travis234/<version>`; Travis234 never claims another CLI's identity. These details are automatic—users only need `/login`, `/model`, and a normal prompt.

The active worker binding can be explicit:

```dotenv
TRAVIS234_WORKER_LLM_PROVIDER=openrouter
TRAVIS234_WORKER_LLM_MODEL=xiaomi/mimo-v2.5
TRAVIS234_WORKER_LLM_CONTEXT_WINDOW=1048576
```

OpenAI-compatible routers and proxies do not need catalog entries of their own. Keep the
`openrouter` transport contract and replace only the endpoint, credential, and model ID.
For example, a local 9Router installation exposes its compatible API at
`http://localhost:20128/v1`:

```dotenv
TRAVIS234_WORKER_LLM_PROVIDER=openrouter
TRAVIS234_WORKER_LLM_BASE_URL=http://localhost:20128/v1
TRAVIS234_WORKER_LLM_API_KEY=local-placeholder
TRAVIS234_WORKER_LLM_MODEL=anthropic/claude-opus-5
```

Use the proxy's exact model ID. When it matches an OpenRouter catalog ID, Travis234 keeps
the catalog's reasoning and capacity metadata while sending requests to the overridden
endpoint. For proxy-only aliases such as `kr/...`, also set
`TRAVIS234_WORKER_LLM_CONTEXT_WINDOW` and `TRAVIS234_WORKER_LLM_MAX_TOKENS`; unknown IDs
otherwise receive conservative fallback limits. A local proxy with authentication disabled
still needs a non-secret placeholder because provider authentication fails closed.

For a custom or newly released model whose catalog metadata is unavailable, set `TRAVIS234_WORKER_LLM_CONTEXT_WINDOW` to the provider's documented size. Footer telemetry and automatic compaction use this value as their denominator.

Model-driven subprocesses do not inherit provider credentials by default. A trusted project command can receive an exact allowlisted variable through `TRAVIS234_TOOL_ENV_PASSTHROUGH`. Human-authored `!command` remains an operator shell and inherits the operator environment.

## Context and compaction

Travis234 supports conservative manual compaction with `/compact [focus]`, aggressive manual-only compaction with `/compact deep [focus]`, and automatic compaction against the effective input window (the selected route's context window minus its reserved output). Normal `/compact` and automatic compaction retain a protected recent raw suffix so active work stays verbatim. Normal manual compaction safely makes no changes when its generated summary would increase context. The Hermes-aligned automatic default triggers at 75% for routes below 512K and 50% for larger routes. Routes below 64K use a reachable 85% fallback instead of an impossible fixed floor.

`/compact deep` is an explicit fresh-envelope checkpoint for completed work. It replaces the live conversation with one standalone handoff and retains no pre-checkpoint raw suffix. The handoff targets 2,048 estimated tokens; one validation-repair pass may use an absolute 4,096-token ceiling. Large tool results and arguments are bounded before summarization, private reasoning is excluded, sensitive text is redacted, and recent read/modified file anchors are carried forward. Earlier JSONL records remain append-only session history, but they are not replayed into the next provider request.

Deep compaction is atomic and fail-closed. It refuses unanswered users, aborted or errored assistants, unfinished tool turns, insufficient summarizer capacity, invalid or secret-shaped output, and checkpoints that do not save at least 256 tokens or 5%. A refusal preserves the exact live messages and appends no compaction entry. Use normal `/compact` during active implementation when recent turns should remain verbatim; use `/compact deep` after a clean completed turn when reclaiming the context envelope matters more than raw conversational detail. The optional `focus` text tells either summarizer what to prioritize.

An auxiliary summarizer can compact context without changing the active coding model:

```dotenv
TRAVIS234_COMPRESSION_LLM_ENABLED=true
TRAVIS234_COMPRESSION_LLM_PROVIDER=openrouter
TRAVIS234_COMPRESSION_LLM_MODEL=openai/gpt-5.6-luna-pro
TRAVIS234_COMPRESSION_LLM_TIMEOUT_SECONDS=120
```

When required, add `TRAVIS234_COMPRESSION_LLM_BASE_URL` and `TRAVIS234_COMPRESSION_LLM_API_KEY`. Without an auxiliary route, compaction uses the active model. A smaller auxiliary route lowers the live trigger so its summary request fits before the main route overflows. After compaction, Travis234 publishes a full-request estimate (system prompt, active tool schemas, messages, images, and provider replay metadata), then verifies it against the next real provider prompt.

Context pressure counts provider input plus cache-read/cache-write input; generated output is retained for billing statistics but does not make the next prompt larger. This is why a large answer no longer causes premature compaction. Existing JSONL sessions require no migration: summaries, route changes, and the new confidence/component telemetry are re-derived when a session is resumed.

## Extensions

Travis234 discovers extensions from two locations:

```text
~/.travis234/agent/extensions/   # available across projects
.travis234/extensions/          # scoped to the current workspace
```

Run `/reload` after adding or changing extension code; the TUI process does not need to restart.

You can ask Travis234 to create or repair an extension in plain language. The agent is shown the installed extension guide when the request concerns Travis234 extensions, so it can read the exact runtime API, write the Python file, validate it with `python -m py_compile`, ask you to run or run `/reload` as appropriate, and diagnose any reported error. No extension-authoring skill is required. A good first request is: “Create a project extension that adds a `/review` command, validate it, reload it, and help me test it.”

Extensions can register typed, long-form CLI flags:

```python
def extension(travis):
    travis.register_flag("verbose", {"type": "boolean", "description": "Verbose output"})
    travis.register_flag("profile", {"type": "string", "description": "Select a profile"})
```

Load an explicitly trusted extension and pass its flags before the prompt:

```bash
travis234 --extension ./trusted-extension.py --profile security --verbose "inspect this repository"
```

Authorized extension flags appear in `--help`. Boolean flags never consume the following prompt; string flags require a value, and a repeated string flag uses the last value. Use `--` to keep option-shaped text in the prompt instead of parsing it as a flag.

Flag values are process-local, are reapplied when the app replaces its active session, and are not written to settings or session history. Project-only flag schemas require explicit or saved trust before they become valid CLI options. Registering a flag adds no core context-envelope tokens; context grows only if the extension uses that value to enable prompt text, tools, or another context-bearing resource.

The Python extension host runs in TUI, print, JSON, and RPC modes and rebinds session replacements before their startup lifecycle. Async slash commands execute exactly once outside model turns; TUI shortcuts receive raw key input, and live extension tools use the canonical extension context. Non-interactive hosts expose `has_ui=False` and keep JSON/RPC stdout machine-readable. See [the extension guide](travis/resources/docs/extensions.md) for lifecycle details, supported UI behavior, source/staleness rules, and intentional Pi divergences.

Extensions execute with Travis234's permissions, so install only trusted code. Unknown workspaces fail closed: project settings, extensions, skills, prompts, themes, and project system-prompt files stay disabled until trust is resolved. Use `--approve` or `--no-approve` for a process-only CLI decision, or `/trust` to save a folder/parent decision; `/trust` never executes project code by itself. Global resources under `~/.travis234/agent/` remain available during trust resolution. Travis JavaScript extensions do not run directly in the Python runtime and require a Python adapter.

Resource files use safe YAML frontmatter. Discovery merges `.gitignore`, `.ignore`, and `.fdignore`; an explicitly named file remains an operator-selected exception. Leading `/template` prompts expand shell-quoted `$ARGUMENTS`, `$1`, and related Pi placeholders before provider submission. When `enableSkillCommands` is enabled, `/skill:<name>` injects only the selected skill. Discovered themes are reloadable, and extension UI code can select them with `setTheme`.

Packages can be local directories, `git+https://...@revision` sources, or pinned Python requirements. Global commands use `travis234 install|remove|update|list`; add `--local` for trusted project scope. Installs replace atomically, ordinary startup never auto-updates packages, and package subprocesses do not receive model-provider, worker, compression, OAuth, or ambient token credentials.

### Optional MCP adapter

Install the separate official-SDK adapter when Travis234 should call explicitly configured Model Context Protocol servers. Keeping it optional means ordinary Travis234 installations do not inherit MCP dependencies or remote tool schemas.

```bash
travis234 install travis234-mcp-adapter
```

Restart Travis234 after the first install or an update. The adapter registers one lazy `mcp` proxy instead of adding every remote tool to the provider schema. Enable it for the current process with the additive `--mcp` flag:

```bash
# Default Travis234 tools plus MCP
travis234 --cwd . --mcp

# MCP only
travis234 --cwd . --no-tools --mcp

# Advanced explicit subset plus MCP
travis234 --cwd . --tools read,bash --mcp
```

`--mcp` only changes the active tools for that process; it does not install the adapter or modify any MCP configuration. The generic `--tools mcp` form remains supported for an explicit MCP-only allowlist.

The adapter reads `mcpServers` from these files, in increasing precedence:

1. `~/.config/mcp/mcp.json`
2. `~/.travis234/agent/mcp.json`
3. project `.mcp.json`
4. project `.travis234/mcp.json`

Project files require project trust. A higher-precedence definition replaces the complete lower-precedence server definition; individual fields are not merged. The adapter never writes these files.

Minimal stdio configuration:

```json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/absolute/allowed/path"],
      "lifecycle": "lazy"
    }
  }
}
```

Minimal Streamable HTTP configuration:

```json
{
  "mcpServers": {
    "context7": {
      "url": "https://mcp.context7.com/mcp",
      "headers": {
        "CONTEXT7_API_KEY": "$env:CONTEXT7_API_KEY"
      }
    }
  }
}
```

Secrets stay in the Travis234 process environment. Configuration may use `${SERVICE_TOKEN}` inside a value or exact `$env:SERVICE_TOKEN`; the adapter does not load `.env` itself. Native users export variables before launch. The npm sandbox may receive an operator-selected file through its existing `--dotenv /path/to/.env` boundary.

The model sees five bounded proxy forms:

```json
{}
{"server":"filesystem"}
{"server":"filesystem","search":"read text"}
{"server":"filesystem","describe":"read_text_file"}
{"server":"filesystem","tool":"read_text_file","args":{"path":"/absolute/allowed/path/README.md"}}
```

Status does not connect. Listing, search, describe, and calls connect only the named server. Calls are never fanned out or automatically retried. `requestTimeoutMs` controls MCP initialization, discovery, and calls only; it does not alter provider, process, or subagent timeouts. Shared `"lifecycle": "lazy"` declarations are accepted as no-ops, while eager and keep-alive modes are rejected.

Configured servers are an operator consent boundary: review third-party packages, pin versions when reproducibility matters, and give filesystem servers only the directories they need. The proxy declares all four tool effects because remote method semantics are not locally provable; enforce mode may therefore request a normal tool-policy approval showing only server and operation. The adapter supports stdio and Streamable HTTP. It does not currently implement legacy SSE, MCP OAuth, prompts, resources, sampling, elicitation, Apps/UI, or direct per-server provider tools.

See the [complete adapter user guide](packages/travis234-mcp-adapter/README.md) for installation management, public-server examples, security rules, output limits, TUI workflows, and troubleshooting.

## Skills and state

Every PyPI wheel includes four read-only fallback skills:

- `coordination` for optional plain-language planning, routing, and verification when selected;
- `orchestration` for durable Travis-to-Travis worktree handoffs through tmux and structured RPC;
- `subagent-delegation` for bounded reviewer or worker delegation;
- `web-search` for source-backed web research.

They are discovered lazily and add only their compact name, description, and path to the system prompt until selected. Project and global skill directories retain their existing precedence, so a same-named user skill takes precedence over the packaged fallback. `--no-skills` disables both packaged and user-discovered skills.

Travis234 keeps application state outside project workspaces:

```text
~/.travis234/agent/AGENTS.md
~/.travis234/agent/skills/
~/.travis234/agent/sessions/
~/.travis234/sandbox-home/
```

Workspace skills remain project-owned and load only when selected. Session history, compaction records, and extension state remain under the Travis234 state boundary.

Inside the sandbox, `/travis-home` is the application home and persisted session files live under `/travis-home/agent/sessions/`.

Useful overrides:

| Variable | Purpose |
|---|---|
| `TRAVIS234_CODING_AGENT_DIR` | Override the agent state root |
| `TRAVIS234_CODING_AGENT_SESSION_DIR` | Override persisted session storage |
| `TRAVIS234_SANDBOX_HOME` | Override host-side sandbox state |
| `TRAVIS234_IMAGE` | Select the runtime image |
| `TRAVIS234_SANDBOX_IMAGE` | Select the sandbox image explicitly |
| `TRAVIS234_SHARE_VIEWER_URL` | Configure the shared-session viewer |

### Durable multi-Travis orchestration

Users can ask in ordinary language for another Travis234 to work in a separate
checkout and bring evidence back. There is no orchestration syntax to learn:

```text
Start another Travis in a new worktree, have it inspect parser ownership,
bring the evidence back for my review, then release it safely.
```

The lazy `orchestration` skill is selected from that intent. Its full workflow
is not embedded in the global system prompt, so unrelated turns pay only for
the skill's compact name and description. This capability is independent of
the existing subagent tools: Travis B is a complete, resumable Travis234
session in tmux with its own session history and workspace.
It complements rather than replaces n8n workflows, the generic MCP adapter,
or bounded subagent delegation; choose each mechanism for its own job.
tmux keeps B alive across A's turns, structured RPC carries prompts and
results, Git worktrees isolate code, and SQLite remembers status and mail.

| Mode | What happens |
|---|---|
| Supervised | Travis A remains in the user conversation, reviews B's questions and evidence, can send bounded corrections, and explicitly acknowledges each delivery. |
| Full handoff | B owns the complete bounded scope. A returns the durable worker/session identities with monitoring off and recovers later only when requested. |

The helper creates durable Run, Task, Worker, Dispatch, and Message records
under `~/.travis234/agent/orchestration`. New-worktree workers keep writes
separate from A. A one-Dispatch capability authenticates B's reports without
placing the secret in SQLite, prompts, tool receipts, or logs. Questions,
replies, terminal packets, corrections, acknowledgements, cancellation,
abandonment, retention, release, and restart recovery are all explicit and
bounded.

Important safety boundaries remain visible in every lifecycle receipt:

- B's packet is a report, not proof; A independently checks files, commits,
  tests, and repository state.
- Code Tasks commit by default unless the user explicitly chooses
  `no_commit`; A still reviews before integration.
- No result automatically merges, cherry-picks, pushes, deletes a branch, or
  removes a worktree.
- Worker branches and worktrees remain available until the user explicitly
  requests a safe cleanup operation.
- Recovery observes compatible, lost, or uncertain workers and never silently
  replays a prompt.
- Unacknowledged packets survive an A restart; acknowledged packets stop being
  redelivered.
- The default live-worker limit is two, the hard limit is three, and the
  default A-to-B prompt budget is four with a hard maximum of twelve.

Advanced users can inspect the version-matched JSON command surface after the
skill is loaded with `python3 scripts/orchestrate.py guide`. Ordinary users do
not need to call it directly.

## Managed processes

Finite commands run with Bash and need no process follow-up. A command that is still running returns a managed process handle instead of blocking the agent. For noninteractive work, the handoff includes a `{"action":"wait",...}` call with the real session ID and cursor. For planned terminal input, start Bash with open stdin and a PTY; the handoff leads with a `{"action":"write",...}` call containing the real session ID, and the write result supplies the wait call using the exact `nextCursor returned by the write`. Use a PTY only for terminal interaction—long duration alone does not require one.

The model-facing process tool uses one `action` field for polling, waiting, acknowledged stdin writes, interrupts, and terminal-state recovery; it does not expose namespaced tools such as `process.wait`.

- The `wait` action waits for terminal state and does not change the command timeout.
- Model-generated camelCase or collapsed process fields are recovered only for documented process arguments; unknown or conflicting fields still fail strict validation.
- Pipe-style `eof=true` is rejected on PTYs without closing their input; send explicit terminal control characters through `write_raw`.
- If a wait deadline expires, the command is not killed; a later wait continues from the returned cursor.
- Live output is bounded to 64 MiB per process and reports `output_limit` when crossed.
- Completed metadata is retained for bounded recovery.
- Travis234 cannot reattach a running process after an application restart.

Use `tmux` for durable development servers, watchers, REPLs, test loops, and long builds. Travis234 namespaces tmux sessions to the current workspace, preserves fast-exiting command output, and requires explicit cleanup with the returned logical or resolved session name.

### Durable output artifacts

When a persistent session truncates command or managed-process output, Travis234 promotes the completed sanitized output into session-authorized content-addressed storage. The model sees only an opaque `artifact-...` ID and reads it in bounded byte pages. The same ID remains readable after `/resume`, and `/fork` or `/clone` copies only references reachable from the selected branch without copying the underlying object. Small output stays in ordinary session history and creates no artifact object; in-memory sessions remain entirely ephemeral.

Artifact objects live below `~/.travis234/agent/artifacts/objects/`, while authorization lives in `<session>.artifacts.jsonl`. Default per-object, per-session, installation, and free-space limits are documented in [settings](docs/settings.md). A storage or quota failure does not change a successful tool effect: the bounded result carries `artifactUnavailable` and no host path. Collection is explicit, conservative, and fails closed if any manifest cannot be validated.

Subagent management tools stay outside ordinary model turns. Explicit delegation, multiple-agent, parallel-worker, split-work, or independent-review requests expose them temporarily; an explicit request not to use subagents always wins. Coding children receive bounded workspace-write access to `read`, `grep`, `find`, `ls`, `bash`, `process`, `tmux`, `edit`, and `write`, further narrowed by a matching typed role. Concurrent children must own disjoint files, verify requested changes, and report changed-file evidence. Typed results may return schema-validated structured output and explicitly declared durable artifacts; legacy expanded result access remains available. Child-owned managed processes are cleaned up when the child ends, while parent processes and durable tmux sessions remain independently owned.

## Production sandbox

The release image runs as the unprivileged `travis` user. The npm launcher mounts only the chosen workspace and isolated Travis234 state, drops Linux capabilities, enables `no-new-privileges`, and forwards a dotenv file only when the user explicitly supplies `--dotenv`.

```bash
travis234 --cwd /path/to/project
```

Default image: `ghcr.io/htooayelwinict/travis234`

## Verification

### Local gates

```bash
PYTHONPATH=. .venv/bin/python -m pytest tests -q
npm --prefix packages/travis234-cli test
npm --prefix packages/travis234-cli run pack:dry-run
python -m build
.venv/bin/python scripts/verify_acceptance.py --parity-json
```

The parity report maps 78 pinned Pi behaviors—including all 33 extension events—and 11 Hermes compaction behaviors to concrete tests, with intentional Travis safety divergences called out explicitly. The repository also carries focused architecture, provider, compaction, process-ownership, cancellation, extension, installed-wheel, container, and release-contract tests. See the [full verification record](docs/verification/full-suite.md).

### Manual 21-prompt TUI acceptance

Production acceptance uses the real installed console entry point in an attached background PTY—not the eval runner, a scripted prompt driver, or `python -m travis.cli`.

```bash
TRAVIS234_CODING_AGENT_DIR=/tmp/travis234-acceptance/agent \
uv run travis234 \
  --cwd /tmp/travis234-acceptance/workspace \
  --dotenv .env \
  --temperature 0.2 \
  --thinking high \
  --event-trace /tmp/travis234-acceptance/events.jsonl \
  --conversation-log /tmp/travis234-acceptance/conversation.jsonl
```

Run `/model mimo`, select `openrouter/xiaomi/mimo-v2.5-pro`, and enter the 21 scenarios in `evals/scenarios.json` manually, one at a time. For every completed prompt:

1. Wait until the TUI is idle and inspect the final answer.
2. Verify edits, tool choices, persistence, process ownership, and recovery behavior.
3. Record footer tokens, context percentage, and compaction state.
4. Run the scenario verifier outside the TUI.
5. Classify failures as model quality, provider translation, context management, runtime/tooling, or environment behavior.

The same session must exercise extension creation and `/reload`, lazy skill loading, a reviewer subagent, managed process stdin and cancellation, repeated Ctrl-C escalation, `/session`, manual `/compact`, automatic compaction, and a dependent post-compaction prompt. Exit with `/exit` and confirm that no owned process remains.

A paid provider failure stops the run for diagnosis. A weak model answer is recorded as model quality and does not, by itself, justify a runtime change.

### Five-scenario native-TUI acceptance

Use this shorter protocol for scrollback, selection, themes, Markdown, tools, resize, and multiline regressions. It must use the installed `travis234` console entry point in a real PTY with isolated state—not `python -m`, a fake terminal, or the eval runner.

```bash
rm -rf /tmp/travis234-tui-acceptance
mkdir -p /tmp/travis234-tui-acceptance/workspace
cp README.md /tmp/travis234-tui-acceptance/workspace/README.md
TRAVIS234_CODING_AGENT_DIR=/tmp/travis234-tui-acceptance/agent \
uv run travis234 \
  --cwd /tmp/travis234-tui-acceptance/workspace \
  --dotenv .env \
  --temperature 0.2 \
  --thinking high
```

Run `/model mimo`, select `openrouter/xiaomi/mimo-v2.5-pro`, then complete these five prompts in the same session:

1. `Return a numbered diagnostic checklist with 80 short lines, then end with NATIVE-HISTORY-END.` Scroll with the wheel/touchpad, Shift+PageUp/PageDown or tmux history; drag-select lines near the top and copy them. The prompt must remain usable at the live bottom.
2. `Show a compact Markdown demo containing a heading, quote, bullets, ordered steps, inline code, a fenced diff, a link, and a two-column table.` Verify semantic styling, clickable-link behavior when supported, clean narrow-table fallback, and no raw Markdown fences.
3. Enter `Explain the difference between` then insert a newline with Shift+Enter or Alt+Enter, enter `terminal scrollback and an application viewport`, and submit with Enter. Verify that the provider receives one prompt containing the newline and that Up/Down preserves the intended column before submission.
4. `Read README.md and report only its product name, Python version, and the six built-in TUI theme names.` Verify pending/success tool surfaces, stable output ordering, and that selection/copy remain terminal-native while the tool runs.
5. Preview Neon Oni, cancel, preview Blood Circuit, commit, resize through roughly 40/80/120 columns, then enter `Reply exactly: THEME-RESIZE-OK`. Verify exact preview restoration, persisted commit, bounded line widths, visible context pressure, and a clean final prompt.

Repeat scenario 1 with `NO_COLOR=1`, and once inside tmux when available. Exit with `/exit`; the terminal must restore cursor, bracketed-paste, and mouse state without deleting native history.

## Distribution identity

| Surface | Contract |
|---|---|
| Product and repository | `Travis234` / `travis234` |
| Python distribution | `travis234` |
| Python import package | `travis` |
| CLI command | `travis234` |
| npm package | `@htooayelwinict/travis234` |
| Container image | `ghcr.io/htooayelwinict/travis234` |
| Container user | `travis` |
| Environment prefix | `TRAVIS234_*` |

This is a hard cutover. Legacy runtime aliases, state paths, and migration fallbacks are not supported.

## License

Travis234 is distributed under the [MIT License](LICENSE). See [NOTICE.md](NOTICE.md) for attribution and notices.

<p align="center">
  <strong>Travis234</strong><br>
  Built for developers who need the agent to keep working.
</p>
