Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/AGENT_CLIENT_PROTOCOL.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ The ACP protocol implementation is identical to upstream OpenCode — no Franken

However, Frankencode's additional tools are **transparently available** to ACP clients. When an ACP client sends a prompt, the agent can use all Frankencode tools including `context_edit`, `thread_park`, `classifier_threads`, `distill_threads`, `verify`, `refine`, and `objective_set`. These appear as standard tool calls in the ACP event stream — no client-side changes needed.

See [FRANKENCODE_DIFFERENCES.md](FRANKENCODE_DIFFERENCES.md) for the complete list of Frankencode additions.
See [FRANKENCODE.md](FRANKENCODE.md) for the complete list of Frankencode additions.

---

Expand All @@ -152,4 +152,4 @@ See [FRANKENCODE_DIFFERENCES.md](FRANKENCODE_DIFFERENCES.md) for the complete li
- [API_PROVIDERS.md](API_PROVIDERS.md) — provider/model selection (used in ACP NewSessionRequest)
- [context-editing.md](context-editing.md) — context editing tools available through ACP
- [EFFECTIFICATION.md](EFFECTIFICATION.md) — Effect architecture (ACP sessions boot via InstanceLifecycle)
- [FRANKENCODE_DIFFERENCES.md](FRANKENCODE_DIFFERENCES.md) — all Frankencode vs OpenCode differences
- [FRANKENCODE.md](FRANKENCODE.md) — all Frankencode vs OpenCode differences
4 changes: 2 additions & 2 deletions docs/API_PROVIDERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ Frankencode adds features at the **session/tool layer** that work with all provi
- **Refine tool** (`src/tool/refine.ts`) — evaluator-optimizer loop, spawns child sessions on the same provider
- **Evaluator/optimizer agents** — use the session's model for code review scoring

See [FRANKENCODE_DIFFERENCES.md](FRANKENCODE_DIFFERENCES.md) for the complete list.
See [FRANKENCODE.md](FRANKENCODE.md) for the complete list.

---

Expand All @@ -223,4 +223,4 @@ See [FRANKENCODE_DIFFERENCES.md](FRANKENCODE_DIFFERENCES.md) for the complete li
- [EFFECTIFICATION.md](EFFECTIFICATION.md) — Effect architecture (ProviderAuthService, ConfigService are Effect services)
- [agents.md](agents.md) — agents that use providers (evaluator, optimizer inherit session model)
- [AGENT_CLIENT_PROTOCOL.md](AGENT_CLIENT_PROTOCOL.md) — model selection via ACP NewSessionRequest
- [FRANKENCODE_DIFFERENCES.md](FRANKENCODE_DIFFERENCES.md) — all Frankencode vs OpenCode differences
- [FRANKENCODE.md](FRANKENCODE.md) — all Frankencode vs OpenCode differences
2 changes: 1 addition & 1 deletion docs/EFFECTIFICATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ Frankencode completed the Effect-ification ahead of upstream in several areas:

## See Also

- [FRANKENCODE_DIFFERENCES.md](FRANKENCODE_DIFFERENCES.md) — complete list of Frankencode vs OpenCode changes
- [FRANKENCODE.md](FRANKENCODE.md) — complete list of Frankencode vs OpenCode changes
- [API_PROVIDERS.md](API_PROVIDERS.md) — provider architecture (ProviderAuthService is an Effect service)
- [context-editing.md](context-editing.md) — context editing tools (use Effect services for state management)
- [AGENT_CLIENT_PROTOCOL.md](AGENT_CLIENT_PROTOCOL.md) — ACP protocol (sessions boot via InstanceLifecycle)
Expand Down
134 changes: 105 additions & 29 deletions docs/FRANKENCODE_DIFFERENCES.md → docs/FRANKENCODE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,55 @@
# Frankencode vs OpenCode: All Differences
# Frankencode

