# How the Brainstorming Skill Utilizes Visual Companions and Server Scripts in OpenAI Plugins

> Discover how the brainstorming skill in OpenAI plugins uses Node.js server scripts and visual companions to automate diagram and mock-up generation within HTML frames.

- Repository: [OpenAI/plugins](https://github.com/openai/plugins)
- Tags: how-to-guide
- Published: 2026-06-30

---

**The brainstorming skill automates visual brainstorming by spawning a Node.js companion server via shell scripts, publishing connection metadata to a state directory, and communicating over HTTP to render diagrams and mock-ups inside HTML frames.**

The **brainstorming skill** found in `plugins/superpowers/skills/brainstorming` within the openai/plugins repository operates in two distinct modes: pure-text dialogue inside the LLM chat, and **visual-companion mode** that externalizes asset generation to a lightweight server. When users explicitly accept visual assistance, the skill manages the entire server lifecycle—startup, connection hand-off, and termination—through specification-driven scripts that require no manual code changes.

## Activating Visual Companion Mode

The transition from text-only to visual brainstorming follows a strict handshake defined in [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md).

**User Acceptance Protocol**
Before launching any external processes, the skill sends a single-message offer containing only the visual-companion invitation. The user must explicitly reply "yes" to trigger the server initialization. This guard ensures that background processes only spawn when explicitly requested, preventing unnecessary resource consumption.

**Server Initialization via Shell Scripts**
Once accepted, the skill executes [`scripts/start-server.sh`](https://github.com/openai/plugins/blob/main/scripts/start-server.sh), a Bash wrapper that launches the Node.js server defined in `scripts/server.cjs`. The script accepts a `--project-dir` argument pointing to the root of the current LLM project, ensuring all generated assets are scoped to that workspace.

```bash

# Example invocation as performed by the skill

PROJECT_ROOT="/path/to/your/project"
scripts/start-server.sh --project-dir "$PROJECT_ROOT"

```

The server startup is asynchronous; the script returns immediately after spawning the background Node process, allowing the LLM to continue the conversation while the companion initializes.

## State Management and Connection Discovery

The visual companion uses a file-based discovery mechanism to communicate its network location without hard-coded ports.

**State Directory Preparation**
As documented in [`visual-companion.md`](https://github.com/openai/plugins/blob/main/visual-companion.md), the server prepares a state directory under `.superpowers/brainstorm/<session-id>/` within the project root. This directory persists across restarts when `--project-dir` is provided, ensuring visual assets survive LLM session interruptions.

**Publishing Connection Metadata**
On startup, the server writes a JSON blob to `$STATE_DIR/server-info` containing the dynamic host, port, and optional authentication token. This file serves as the single source of truth for the LLM to locate the companion.

```python

# LLM-side pseudocode for reading server connection details

import json
import pathlib

state_dir = pathlib.Path(".superpowers/brainstorm") / "<session-id>"
info_path = state_dir / "server-info"

with open(info_path) as f:
    info = json.load(f)
    
base_url = f"http://{info['host']}:{info['port']}"

```

## HTTP Communication Protocol

Once the `server-info` file is available, the LLM communicates with the companion via RESTful HTTP requests, maintaining stateless interactions where each request contains sufficient context for the server to identify the correct session.

**Rendering Visual Assets**
The LLM sends POST requests to endpoints like `/render` with JSON payloads specifying asset types (mock-ups, SVG diagrams, or static images). The server responds with HTML frames based on [`scripts/frame-template.html`](https://github.com/openai/plugins/blob/main/scripts/frame-template.html), which embed the generated visual content.

```bash

# Example request to generate a mock-up

curl -X POST "$BASE_URL/render" \
     -H "Content-Type: application/json" \
     -d '{"type":"mockup","data":{"title":"Dashboard","components":["chart","table"]}}'

```

**Frame Rendering**
The [`frame-template.html`](https://github.com/openai/plugins/blob/main/frame-template.html) file provides the HTML scaffold that wraps raw asset output, ensuring consistent styling and responsive layout for diagrams generated by downstream skills.

## Server Termination and Cleanup

The skill maintains strict resource hygiene by automatically terminating the companion when brainstorming concludes.

**Lifecycle Boundaries**
When the user signals completion or the LLM transitions to the `writing-plans` skill (the only permitted successor to brainstorming), the skill invokes [`scripts/stop-server.sh`](https://github.com/openai/plugins/blob/main/scripts/stop-server.sh).

```bash

# Cleanup invocation

scripts/stop-server.sh --project-dir "$PROJECT_ROOT"

```

This script terminates the background Node process and removes the temporary state directory. If `--project-dir` was specified, the visual assets in `.superpowers/brainstorm/` remain available for future reference, though the server process itself is destroyed.

## Key Integration Characteristics

**Dynamic Port Allocation**
The server selects an available port at runtime rather than using hard-coded values, preventing conflicts with other development services. This dynamic allocation is communicated exclusively through the `server-info` file.

**Project-Scoped Persistence**
By requiring `--project-dir`, the skill ensures that generated visual assets are stored within the project's `.superpowers/brainstorm/` folder. Developers should add this directory to `.gitignore` to avoid committing temporary render files.

**Stateless Architecture**
Each HTTP call includes session identifiers and tokens, allowing the server to serve correct assets without maintaining long-lived in-memory state. This design supports horizontal scaling and crash recovery.

**Skill Isolation**
The visual companion is strictly bounded to the brainstorming session. After completion, the workflow transitions exclusively to `writing-plans`, preventing accidental companion reuse in incompatible contexts.

## Summary

- The **brainstorming skill** operates in pure-text or visual-companion mode, switching based on explicit user acceptance.
- **Server lifecycle** is managed by [`scripts/start-server.sh`](https://github.com/openai/plugins/blob/main/scripts/start-server.sh) and [`scripts/stop-server.sh`](https://github.com/openai/plugins/blob/main/scripts/stop-server.sh), which spawn and terminate a Node.js server (`scripts/server.cjs`).
- **Connection discovery** occurs via JSON metadata written to `.superpowers/brainstorm/<session-id>/server-info`, eliminating hard-coded network configuration.
- **Visual rendering** happens through HTTP POST requests to the companion server, which returns HTML frames using [`scripts/frame-template.html`](https://github.com/openai/plugins/blob/main/scripts/frame-template.html).
- **State persistence** is scoped to the project directory via `--project-dir`, ensuring assets survive restarts while server processes are properly cleaned up.

## Frequently Asked Questions

### How does the brainstorming skill decide when to start the visual companion server?

The skill sends a single-message offer defined in [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md) that explicitly asks the user if they want visual assistance. Only upon receiving an affirmative "yes" response does the skill execute [`scripts/start-server.sh`](https://github.com/openai/plugins/blob/main/scripts/start-server.sh). This user-gated approach prevents unnecessary resource consumption and ensures the server only runs when explicitly requested.

### Where does the visual companion store generated files and connection information?

The server stores all data under `.superpowers/brainstorm/<session-id>/` within the project root specified by `--project-dir`. This directory contains the `server-info` JSON file with connection details, rendered assets, and session state. When a persistent project directory is provided, these files survive LLM restarts; otherwise, [`scripts/stop-server.sh`](https://github.com/openai/plugins/blob/main/scripts/stop-server.sh) removes them during cleanup.

### Why does the server use a file-based discovery mechanism instead of environment variables?

The `server-info` JSON file approach allows for **dynamic port allocation** without requiring the LLM to parse shell output or environment variables. The Node.js server selects an available port at runtime, writes the host and port to `$STATE_DIR/server-info`, and the LLM reads this file to construct the base URL. This eliminates port conflicts and simplifies process management across different operating systems.

### What prevents the visual companion from interfering with other skills?

The brainstorming skill enforces strict workflow boundaries. According to the skill specification, the only permitted next skill after brainstorming is `writing-plans`. The companion server is explicitly terminated by [`scripts/stop-server.sh`](https://github.com/openai/plugins/blob/main/scripts/stop-server.sh) before this transition occurs, ensuring visual rendering processes never leak into unrelated skill contexts.