How the Brainstorming Skill Integrates with External Visual Companion Servers in OpenAI Plugins

The brainstorming skill hands off visual rendering tasks to a lightweight Node.js companion server by executing shell scripts that manage the server's lifecycle, with connection details exchanged via a JSON state file in the project's .superpowers/brainstorm/ directory.

The brainstorming skill in the openai/plugins repository supports two distinct modes of operation: pure-text brainstorming within the LLM chat interface, and visual-companion mode that leverages external scripts to generate mock-ups and diagrams. This article examines how the skill orchestrates seamless integration with external processes without requiring manual code changes, using specification files and shell scripts to manage a temporary Node.js server.

Understanding the Brainstorming Skill Architecture

Located under plugins/superpowers/skills/brainstorming, the skill is designed to run in two distinct modes. In pure-text brainstorming, all interaction stays inside the LLM chat. In visual-companion mode, the skill hands off the session to a lightweight companion server that renders mock-ups, diagrams, and other visual assets. The hand-off is orchestrated entirely by the skill's specification files found in SKILL.md and visual-companion.md, requiring no manual code modifications to enable external script integration.

Step-by-Step Integration Flow

The integration follows a strict lifecycle managed through shell scripts and state files. Each step is governed by specific source files in the repository.

Step 1: User Accepts Visual Help

The skill initiates visual mode by sending a single-message offer containing the visual-companion invitation, as defined in plugins/superpowers/skills/brainstorming/SKILL.md. The user must explicitly reply "yes" to trigger the external server launch. This explicit opt-in ensures that external script execution only occurs with user consent.

Step 2: Companion Server Startup

Upon user agreement, the skill executes plugins/superpowers/skills/brainstorming/scripts/start-server.sh. This bash wrapper spawns a Node.js server (scripts/server.cjs) in the background. The script receives --project-dir (the root of the current LLM project) as a parameter, establishing the working context for the session.

Step 3: State Directory Preparation

The startup script prepares a dedicated state directory under .superpowers/brainstorm/<session-id>/ within the project root. All generated files are stored here, ensuring they survive restarts and remain scoped to the specific brainstorming session. According to plugins/superpowers/skills/brainstorming/visual-companion.md, this directory structure allows the server to maintain persistence without interfering with the host project's version control.

Step 4: Server Publishes Connection Info

On startup, the server writes a JSON blob to $STATE_DIR/server-info containing the host, port, and optional secret token. This file serves as the single source of truth for the LLM to determine how to reach the companion. The server dynamically selects an available port at runtime rather than using hard-coded values, preventing conflicts with other services.

Step 5: LLM-to-Server Communication

Subsequent brainstorming turns include HTTP GET and POST requests to the URL read from server-info. The server returns HTML frames based on plugins/superpowers/skills/brainstorming/scripts/frame-template.html, embedding mock-ups, SVG diagrams, or static images generated by downstream skills. Each request contains sufficient context (session ID, token) to enable stateless communication.

Step 6: Session Cleanup

When the user signals the end of brainstorming or the LLM transitions to the writing-plans skill, the skill executes plugins/superpowers/skills/brainstorming/scripts/stop-server.sh. This script terminates the background Node process and removes the temporary state directory, unless a persistent --project-dir was specified to retain visual assets.

Key Integration Mechanisms

The integration relies on four architectural principles that ensure reliable operation:

  • Dynamic Port Allocation: The server selects an available port at runtime and publishes it via server-info, eliminating port conflicts and manual configuration.
  • Project-Scoped Persistence: By passing --project-dir, visual assets are stored in the project's .superpowers/brainstorm/ folder, which should be added to .gitignore to prevent accidental commits of generated files.
  • Stateless Communication: Each HTTP call contains enough context (session ID, token) for the server to serve correct assets without maintaining long-lived in-process state.
  • Skill Isolation: After brainstorming, the only permitted next skill is writing-plans; the visual companion cannot be invoked again unless a new brainstorming round starts.

Practical Implementation Examples

The following examples demonstrate how to interact with the visual companion server manually, though the skill handles these operations automatically.

Start the visual companion from the skill runner:

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

Read the server connection details (LLM-side implementation pattern):

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']}"

Request a visual asset rendering via the server's REST API:

curl -X POST "$BASE_URL/render" \
     -H "Content-Type: application/json" \
     -d '{"type":"mockup","data":{...}}'

Terminate the server and clean up resources:

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

Summary

  • The brainstorming skill in openai/plugins supports visual-companion mode through automated shell script execution.
  • scripts/start-server.sh launches a Node.js server (scripts/server.cjs) that publishes connection details to .superpowers/brainstorm/<session-id>/server-info.
  • Communication occurs via stateless HTTP requests to dynamically assigned ports, with HTML frames rendered using scripts/frame-template.html.
  • scripts/stop-server.sh handles graceful shutdown and cleanup, while agents/openai.yaml configures the LLM's decision-making during the brainstorming session.
  • Visual assets persist in project-scoped directories when --project-dir is specified, enabling seamless integration with external diagram and mock-up generation tools.

Frequently Asked Questions

What happens if the visual companion server crashes during a session?

If the Node.js process terminates unexpectedly, the server-info file remains in the state directory, but subsequent HTTP requests from the LLM will fail. The skill specification in SKILL.md does not currently define automatic restart behavior; the user must manually restart the session or the skill runner must re-execute scripts/start-server.sh to recreate the server process and regenerate the connection file.

Can I configure a fixed port for the visual companion server?

No, the implementation in scripts/server.cjs intentionally avoids hard-coded ports. The server binds to an available ephemeral port at runtime and publishes this information to $STATE_DIR/server-info. This design prevents port conflicts when multiple brainstorming sessions run concurrently or when other services occupy standard ports.

How do I persist visual assets between brainstorming sessions?

Pass the --project-dir argument when running scripts/start-server.sh, pointing to your project's root directory. Generated files are stored under .superpowers/brainstorm/<session-id>/ within that directory. To retain assets indefinitely, avoid running scripts/stop-server.sh with cleanup flags, or copy files from the state directory before initiating the stop script. Remember to add .superpowers/ to your .gitignore file.

Is the communication between the LLM and the visual companion server secure?

The server writes an optional secret token to the server-info JSON file alongside the host and port. Subsequent HTTP requests from the LLM should include this token in headers for authentication. However, as implemented in plugins/superpowers/skills/brainstorming, the server runs on localhost by default, minimizing exposure to external networks. For production deployments, additional reverse proxy configuration or TLS termination would be required beyond the basic start-server.sh implementation.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →