terella 0.19.1

terella agent
# terella

<p align="center">
  <img src="terella.gif?v=8" alt="terella" width="33%" />
</p>

Terella is an open, local-first workflow runtime for repo agents: it turns Claude, Codex, Gemini, Copilot, Cline, Junie, Cursor, and other agent CLIs into repeatable software-factory workflows across desktop, web, CLI, and GitHub Actions.

- Desktop
- Web
- CLI
- GitHub Actions

## Design
A growing codebase is less a straight road than a shifting field of signatures: accounts, permissions, documentation, compliance, security, issues, and release pressure all pull in different directions at once. Terella is built to help agents read those signals, orient themselves, and move work forward in the right sequence when no single pair of hands can carry the whole effort alone.

## Quickstart
```shell
$ cargo binstall terella
$ terella --help
```

New to terella? Start with the [Getting started guide](https://terella.dev/docs/getting-started.html).

## CLI examples

```shell
# Launch the desktop UI (default subcommand)
$ terella

# Review every open PR in the current repo
$ terella code-review

# Work a single issue end-to-end (drafts a branch + PR)
$ terella issue 42

# Address review threads on a PR
$ terella fix-pr 1337

# Continuously work issues from a tracker issue
$ terella loop 7

# Sweep open issues, PRs, local branches, and tracker bodies
$ terella housekeeping

# Refresh root-level project docs against the current state of the code
$ terella refresh-docs

# Serve the web UI on http://localhost:8080 (override with --port)
$ terella serve
$ terella serve --port 3030

# Pick a different agent CLI on the fly
$ terella --agent codex code-review
$ terella --agent gemini issue 42

# List available workflow presets, or peek inside one
$ terella presets
$ terella presets xp

# Run a workflow under a different preset (overrides terella.toml)
$ terella --preset xp ideation
```

`--agent` accepts `claude`, `cline`, `codex`, `copilot`, `gemini`, `junie`, `xai`, `cursor` (default: `claude`). The matching CLI must be installed and authenticated. `--auto` passes adapter-specific flags that reduce permission prompts and, for two-phase workflows (ideation, housekeeping, sprint-planning, retrospective, etc.), synthesizes stand-in feedback so the draft chains straight into finalize without a human in the loop — without `--auto` the CLI stops after the draft so you can review before any side effects fire. `--dry-run` prints planned prompts and actions without making supported changes. `--preset <name>` swaps the workflow preset for a single invocation (use `terella presets` to see what's available; `terella presets <name>` lists the workflows that preset ships with).

## Desktop UI

The desktop app is split into a workflow sidebar and an editor panel. The sidebar
handles agent/model selection, local inference settings, workflow presets,
workflow actions, tracker issues, open issues, and open PRs. The editor panel has
tabs for:

- **Agent Output** — streamed assistant, tool, and log events.
- **Files** — files read or changed by the agent, plus a repository file browser.
- **Personas** — a User Personas Studio for creating, editing, deleting, and
  natural-language drafting persistent personas.
- **Security** — local security scan findings and JSON export.
- **Interview** — multi-round structured interview flows.
- **Chat** — free-form project chat with the selected agent.

Personas are stored as JSON files in the `personas/` directory beside the
resolved `user_personas` skill file. With automatic defaults, that directory is
**`.terella/skills/user-personas/personas/`** when you keep forked skills there,
else **`assets/skills/user-personas/personas/`** when present (upstream Terella’s
bundled layout), else beside the materialized `SKILL.md` under your OS app-data
directory — see **Skill paths** under Configuration below. If you override
`[skills].user_personas`, the Personas tab reads and writes next to that custom skill
path so UXR workflows and the studio share the same persona set.

## Configuration (`terella.toml`)

terella reads `terella.toml` from the repo root on every launch (the legacy filename `dev.toml` is still honored as a fallback). Every field is optional — drop in only what you want to change. The full surface looks like this:

**Skill paths (defaults):** if you omit `[skills]`, terella searches in order — repo-relative **`.terella/skills/.../SKILL.md`** when present (**recommended overrides** for forks and application repos); else **`assets/skills/.../SKILL.md`** when present (**upstream Terella’s embedded source tree**, unchanged here); otherwise **absolute** paths to the bundled copy materialized under the OS app-data directory — typically **`$HOME/Library/Application Support/terella/skills`** on macOS, **`$XDG_DATA_HOME/terella/skills`** (or **`~/.local/share/terella/skills`**) on Linux — so workflows work with no copied skills at all. If both layouts exist in the checkout, **`.terella/skills/` wins**. Explicit `[skills]` entries override everything.

```toml
# ── Top-level ─────────────────────────────────────────────────────────────
project_name           = "my-project"   # default: inferred from the repo dir
geodynamo_url          = "https://field.terella.dev/"
workflow_preset        = "default"      # default: "default"  (run `terella presets`)
bootstrap_agent_files  = true           # default: true   — legacy agent-file bootstrap flag
bootstrap_snapshot     = false          # default: false  — opt-in to toak-rs codebase snapshot on launch
use_subscription       = false          # default: false  — billing hint for adapters that support it

# ── Per-agent default model ───────────────────────────────────────────────
# Keys match `--agent` values. Empty / missing = adapter default.
[agent_models]
claude  = "claude-opus-4-7"
codex   = "gpt-5-codex"
gemini  = "gemini-2.5-pro"
grok    = "grok-4"

# ── Local inference (OpenAI-compatible endpoint) ──────────────────────────
[local_inference]
advanced = false                          # show advanced fields in the GUI
preset   = "vllm"                         # vllm | lm_studio | ollama | custom
base_url = "http://localhost:8000/v1"     # filled from preset unless preset = "custom"
model    = "qwen2.5-coder-32b-instruct"
# api_key stored via `terella`'s OS keychain; do not commit it.

# ── Skill files (optional — overrides automatic `.terella/` then `packages/terella-assets/` resolution) ─
# [skills]
# user_personas  = ".terella/skills/user-personas/SKILL.md"
# issue_tracking = ".terella/skills/issue-tracking/SKILL.md"

# ── Bot identity for code review / approvals ──────────────────────────────
# mode = "disabled" | "token" | "github_app". Tokens / private keys are
# stored in the OS keychain via the GUI, not in this file.
[bot]
mode            = "github_app"
app_id          = "1234567"
installation_id = "12345678"

# ── Security scan target paths ────────────────────────────────────────────
# List the files this project considers security-relevant. The local scanner
# runs its checks (hardcoded-secret detection, weak-crypto markers, plaintext
# http:// URLs) against each declared path; repository-wide hygiene checks
# (.gitignore coverage, SECURITY.md presence) run regardless. Leaving `paths`
# empty surfaces a configuration warning rather than guessing.
[security_scan]
paths = [
    # "src/auth.rs",
    # "src/api/handlers.rs",
]

# ── Visual regression command ────────────────────────────────────────────
# `command` is run exactly as configured from the repo root. `base_url` and
# `screenshots_dir` are kept as Terella context fields for continuity across
# workflows; they are not injected into the child process.
[visual_regression]
command = ["bun", "x", "playwright", "test", "tests/visual"]
base_url = "http://localhost:5173"
screenshots_dir = "tests/visual/screenshots"

# ── Deploy command ───────────────────────────────────────────────────────
# `command` is run exactly as configured from the repo root. `environment`
# and `url` are kept as Terella context fields for continuity across workflows;
# they are not injected into the child process.
[deploy]
command = ["./scripts/deploy.sh"]
environment = "staging"
url = "https://staging.example.com"
```

`user_personas` also controls the Personas Studio storage location: persona JSON
documents live in a `personas/` directory beside the resolved `SKILL.md` (whether
that path is repo-relative, materialized under app data, or set explicitly in `[skills]`).

`geodynamo_url` is optional for compatibility with the Field integration. It
should point at the Field Worker root; the autopilot action falls back to this value when its `geodynamo-url`
input is not set.

When the desktop app is launched in GUI mode and `geodynamo_url` is set **and** a
context token is available, terella fetches the project's shared context from
`GET {geodynamo_url}/contexts/{project}/context.json` (authenticated with
`Authorization: Bearer <token>`) once at startup and frames every agent run in
that session with it. This lets a team lead hand each worker a URL + token so a
group collaborates against the same leader-defined context for their domain. The
token is a secret, so it is not read from `terella.toml`; supply it via the
`TERELLA_GEODYNAMO_CONTEXT_TOKEN` env var (the URL may likewise be overridden
with `TERELLA_GEODYNAMO_URL`). The fetch is best-effort — if geodynamo is
unreachable, the token is rejected, or no context exists for the project, the app
launches normally without the extra context.

CLI flags (`--agent`, `--auto`, `--dry-run`, `--preset`) override matching `terella.toml` values for that single invocation. Secrets — agent API keys, GitHub bot tokens, GitHub App private keys — are not written to `terella.toml`; they're stored in the OS keychain by the GUI's settings panel or supplied via env vars (see the [GitHub Actions example](#github-actions) below).

## GitHub Actions
Every CLI subcommand above is also available as a GitHub Action — [**terella-project/terella-action**](https://github.com/terella-project/terella-action). Wire it to `pull_request`, `issues`, or `schedule` and your repo starts maintaining itself: issues become PRs, PRs get reviewed, review threads get addressed, weekly housekeeping happens on its own.

```yaml
- uses: terella-project/terella-action@main   # pin to a SHA or tag for production
  with:
    task: code-review
    agent: claude
  env:
    # ── Agent auth (pick the ones that match your `agent:` choice) ──
    CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}   # claude (preferred)
    # ANTHROPIC_API_KEY:     ${{ secrets.ANTHROPIC_API_KEY }}         # claude (alternative)
    # OPENAI_API_KEY:        ${{ secrets.OPENAI_API_KEY }}            # codex
    # GEMINI_API_KEY:        ${{ secrets.GEMINI_API_KEY }}            # gemini
    # GROK_CREDENTIALS:      ${{ secrets.GROK_CREDENTIALS }}          # xai (SuperGrok / X Premium+ OAuth)
    # XAI_API_KEY:           ${{ secrets.XAI_API_KEY }}               # xai (metered API; do not combine with GROK_CREDENTIALS)
    # (cline, copilot, junie, cursor authenticate via their own CLI login flow)

    # ── GitHub auth for the `gh` CLI terella shells out to ──
    GH_TOKEN: ${{ secrets.TERELLA_PAT || github.token }}              # PAT preferred so PRs trigger downstream workflows

    # ── Bot identity (so reviews/approvals don't run as the PR author) ──
    # Pick ONE of the three styles below.
    #
    # 1. Direct token:
    # DEV_BOT_TOKEN:           ${{ secrets.DEV_BOT_TOKEN }}
    #
    # 2. Token from a file:
    # DEV_BOT_TOKEN_PATH:      /path/to/token-file
    #
    # 3. GitHub App (mints installation tokens at runtime):
    DEV_BOT_APP_ID:          ${{ secrets.DEV_BOT_APP_ID }}
    DEV_BOT_INSTALLATION_ID: ${{ secrets.DEV_BOT_INSTALLATION_ID }}
    # DEV_BOT_PRIVATE_KEY is the *path* to a PEM. A prior step base64-decodes
    # secrets.DEV_BOT_PRIVATE_KEY_B64 into $RUNNER_TEMP/dev-bot.pem and exports it.

    # ── terella knobs ──
    # DEV_PROJECT_NAME: my-project   # override project name (otherwise inferred from the repo)
    # DISABLE_TOAK: "1"              # skip the toak-rs bootstrap snapshot (faster, less context)

    # ── Diagnostics ──
    # RUST_LOG: info                 # the action defaults to info; bump to debug/trace if you need more
```

The full hands-off setup (PAT, OAuth token, GitHub App credentials, branch protection) is documented step-by-step in the [terella documentation](https://terella.dev/docs/).

## Status: Unstable (Active Development)
Expect unexpected breaking changes.

## Docs
Full documentation lives at **[terella.dev/docs](https://terella.dev/docs/)**:

- [Overview](https://terella.dev/docs/terella-overview.html)
- [Getting started](https://terella.dev/docs/getting-started.html)
- [Installation and build](https://terella.dev/docs/installation-and-build.html)
- [CLI reference](https://terella.dev/docs/cli-reference.html)
- [Workflows and presets](https://terella.dev/docs/workflow-and-presets.html)
- [Configuration reference](https://terella.dev/docs/configuration-reference.html)
- [Desktop and web UI](https://terella.dev/docs/desktop-and-web-ui.html)
- [Architecture](https://terella.dev/docs/architecture.html)
- [Security and privacy](https://terella.dev/docs/security-and-privacy.html)
- [Development and testing](https://terella.dev/docs/development-and-testing.html)

## Built by terella

- [geoffsee/aurora](https://github.com/geoffsee/aurora) - vdj via Ableton osc w/ midi+vst
- [geoffsee/midi-vibe](https://github.com/geoffsee/midi-vibe) - write music with typescript
- [geoffsee/tx-monitor](https://github.com/geoffsee/tx-monitor) - network traffic monitor
- [geoffsee/cortex-enigma](https://github.com/geoffsee/cortex-enigma) - Prompting UI

## License & Revenue Sharing
terella is dual-licensed under [MIT](LICENSE-MIT) or [Apache-2.0](LICENSE-APACHE); individuals, small teams, and organizations under the revenue threshold use it under those terms with no further obligation. Organizations (government or non-government) with **US $500,000+** annual revenue that put a significant portion of the code or product into production are asked to make contact first and share fairly — see [`REVENUE-SHARING.md`](REVENUE-SHARING.md).

## Contributing
- Open Issue -> Fork Repo -> Create Pull Request

## Contact
- File an issue for any questions or feedback.