AR

Provides architectural oversight for Electrobun projects, detailing the interaction between the trading engine, native webviews, and broker APIs.

Install

mkdir -p .claude/skills/architecture-mohitkoley && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/16576" && unzip -o skill.zip -d .claude/skills/architecture-mohitkoley && rm skill.zip

Installs to .claude/skills/architecture-mohitkoley

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Electrobun uses a multi-process architecture:
45 chars · catalog descriptionno explicit “when” trigger
Intermediate

Key capabilities

  • Define the Electrobun multi-process architecture
  • Describe the Bun Layer responsibilities
  • Describe the Webview Layer responsibilities
  • Define shared types for RPC schema and data models
  • Illustrate multi-window architecture
  • Explain embedded webviews for third-party content

How it works

The skill outlines the multi-process architecture of Electrobun, detailing the roles of the Bun Layer (trading engine) and Webview Layer (display) and their communication mechanisms.

Inputs & outputs

You give it
Request for Electrobun architecture details
You get back
Description of process model, layer responsibilities, and communication

When to use architecture

  • Understanding the multi-process communication model
  • Debugging inter-process RPC issues
  • Extending native UI capabilities

About this skill

Electrobun Algo Trading Architecture

Process Model

Electrobun uses a multi-process architecture:

┌─────────────────────────────────────────────────┐
│                  Launcher (Zig)                  │
│  Tiny binary → spawns Bun → inits native GUI    │
└──────────────────────┬──────────────────────────┘
                       │
┌──────────────────────▼──────────────────────────┐
│              Bun Main Process                    │
│  ┌─────────────┐  ┌──────────────┐             │
│  │ Broker APIs  │  │ SQLite DB    │             │
│  │ WebSockets   │  │ Order Mgmt   │             │
│  │ Risk Engine  │  │ Strategy     │             │
│  └──────┬──────┘  └──────┬───────┘             │
│         │    Encrypted RPC    │                  │
│         │   (AES-256-GCM)    │                  │
│  ┌──────▼────────────────▼───────┐              │
│  │     RPC Transport Layer       │              │
│  │  WebSocket localhost + FFI    │              │
│  └──────────────┬────────────────┘              │
└─────────────────┼───────────────────────────────┘
                  │
┌─────────────────▼───────────────────────────────┐
│           Native Webview (per-window)            │
│  WKWebView (mac) / WebView2 (win) / GTK (linux) │
│  ┌─────────────────────────────────────┐        │
│  │  Electroview + UI (HTML/CSS/TS)     │        │
│  │  Dashboard, Charts, Order Entry     │        │
│  │  NO direct broker/DB access         │        │
│  └─────────────────────────────────────┘        │
└─────────────────────────────────────────────────┘

Layer Responsibilities

Bun Layer (src/bun/) — The Trading Engine

This is where ALL business logic lives:

  • Broker API authentication and session management
  • WebSocket connections to market data feeds
  • Order placement, modification, cancellation
  • Position tracking and P&L calculation
  • Risk management (pre-trade checks, circuit breakers)
  • Strategy execution engine
  • SQLite database operations (trades, logs, config)
  • Encryption and key management
  • Local HTTP/WebSocket server for external tool integration

Webview Layer (src/mainview/) — The Display

Pure presentation:

  • Renders data received via RPC messages
  • Sends user actions (place order, start strategy) via RPC requests
  • Chart rendering, table displays, forms
  • NEVER holds API keys, tokens, or database handles
  • NEVER makes direct HTTP calls to brokers

Shared Types (src/shared/) — The Contract

  • RPC schema type definitions
  • Data model interfaces (Order, Position, OHLC, etc.)
  • Enum definitions (OrderType, OrderStatus, Exchange)

Multi-Window Architecture

Trading apps often need multiple windows:

import { BrowserWindow, BrowserView } from "electrobun/bun";

// Main trading window
const mainWindow = new BrowserWindow({
  title: "Trading Dashboard",
  url: "views://mainview/index.html",
  frame: { x: 0, y: 0, width: 1400, height: 900 },
  rpc: mainRpc,
});

// Separate order book window
const orderbookWindow = new BrowserWindow({
  title: "Order Book",
  url: "views://orderbook/index.html",
  frame: { x: 1400, y: 0, width: 500, height: 900 },
  rpc: orderbookRpc,
});

