Skip to content
Back to skills

Walnut Console Ops

ASecurity

Operating the Walnut web UI (localhost:3456) via Playwright MCP tools — understanding the UI layout, chatting with main agent, interacting with sessions, monitoring status changes. Use when asked to test, verify, or interact with the Walnut web console as a human user would.

  • 32 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 1, 2026
developmentrustgoreacttestingdebuggingapifrontendbackend

Works with

  • claude code
  • cli
  • api
  • mcp

Security analysis

A100/100

Scanned October 1, 2026

npx -y skills add EvanZhang008/open-walnut --skill walnut-console-ops --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Walnut Console Ops?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Walnut Console Ops
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/evanzhang008-walnut-console-ops/badge)](https://www.skillsdirectory.com/skills/evanzhang008-walnut-console-ops)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: walnut-console-ops
description: Operating the Walnut web UI (localhost:3456) via Playwright MCP tools — understanding the UI layout, chatting with main agent, interacting with sessions, monitoring status changes. Use when asked to test, verify, or interact with the Walnut web console as a human user would.
requires:
  bins: []
---

# Walnut Web Console — How It Works

This skill explains the Walnut web UI so you can operate it confidently via Playwright MCP tools, acting as a human user.

**Which server.** Looking at the real console on :3456 is fine. Anything that creates or changes data to test a flow (a new task, a session, a sent message, a cron job) runs on a throwaway server instead: `npm run dev:ephemeral`, then open the printed port. Test data made on :3456 stays on the user's board. The ephemeral server's sessions and tools talk only to it (see "Live verification" in the repo AGENTS.md).

## Core Mental Models for SPA Console Testing

These principles are universal — they apply to any single-page app, not just Walnut.

### 1. Stay on one page — panels, not pages
SPAs show everything through panels that open/close on the same page. Don't navigate away to find something. The session panel opens inline when you click a session link. (The dedicated `/sessions` page was removed — `/sessions?id=…` links reroute to the home session columns.)

### 2. Disambiguate inputs by placeholder
Multiple input boxes coexist on screen. They look identical in the DOM. **Placeholder text** is the reliable discriminator. Check it before typing.

### 3. Same state, multiple renderings — verify all
One piece of state (e.g., "session mode") appears in 3+ places, each with different update paths (REST vs WebSocket vs React state). Check all of them. Bugs often show as one updating while another stays stale.

### 4. Act → Wait → Verify
Every action triggers async work. Pattern: **Act** → **Wait** (5-20s) → **Screenshot** (visual truth) → **Snapshot** (clickable refs). Skip the wait = see stale state.

### 5. Screenshot is ground truth
Screenshot shows what the user sees. DOM snapshot shows logical tree. When they disagree, trust the screenshot.

### 6. Refs are ephemeral
Playwright refs (`ref=e1234`) are tied to a specific DOM state. Any async change invalidates them. Always re-snapshot before interacting.

### 7. Build ≠ Deploy
Frontend changes (vite build) take effect on page refresh. Backend changes (npm run build) need server restart. Common mistake: build the fix, test, see no change — server is still running old code.

### 8. Trace WebSocket events through 4 stages
When the UI doesn't update: (1) Did backend emit the event? → (2) Did WebSocket forward it? → (3) Did frontend listen for it? → (4) Did component re-render? The bug is always at one stage.

## Understanding Session-Based Apps

These patterns apply to any app where you chat with an AI agent that spawns background sessions.

### Two conversation channels
There's a **main agent** (orchestrator) and **individual sessions** (workers). They have separate inputs. Typing in the wrong one sends your message to the wrong place. The main agent can create sessions, but once a session exists, you interact with it directly through its own input.

### Session lifecycle and status
Sessions go through states: created → running → stopped. They also have a **work status** (in_progress, awaiting_human, agent_complete) and a **mode** (bypass, plan, etc.). These update in real-time via WebSocket. Status displays in multiple UI locations, each updated by different code paths.

### Opening a session inline
When the agent creates a session and shows a link, click it to open a **session panel inline** on the same page. Don't navigate to a separate sessions page. The session panel has its own chat history, input box, and status header — all distinct from the main chat.

## Walnut Home Page Layout (`/`)

```
┌────────┬─────────────────┬─────────────────┬──────────────────┐
│Sidebar │  Main Chat      │  SessionPanel   │  TodoPanel       │
│        │                 │                 │  ┌─────────────┐ │
│ Home   │  Chat history   │  Session header │  │ Task list   │ │
│ Tasks  │  (main agent)   │  (status, mode) │  │ (grouped by │ │
│ Sess.  │                 │                 │  │  cat → proj)│ │
│ Search │                 │  Session chat   │  ├─────────────┤ │
│ Memory │                 │  (You ↔ Claude) │  │ TodoDetail  │ │
│ ...    │                 │                 │  │  Sessions   │ │
│        │ ┌─────────────┐ │                 │  │  Summary    │ │
│        │ │ Chat input  │ │  Session input  │  │  Triage     │ │
│        │ └─────────────┘ │                 │  └─────────────┘ │
│        │  Task context   │                 │  Quick add       │
└────────┴─────────────────┴─────────────────┴──────────────────┘
```

SessionPanel only appears when a session is open. Without it, Main Chat takes more space.

### 1. Main Chat
Where you talk to the **main agent**. It can create tasks, start sessions, query data, run tools. When it starts a session, it responds with a clickable session link:

> ✅ Session started: [Session Title](/sessions?id=xxx)

Input placeholder: `"Type a message... (/ for commands)"` or `"Ask about '<task name>'..."`

### 2. TodoPanel (right side, top)
Task list grouped by Category → Project. Each task row shows phase icon, title, **SessionPill** (e.g., `plan · Awaiting Human / Stopped`), priority, star. Clicking a task opens TodoDetailPanel below.

### 3. TodoDetailPanel (right side, bottom — when task selected)
Shows detail for the selected task:
- **Sessions list**: mode badge (**Plan** or none for bypass), work status, timestamp, clickable `↗`
- **Summary (AI)**: triage-generated summary
- **Triage history**: `View Triage History (N) →`

Clicking a session in this list also opens SessionPanel.

### 4. SessionPanel (middle — when session open)
Session chat with the Claude Code CLI process. Contains:
- **Header**: session title + process status (Running/Stopped) + work status (Awaiting Human, In Progress)
- **Task link**: `📋 Task Name ↗`
- **My Messages**: collapsible list of messages you've sent
- **Chat history**: full conversation with tool calls, thinking blocks, token counts
- **Input**: `"Send a message to this session... (/ for commands)"`

The session input sends messages **directly to the Claude Code CLI process** — not through the main agent.

### How Panels Connect
- Click **task** in TodoPanel → TodoDetailPanel opens, task context set in main chat
- Click **session link** in main chat → SessionPanel opens inline (stays on `/`)
- Click **session** in TodoDetailPanel → SessionPanel opens
- Close SessionPanel (`×`) → returns to layout without it

## Input Boxes

| Input | Placeholder | Purpose |
|---|---|---|
| Main chat | `"Type a message..."` or `"Ask about '...'"` | Talk to main agent |
| Session chat | `"Send a message to this session..."` | Talk directly to Claude Code CLI |
| Task search | `"Search tasks... ⌘K"` | Filter tasks in TodoPanel |
| Quick add | `"Quick add task..."` | Create task directly (no agent) |

## Common Actions

### Create a Task + Session
Talk to the main agent: `"Create task 'My Task' in Projects/Walnut, start a bypass session with prompt 'Just say HI'"`

Session modes: **bypass** (execute immediately), **plan** (investigate → write plan → ExitPlanMode)

### Interact with a Session
1. Find session link in chat or TodoDetailPanel
2. Click it → SessionPanel opens inline
3. Click session input (`"Send a message to this session..."`)
4. Type → Enter
5. Wait → screenshot → snapshot to verify

### Monitor Status Changes
After an action, check **three places**:
- **SessionPanel header**: process + work status
- **TodoPanel SessionPill**: mode prefix (`plan` / `session`) + status
- **TodoDetailPanel sessions list**: mode badge + work status label

## Routes

| Route | What it is |
|---|---|
| `/` | Home — main chat + SessionPanel + TodoPanel (most common) |
| `/tasks` | Full task board |
| `/tasks/:id` | Task detail page (standalone, different from TodoDetailPanel) |
| `/search` | Full-text search |

Most of the time, `/` gives you everything you need.

## Interact Like a Human

**Prefer**:
- `browser_take_screenshot` — see what a real user sees, catch visual bugs
- `browser_snapshot` — accessibility tree with clickable refs
- `browser_click` — click buttons, links, tabs like a user would
- `browser_type` + `browser_press_key` — type into inputs and press Enter

**Use sparingly**:
- `browser_evaluate` / `browser_run_code` — useful for waits, but don't bypass the UI
- Direct DOM manipulation — defeats the purpose of testing

Principle: if a human would click a button, you click that button.

## Debugging Tips

- **`browser_snapshot`** — most useful tool, gives refs for clicking
- **`browser_take_screenshot`** — visual truth when DOM looks fine but something's wrong
- **Refs change** after DOM updates — re-snapshot before interacting
- **`browser_run_code`** — `await page.waitForTimeout(5000)` for delays
- **`browser_network_requests`** — check API calls and WebSocket frames
- **`browser_console_messages`** — check for JS errors
- **Server logs** (`/tmp/walnut/walnut-YYYY-MM-DD.log`) — when UI doesn't update, check if backend sent the event
- **WebSocket events**: `session:status-changed` carries mode/work_status/process_status; `task:updated` carries task data; `session:started`/`session:ended` for lifecycle

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.