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
Binary file added .github/assets/dashboard-overview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/assets/session-editor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
120 changes: 105 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,74 @@
<div align="center">

<img src="./src/web/favicon.svg" alt="OpenCode Dashboard" width="96" />

# OpenCode Dashboard

A local dashboard for monitoring OpenCode sessions and agent activity across projects.
**A private, local dashboard for OpenCode sessions, projects, and agent activity.**

Open the dashboard from the TUI with `/dashboard`. No prompts, responses, or tool payloads leave your machine.

</div>

![OpenCode Dashboard overview with demo data](./.github/assets/dashboard-overview.png)

> [!NOTE]
> The screenshots use fictional projects, paths, sessions, and models. No user data is included.

## Why OpenCode Dashboard?

OpenCode Dashboard gives you one browser view of activity across every local OpenCode project. It combines live process updates with persisted session history, so active work and older sessions remain easy to find.

- Monitor running, waiting, retrying, idle, failed, and stale sessions.
- Browse sessions by project, including parent and subagent relationships.
- See agent usage, active counts, models, and recent activity.
- Rename or delete sessions through the connected OpenCode process.
- Retain dashboard state in the browser between collector restarts.

![Editing a session with demo data](./.github/assets/session-editor.png)

## Privacy

The dashboard runs entirely on your machine and binds to `127.0.0.1:4747`.

It collects session metadata only:

| Included | Never collected |
| --- | --- |
| Session ID and title | Prompts and responses |
| Project name and local directory | Model reasoning |
| Agent, model, status, and timestamps | Tool inputs and outputs |
| Parent/child session relationships | Credentials and environment variables |

Nothing is sent to an external telemetry or storage service.

## Requirements

- [OpenCode](https://opencode.ai/) `1.18.30` or newer
- [Bun](https://bun.sh/) for installation from source
- A browser available through your operating system's default URL opener

## Installation

OpenCode loads server and TUI plugins separately. Add the package to both global configuration files.
OpenCode Dashboard is installed as a [local plugin](https://opencode.ai/docs/plugins/#from-local-files). Clone it into your OpenCode configuration directory and build it:

```bash
git clone https://github.com/RayXpub/opencode-dashboard.git ~/.config/opencode/opencode-dashboard
cd ~/.config/opencode/opencode-dashboard
bun install --frozen-lockfile
bun run build
```

OpenCode loads server and TUI plugins separately. Add their local entrypoints to both global configuration files. These paths are relative to `~/.config/opencode/`, so they work without machine-specific absolute paths.

`~/.config/opencode/opencode.json`:

```json
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-dashboard"]
"plugin": [
"./opencode-dashboard/dist/server/index.js"
]
}
```

Expand All @@ -20,13 +77,52 @@ OpenCode loads server and TUI plugins separately. Add the package to both global
```json
{
"$schema": "https://opencode.ai/tui.json",
"plugin": ["opencode-dashboard"]
"plugin": [
"./opencode-dashboard/dist/tui/index.js"
]
}
```

Restart OpenCode after changing either configuration file. Run `/dashboard` in the TUI to start the local collector and open the dashboard in your default browser.
Preserve any plugins already present in those arrays. Restart OpenCode after changing either file.

The dashboard binds to `127.0.0.1:4747` and remains available while the OpenCode TUI that launched it is running.
## Usage

Run the following slash command from the OpenCode TUI:

```text
/dashboard
```

The command starts or reconnects to the local collector, synchronizes persisted sessions across projects, and opens `http://127.0.0.1:4747` in your default browser.

The dashboard remains available while the OpenCode TUI that launched its collector is running. Session rename and delete actions require at least one connected OpenCode server process.

## Updating

Pull the latest changes and rebuild the plugin:

```bash
cd ~/.config/opencode/opencode-dashboard
git pull --ff-only
bun install --frozen-lockfile
bun run build
```

Restart OpenCode after rebuilding so both plugin entrypoints are reloaded.

## Troubleshooting

### `/dashboard` is unavailable

Confirm the TUI entrypoint is present in `~/.config/opencode/tui.json`, then fully quit and restart OpenCode. Configuration-time plugins are not hot-reloaded.

### The dashboard does not open

Visit `http://127.0.0.1:4747` directly. If it is unavailable, check whether another application already uses port `4747` and review the OpenCode logs for plugin errors.

### Rename or delete is unavailable

Session actions are relayed through a connected OpenCode server plugin. Confirm the server entrypoint is present in `~/.config/opencode/opencode.json` and restart OpenCode.

## Development

Expand All @@ -35,7 +131,7 @@ bun install --frozen-lockfile
bun run dev
```

Quality checks:
Run the complete quality suite before submitting a change:

```bash
bun run lint
Expand All @@ -44,16 +140,10 @@ bun test
bun run build
```

## Releases

Add a changeset to each pull request with a user-facing change:
User-facing changes require a Changeset:

```bash
bun run changeset
```

After changesets reach `main`, the release workflow creates or updates a version pull request. Merging the version pull request updates `package.json` and `CHANGELOG.md`, then creates and pushes a Git tag such as `v0.1.0`.

This package is private and the release workflow has no npm publish command or npm token. Releases exist only as versions, changelog entries, and Git tags.

GitHub repository settings must allow GitHub Actions to create pull requests under **Settings > Actions > General > Workflow permissions**.
The package is private. Releases consist of version updates, changelog entries, and Git tags; the release process never publishes to npm.
8 changes: 4 additions & 4 deletions src/web/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, type FormEvent } from "react"
import { useState, type SubmitEvent } from "react"
import type { DashboardSession, DashboardState } from "../shared/protocol"
import { useDashboard } from "./hooks/use-dashboard"
import { useSessionActions } from "./hooks/use-session-actions"
Expand Down Expand Up @@ -289,7 +289,7 @@ function SessionActionDialog({
onTitleChange: (title: string) => void
onDelete: () => void
onClose: () => void
onSubmit: (event: FormEvent<HTMLFormElement>) => void
onSubmit: (event: SubmitEvent<HTMLFormElement>) => void
}) {
return (
<div className="fixed inset-0 z-[100] grid place-items-center bg-black/50 p-4" role="presentation" onMouseDown={onClose}>
Expand Down Expand Up @@ -396,7 +396,7 @@ export function App() {
setDialog({ session })
}

async function submitSessionAction(event: FormEvent<HTMLFormElement>) {
async function submitSessionAction(event: SubmitEvent<HTMLFormElement>) {
event.preventDefault()
if (!dialog) return

Expand Down Expand Up @@ -454,7 +454,7 @@ export function App() {
OPEN<span className="opacity-55">CODE</span>
</div>
<span className="hidden text-[11px] font-medium uppercase tracking-[0.1em] text-[var(--stats-faint)] sm:inline">
Session data
Dashboard
</span>
</div>
<div className="flex h-8 items-center gap-2 border border-[var(--stats-line-strong)] px-3 text-[10px] font-medium uppercase tracking-[0.08em] text-[var(--stats-muted)]">
Expand Down
Loading