// Chart window (can load external charting lib in sandboxed webview)
const chartWindow = new BrowserWindow({
  title: "Charts",
  url: "views://charts/index.html",
  frame: { x: 0, y: 900, width: 1900, height: 600 },
  rpc: chartRpc,
});

// Broadcast tick data to all windows
function broadcastTick(data: TickData) {
  mainWindow.webview.rpc?.send.tickUpdate(data);
  orderbookWindow.webview.rpc?.send.tickUpdate(data);
  chartWindow.webview.rpc?.send.tickUpdate(data);
}

Embedded Webviews for Third-Party Content

Use <electrobun-webview> for isolated content like broker login pages:

<!-- In your main HTML -->
<electrobun-webview
  id="broker-login"
  src="https://kite.zerodha.com/connect/login"
  sandbox
  style="width: 100%; height: 500px;">
</electrobun-webview>

The sandbox attribute prevents RPC injection, keeping the broker's login page isolated.

Service Architecture Pattern

// src/bun/services/market-data.ts
export class MarketDataService {
  private ws: WebSocket | null = null;
  private subscriptions = new Map<string, Set<(data: TickData) => void>>();
  private reconnectAttempts = 0;
  private maxReconnectAttempts = 10;
  private reconnectDelay = 1000;

  constructor(private broker: BrokerConnection) {}

  async connect() {
    this.ws = new WebSocket(this.broker.getWebSocketUrl());
    this.ws.onmessage = (event) => this.handleMessage(event);
    this.ws.onclose = () => this.handleDisconnect();
    this.ws.onerror = (err) => this.handleError(err);
    this.reconnectAttempts = 0;
  }

  subscribe(symbol: string, callback: (data: TickData) => void) {
    if (!this.subscriptions.has(symbol)) {
      this.subscriptions.set(symbol, new Set());
      this.ws?.send(JSON.stringify({ action: "subscribe", symbol }));
    }
    this.subscriptions.get(symbol)!.add(callback);
  }

  private handleMessage(event: MessageEvent) {
    const data = this.parseTickData(event.data);
    const callbacks = this.subscriptions.get(data.symbol);
    if (callbacks) {
      for (const cb of callbacks) cb(data);
    }
  }

  private async handleDisconnect() {
    if (this.reconnectAttempts >= this.maxReconnectAttempts) {
      console.error("Max reconnection attempts reached");
      return;
    }
    const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts);
    this.reconnectAttempts++;
    await Bun.sleep(delay);
    await this.connect();
    // Re-subscribe to all symbols after reconnect
    for (const symbol of this.subscriptions.keys()) {
      this.ws?.send(JSON.stringify({ action: "subscribe", symbol }));
    }
  }
}

Application Menu for Trading

ApplicationMenu.setApplicationMenu([
  {
    label: "Trading App",
    submenu: [
      { role: "about" },
      { type: "separator" },
      { label: "Preferences", action: "preferences", accelerator: "," },
      { type: "separator" },
      { role: "hide" },
      { role: "hideOthers" },
      { role: "quit" },
    ],
  },
  {
    label: "Trading",
    submenu: [
      { label: "New Order", action: "new-order", accelerator: "n" },
      { label: "Cancel All Orders", action: "cancel-all", accelerator: "Shift+x" },
      { type: "separator" },
      { label: "Start Strategy", action: "start-strategy" },
      { label: "Stop All Strategies", action: "stop-all-strategies" },
      { type: "separator" },
      { label: "Square Off All", action: "square-off-all", accelerator: "Shift+q" },
    ],
  },
  {
    label: "View",
    submenu: [
      { label: "Dashboard", action: "view-dashboard", accelerator: "1" },
      { label: "Order Book", action: "view-orderbook", accelerator: "2" },
      { label: "Positions", action: "view-positions", accelerator: "3" },
      { label: "Charts", action: "view-charts", accelerator: "4" },
      { type: "separator" },
      { role: "toggleFullScreen" },
    ],
  },
  {
    label: "Edit",
    submenu: [
      { role: "undo" }, { role: "redo" },
      { type: "separator" },
      { role: "cut" }, { role: "copy" }, { role: "paste" }, { role: "selectAll" },
    ],
  },
]);

Tray for Background Trading

const tray = new Tray({
  title: "Trading",
  template: true, // Adapts to macOS light/dark mode
});

function updateTrayMenu(state: AppState) {
  tray.setMenu([
    { label: `P&L: ${state.totalPnL >= 0 ? "+" : ""}${state.totalPnL.toFixed(2)}`, enabled: false },
    { label: `Open Positions: ${state.openPositions}`, enabled: false },
    { label: `Pending Orders: ${state.pendingOrders}`, enabled: false },
    { type: "separator" },
    { label: "Show Dashboard", action: "show-dashboard" },
    { label: "Quick Order", action: "quick-order" },
    { type: "separator" },
    {
      label: "Emergency",
      submenu: [
        { label: "Cancel All Orders", action: "cancel-all" },
        { label: "Square Off All", action: "square-off" },
      ],
    },
    { type: "separator" },
    { label: "Quit", action: "quit" },
  ]);
}

Error Handling Strategy

// Wrap all RPC handlers with consistent error handling
function wrapHandler<P, R>(
  name: string,
  handler: (params: P) => Promise<R>
): (params: P) => Promise<R> {
  return async (params: P) => {
    try {
      return await handler(params);
    } catch (error) {
      const message = error instanceof Error ? error.message : String(error);
      console.error(`[RPC:${name}] Error:`, message);
      // Log to DB for audit
      db.run(
        "INSERT INTO error_log (handler, message, params, timestamp) VALUES (?, ?, ?, ?)",
        name, message, JSON.stringify(params), Date.now()
      );
      throw error; // Re-throw so webview gets the error
    }
  };
}

Updater Integration

// Check for updates on startup (non-blocking)
async function checkUpdates() {
  try {
    const info = await Updater.checkForUpdate();
    if (info.updateAvailable) {
      mainWindow.webview.rpc?.send.connectionStatus({
        broker: "app",
        status: "update-available",
      });
      // Download in background
      await Updater.downloadUpdate();
      // Notify user, don't force-apply during trading hours
      Utils.showNotification({
        title: "Update Available",
        body: `Version ${info.version} is ready to install.`,
      });
    }
  } catch (e) {
    console.error("Update check failed:", e);
  }
}

// Only apply updates when user explicitly requests (not during trading)
async function applyUpdate() {
  const positions = await broker.getPositions();
  const openPositions = positions.filter(p => p.quantity !== 0);
  if (openPositions.length > 0) {
    Utils.showNotification({
      title: "Cannot Update",
      body: "Close all positions before updating.",
    });
    return;
  }
  await Updater.applyUpdate();
}

When not to use it

  • When not working with the Electrobun trading application
  • When not needing to understand inter-process communication
  • When not debugging RPC issues

Limitations

  • Specific to Electrobun Algo Trading Architecture

How it compares

This skill provides a specific architectural blueprint for the Electrobun application, offering a clear understanding of its components and interactions unlike a generic system design overview.

Compared to similar skills

architecture side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
architecture (this skill)04moNo flagsIntermediate
mcp-builder1364moReviewAdvanced
architecture-patterns552moNo flagsAdvanced
nodejs-best-practices286moNo flagsAdvanced

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

mcp-builder

anthropics

Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).

136215

architecture-patterns

wshobson

Implement proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design. Use when architecting complex backend systems or refactoring existing applications for better maintainability.

55214

nodejs-best-practices

davila7

Node.js development principles and decision-making. Framework selection, async patterns, security, and architecture. Teaches thinking, not copying.

28120

senior-fullstack

davila7

Comprehensive fullstack development skill for building complete web applications with React, Next.js, Node.js, GraphQL, and PostgreSQL. Includes project scaffolding, code quality analysis, architecture patterns, and complete tech stack guidance. Use when building new projects, analyzing code quality, implementing design patterns, or setting up development workflows.

35110

workflow-orchestration-patterns

wshobson

Design durable workflows with Temporal for distributed systems. Covers workflow vs activity separation, saga patterns, state management, and determinism constraints. Use when building long-running processes, distributed transactions, or microservice orchestration.

10117

langchain-architecture

wshobson

Design LLM applications using the LangChain framework with agents, memory, and tool integration patterns. Use when building LangChain applications, implementing AI agents, or creating complex LLM workflows.

899

Search skills

Search the agent skills registry