This document lists every change Frankencode makes relative to upstream [OpenCode](https://github.com/anomalyco/opencode) (`dev` branch).
Frankencode is a fork of [OpenCode](https://github.com/anomalyco/opencode) that adds subagent tabs, fork agents, context editing, and a verification/refinement loop.

---

## Tab Bar and Subagent Tabs

OpenCode shows one session at a time. Frankencode adds a **tab bar** at the top of the session view:

```
Main │ + │ S1 │ S2 │ F1
```

- **Main** — the root session (always present)
- **+** — creates a fork agent (copies Main's conversation history)
- **S1, S2, ...** — subagents spawned by the LLM's task tool
- **F1, F2, ...** — fork agents created by the user via `+`

**Navigation:**

| Key | Action |
|-----|--------|
| Tab | Toggle focus between tab bar and chat prompt |
| ←/→ | Navigate tabs (immediately shows selected session) |
| ↓ / Escape | Return focus to chat prompt |
| Enter/Space | Activate selected tab (spawn fork if on `+`) |
| x | Kill selected agent |
| Shift+Tab | Cycle agent type (Build/Plan/etc.) |
| Ctrl+C | First: abort all + show hint. Second: exit app |
| Click | Select any tab and focus bar |

Implementation: [`tab.ts`](../packages/opencode/src/cli/cmd/tui/routes/session/tab.ts) (hook + logic), [`tabbar.tsx`](../packages/opencode/src/cli/cmd/tui/routes/session/tabbar.tsx) (renderer)

---

## Fork Agents

Fork agents are user-created branches of the main conversation. Pressing `+` in the tab bar forks Main's full conversation history into a new child session.

| Feature | Fork Agent (F) | Subagent (S) |
|---------|---------------|--------------|
| Created by | User via `+` | LLM via task tool |
| Conversation history | Copied from Main | Starts empty |
| Can spawn subagents | No (denied by permission) | Yes |
| Tab color | Yellow | Agent color |
| Lifetime | Until user kills with `x` | Auto-terminates when done |
| Promptable | Yes (user types in chat) | LLM-driven |

Fork agents receive a system prompt explaining they cannot spawn subagents and should suggest delegating to Main if needed.

Implementation: `Session.fork()` in [`session/index.ts`](../packages/opencode/src/session/index.ts), fork system prompt in [`prompt.ts`](../packages/opencode/src/session/prompt.ts)

---

Expand All @@ -13,6 +62,7 @@ This document lists every change Frankencode makes relative to upstream [OpenCod
| Context Editing | `src/context-edit/index.ts` | 6 edit operations (hide, unhide, replace, externalize, annotate, mark) |
| Side Threads | `src/session/side-thread.ts`, `src/session/side-thread.sql.ts` | Project-level deferred findings that survive across sessions |
| Objective Tracker | `src/session/objective.ts` | Extracts and tracks session objective from first user message |
| Tab Bar | `src/cli/cmd/tui/routes/session/tab.ts`, `tabbar.tsx` | `useTab` hook + pure renderer for subagent tabs |

See [context-editing.md](context-editing.md) and [schema.md](schema.md) for details.

Expand All @@ -39,13 +89,13 @@ See [context-editing.md](context-editing.md) for usage details.

## New Agents (5)

| Agent | Prompt File | Purpose | Default |
|-------|-------------|---------|---------|
| classifier | `src/agent/prompt/classifier.txt` | Label messages as main/side/mixed with topics | Enabled (hidden) |
| focus | `src/agent/prompt/focus.txt` | Context cleanup based on classification | Disabled |
| focus-rewrite-history | `src/agent/prompt/rewrite-history.txt` | Full conversation rewrite with confirmation | Disabled |
| evaluator | `src/agent/prompt/evaluator.txt` | Score code changes 1-10 with feedback | Enabled (hidden) |
| optimizer | `src/agent/prompt/optimizer.txt` | Improve code based on evaluator feedback | Enabled (hidden) |
| Agent | Purpose | Default |
|-------|---------|---------|
| classifier | Label messages as main/side/mixed with topics | Enabled (hidden) |
| focus | Context cleanup based on classification | Disabled |
| focus-rewrite-history | Full conversation rewrite with confirmation | Disabled |
| evaluator | Score code changes 1-10 with feedback | Enabled (hidden) |
| optimizer | Improve code based on evaluator feedback | Enabled (hidden) |

See [agents.md](agents.md) for configuration and model recommendations.

Expand Down Expand Up @@ -77,9 +127,7 @@ See [agents.md](agents.md) for configuration and model recommendations.
| `edit_graph_head` | Per-session DAG head tracking + branches |
| `side_thread` | Project-level side threads |

Plus 2 new fields on `PartBase` (all message parts): `edit` (EditMeta) and `lifecycle` (LifecycleMeta).

See [schema.md](schema.md) for column details.
Plus 2 new fields on `PartBase` (all message parts): `edit` (EditMeta) and `lifecycle` (LifecycleMeta). See [schema.md](schema.md) for column details.

---

Expand All @@ -91,27 +139,30 @@ Added to the message processing pipeline in `src/session/prompt.ts`:
2. **`filterEphemeral()`** — drops ephemeral command messages entirely
3. **Deterministic sweeper** — auto-hides/externalizes parts based on lifecycle markers
4. **Focus status injection** — adds objective + parked threads to system prompt when context_edit is available
5. **Fork agent prompt** — tells fork agents they cannot spawn subagents

---

## Effect-ification Differences
## Keybinding Changes

Frankencode completed several Effect-ification stages ahead of upstream:
| Keybind | OpenCode | Frankencode |
|---------|----------|-------------|
| Tab | Cycle agents | Toggle tab bar focus |
| Shift+Tab | (none) | Cycle agents (Build/Plan/etc.) |
| ←/→ (tab bar focused) | (N/A) | Navigate tabs |
| Ctrl+C | Exit immediately (if input empty) | Double-press to exit (first press aborts + shows hint) |

| Difference | Frankencode | Upstream |
|------------|-------------|----------|
| `src/project/instance.ts` | Deleted, split into InstanceALS + InstanceLifecycle + InstanceContext | Still has `instance-state.ts` using ScopedCache |
| ALS fallback patterns | 0 remaining (all 59 eliminated) | ~36 deferred |
| Test compatibility | `test/fixture/instance-shim.ts` for 58 test files | N/A |
| TUI tests | 81 component tests + tmux integration harness | Fewer tests |
---

## Promptable Agent Mode Switching

See [EFFECTIFICATION.md](EFFECTIFICATION.md) for architecture details.
Build and Plan agents switch via `plan_enter`/`plan_exit` tools — see [agents.md](agents.md#promptable-mode-switching) for details.

---

## Type Safety Improvements
## Type Safety

Frankencode's type safety audit eliminated ~236 `any` types:
~236 `any` types eliminated. Strong Zod schemas for all message types. 14 documented exceptions at SDK boundaries.

| Area | Changes |
|------|---------|
Expand All @@ -122,17 +173,29 @@ Frankencode's type safety audit eliminated ~236 `any` types:

---

## Bug Fixes (51 total)
## Effect-TS Architecture

22 Effect services, dual-layer context model (InstanceALS + InstanceContext). See [EFFECTIFICATION.md](EFFECTIFICATION.md) for details.

| Difference | Frankencode | Upstream |
|------------|-------------|----------|
| `src/project/instance.ts` | Deleted, split into InstanceALS + InstanceLifecycle + InstanceContext | Still has `instance-state.ts` using ScopedCache |
| ALS fallback patterns | 0 remaining (all 59 eliminated) | ~36 deferred |
| Test compatibility | `test/fixture/instance-shim.ts` for 58 test files | N/A |

---

## Bug Fixes (64 total)

See `BUGS.md` at repo root for the complete bug tracker.

| Range | Category |
|-------|----------|
| B1-B9 | Upstream backports (Phase 1) |
| B10-B16 | Upstream backports (Phase 2) |
| B17-B22 | Upstream app fixes (Phase 3) |
| B23-B46 | Code review fixes (CAS, circuit breaker, evaluator, scripts, lock starvation, etc.) |
| B47-B52 | Final pass (objective cache, session cleanup, mark transaction, queue, bus errors) |

See `BUGS.md` at repo root for the complete bug tracker.
| B23-B52 | Code review fixes (CAS, circuit breaker, evaluator, session cleanup, etc.) |
| B53-B64 | QA rounds 1-6 (plugin hooks, markdown injection, MCP type mismatch, ripgrep, file count, processor timing) |

---

Expand All @@ -142,7 +205,20 @@ These areas are identical to upstream OpenCode:

- **API providers** — all 21+ providers, models.dev integration, transform pipeline (see [API_PROVIDERS.md](API_PROVIDERS.md))
- **ACP support** — full ACP v1 protocol, same capabilities (see [AGENT_CLIENT_PROTOCOL.md](AGENT_CLIENT_PROTOCOL.md))
- **TUI** — same terminal UI (OpenTUI + SolidJS)
- **Session/message format** — same MessageV2 schema (extended with EditMeta/LifecycleMeta)
- **Plugin system** — same plugin hooks (plus `context.edit.before`/`context.edit.after`)
- **Permission system** — same PermissionNext framework

---

## Documentation Index

| Document | What it covers |
|----------|---------------|
| [agents.md](agents.md) | Agent config, mode switching, fork agents, model recommendations |
| [context-editing.md](context-editing.md) | Edit operations, lifecycle markers, sweeper, slash commands |
| [schema.md](schema.md) | Database schema (4 new tables, part extensions) |
| [EFFECTIFICATION.md](EFFECTIFICATION.md) | Effect-TS services, layers, dual context |
| [API_PROVIDERS.md](API_PROVIDERS.md) | 21+ LLM providers |
| [AGENT_CLIENT_PROTOCOL.md](AGENT_CLIENT_PROTOCOL.md) | ACP v1 protocol for IDEs |
| [SECURITY_AUDIT.md](SECURITY_AUDIT.md) | CVEs, security issues |
8 changes: 5 additions & 3 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Frankencode Documentation

> **Frankencode** is a fork of [OpenCode](https://github.com/anomalyco/opencode) that adds context editing, content-addressable storage, an edit graph, focus agents, side threads, and a verification/refinement loop.
> **Frankencode** is a fork of [OpenCode](https://github.com/anomalyco/opencode) that adds context editing, subagent tabs, fork agents, content-addressable storage, an edit graph, focus agents, side threads, and a verification/refinement loop.

## Documentation Map

| Document | Description |
|----------|-------------|
| [FRANKENCODE_DIFFERENCES.md](FRANKENCODE_DIFFERENCES.md) | All differences between Frankencode and upstream OpenCode |
| [FRANKENCODE.md](FRANKENCODE.md) | **Start here** — all Frankencode features, diff vs upstream, tab bar, fork agents, context editing |
| [context-editing.md](context-editing.md) | Context editing tools, lifecycle markers, and deterministic sweeper |
| [agents.md](agents.md) | Frankencode-specific agents (classifier, focus, evaluator, optimizer) |
| [agents.md](agents.md) | Agents, mode switching, fork agents, model recommendations |
| [schema.md](schema.md) | Database schema changes (4 new tables, PartBase extensions) |
| [EFFECTIFICATION.md](EFFECTIFICATION.md) | Effect-TS architecture, 22 services, LayerMap, dual-layer context |
| [AGENT_CLIENT_PROTOCOL.md](AGENT_CLIENT_PROTOCOL.md) | ACP v1 protocol support for IDE integration |
Expand All @@ -23,6 +23,8 @@
|
ACP (JSON-RPC/stdio) or TUI or HTTP API
|
TUI Tab Bar: Main │ + │ S1 │ F1
|
InstanceLifecycle.boot(directory)
|
InstanceALS + InstanceContext (dual context)
Expand Down
2 changes: 1 addition & 1 deletion docs/SECURITY_AUDIT.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,5 +119,5 @@ From `SECURITY.md`:
## See Also

- [UPSTREAM_STATUS.md](../UPSTREAM_STATUS.md) — full upstream commit catalogue
- [FRANKENCODE_DIFFERENCES.md](FRANKENCODE_DIFFERENCES.md) — Frankencode vs OpenCode differences
- [FRANKENCODE.md](FRANKENCODE.md) — Frankencode vs OpenCode differences
- [EFFECTIFICATION.md](EFFECTIFICATION.md) — Effect architecture (relevant to service isolation)
32 changes: 19 additions & 13 deletions docs/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,25 +154,31 @@ All Frankencode agents inherit the session's model by default. Override per-agen

## Agent Visibility

| Agent | Tab-selectable | Mode | Default |
| --------------------- | :------------: | ---------------- | -------- |
| build | Yes | primary | enabled |
| plan | Yes | primary | enabled |
| general | Via `@general` | subagent | enabled |
| explore | Via `@explore` | subagent | enabled |
| classifier | No | subagent | enabled |
| focus | No | primary (hidden) | disabled |
| focus-rewrite-history | No | primary (hidden) | disabled |
| compaction | No | primary (hidden) | enabled |
| title | No | primary (hidden) | enabled |
| summary | No | primary (hidden) | enabled |
| Agent | Shift+Tab cycle | Tab bar | Mode | Default |
| --------------------- | :-------------: | :-----: | ---------------- | -------- |
| build | Yes | — | primary | enabled |
| plan | Yes | — | primary | enabled |
| general | No | S*n* | subagent | enabled |
| explore | No | S*n* | subagent | enabled |
| classifier | No | — | subagent | enabled |
| focus | No | — | primary (hidden) | disabled |
| focus-rewrite-history | No | — | primary (hidden) | disabled |
| compaction | No | — | primary (hidden) | enabled |
| title | No | — | primary (hidden) | enabled |
| summary | No | — | primary (hidden) | enabled |
| *(fork agent)* | No | F*n* | fork child | N/A |

**Shift+Tab cycle** — cycles the agent type (Build/Plan/Docs) for the current session.
**Tab bar** — subagents spawned by the LLM appear as S1, S2, etc. Fork agents appear as F1, F2, etc.

See [FRANKENCODE.md](FRANKENCODE.md#tab-bar-and-subagent-tabs) for full tab bar documentation.

---

## See Also

- [FRANKENCODE.md](FRANKENCODE.md) — tab bar, fork agents, and all Frankencode differences
- [context-editing.md](context-editing.md) — tools used by focus/classifier agents
- [API_PROVIDERS.md](API_PROVIDERS.md) — model selection for agents
- [AGENT_CLIENT_PROTOCOL.md](AGENT_CLIENT_PROTOCOL.md) — agents exposed via ACP protocol
- [EFFECTIFICATION.md](EFFECTIFICATION.md) — AgentService Effect layer
- [FRANKENCODE_DIFFERENCES.md](FRANKENCODE_DIFFERENCES.md) — all Frankencode additions
2 changes: 1 addition & 1 deletion docs/context-editing.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,5 +162,5 @@ See `test/context-edit/integration.test.ts` for the proof tests.

- [schema.md](schema.md) — database tables (cas_object, edit_graph_node/head, side_thread, PartBase extensions)
- [agents.md](agents.md) — classifier, focus, and focus-rewrite-history agents
- [FRANKENCODE_DIFFERENCES.md](FRANKENCODE_DIFFERENCES.md) — all Frankencode vs OpenCode changes
- [FRANKENCODE.md](FRANKENCODE.md) — all Frankencode vs OpenCode changes
- [EFFECTIFICATION.md](EFFECTIFICATION.md) — Effect services powering the context editing pipeline
2 changes: 1 addition & 1 deletion docs/schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,5 +134,5 @@ All new tables are created in a single migration: `20260315120000_context_editin

- [context-editing.md](context-editing.md) — tools that read/write these tables
- [agents.md](agents.md) — agents that create side threads and edit graph nodes
- [FRANKENCODE_DIFFERENCES.md](FRANKENCODE_DIFFERENCES.md) — all Frankencode vs OpenCode changes
- [FRANKENCODE.md](FRANKENCODE.md) — all Frankencode vs OpenCode changes
- [EFFECTIFICATION.md](EFFECTIFICATION.md) — database access via Drizzle ORM and Effect service layers
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ function init() {
const suspended = () => suspendCount() > 0

useKeyboard((evt) => {
if (evt.defaultPrevented) return
if (suspended()) return
if (dialog.stack.length > 0) return
for (const option of entries()) {
Expand Down
4 changes: 2 additions & 2 deletions packages/opencode/src/cli/cmd/tui/routes/session/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const WorkspaceInfo = (props: { workspace: Accessor<string | undefined> }) => {
)
}

export function Header() {
export function Header(props: { tabBar?: boolean }) {
const route = useRouteData("session")
const sync = useSync()
const session = createMemo(() => sync.session.get(route.sessionID)!)
Expand Down Expand Up @@ -100,7 +100,7 @@ export function Header() {
backgroundColor={theme.backgroundPanel}
>
<Switch>
<Match when={session()?.parentID}>
<Match when={session()?.parentID && !props.tabBar}>
<box flexDirection="column" gap={1}>
<box flexDirection={narrow() ? "column" : "row"} justifyContent="space-between" gap={narrow() ? 1 : 0}>
{Flag.OPENCODE_EXPERIMENTAL_WORKSPACES ? (
Expand Down
Loading
Loading