> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bepurple.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Run scripts

> Saved shell command per repo that p0 spawns in a PTY when you press Play in the run sidebar.

export const Mock = props => {
  const {kind, ...rest} = props;
  const iconBase = {
    xmlns: "http://www.w3.org/2000/svg",
    viewBox: "0 0 24 24",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: "2",
    strokeLinecap: "round",
    strokeLinejoin: "round",
    width: "14",
    height: "14",
    "aria-hidden": "true"
  };
  const renderShapes = shapes => shapes.map((shape, idx) => {
    if (shape.tag === "circle") return <circle key={idx} {...shape.attrs} />;
    if (shape.tag === "rect") return <rect key={idx} {...shape.attrs} />;
    if (shape.tag === "line") return <line key={idx} {...shape.attrs} />;
    if (shape.tag === "polyline") return <polyline key={idx} {...shape.attrs} />;
    if (shape.tag === "polygon") return <polygon key={idx} {...shape.attrs} />;
    return <path key={idx} {...shape.attrs} />;
  });
  if (kind === "appShell") {
    const {sidebar, children} = rest;
    return <div className="p0-app-shell" role="img" aria-label="p0 application window mock">
        <div className="p0-app-shell__titlebar" aria-hidden="true">
          <span className="p0-app-shell__dot p0-app-shell__dot--close" />
          <span className="p0-app-shell__dot p0-app-shell__dot--minimize" />
          <span className="p0-app-shell__dot p0-app-shell__dot--maximize" />
        </div>
        <div className="p0-app-shell__body">
          {sidebar ? <aside className="p0-app-shell__sidebar">{sidebar}</aside> : null}
          <main className="p0-app-shell__main">{children}</main>
        </div>
      </div>;
  }
  if (kind === "sidebar") {
    const {sessions = [], repos = []} = rest;
    return <div className="p0-sidebar" role="navigation" aria-label="p0 sidebar mock">
        <section className="p0-sidebar__section">
          <header className="p0-sidebar__section-header">
            <span className="p0-sidebar__section-title">Sessions</span>
            <button type="button" className="p0-sidebar__section-action" aria-label="New session" tabIndex={-1}>
              <svg {...iconBase}>
                <path d="M5 12h14" />
                <path d="M12 5v14" />
              </svg>
            </button>
          </header>
          <ul className="p0-sidebar__list">
            {sessions.map(s => <li key={s.id} className={s.active ? "p0-sidebar__item p0-sidebar__item--active" : "p0-sidebar__item"}>
                <svg {...iconBase} className="p0-sidebar__item-icon">
                  <path d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z" />
                </svg>
                <span className="p0-sidebar__item-label">{s.title}</span>
              </li>)}
          </ul>
        </section>

        <section className="p0-sidebar__section">
          <header className="p0-sidebar__section-header">
            <span className="p0-sidebar__section-title">Repositories</span>
          </header>
          <ul className="p0-sidebar__list">
            {repos.map(r => <li key={r.name} className="p0-sidebar__item">
                <svg {...iconBase} className="p0-sidebar__item-icon">
                  <path d="M18 19a5 5 0 0 1-5-5v8" />
                  <path d="M9 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v5" />
                  <circle cx="13" cy="12" r="2" />
                  <circle cx="20" cy="19" r="2" />
                </svg>
                <span className="p0-sidebar__item-label">{r.name}</span>
              </li>)}
          </ul>
        </section>
      </div>;
  }
  if (kind === "chatInput") {
    const {placeholder = "Message p0…", slashOpen = false} = rest;
    const SLASH_PREVIEW = [{
      command: "/plan",
      description: "Switch to Plan mode"
    }, {
      command: "/build-from-spec",
      description: "End-to-end spec → PR pipeline"
    }, {
      command: "/refine",
      description: "Iterate on a built feature"
    }];
    const ciIconBase = {
      ...iconBase,
      width: "16",
      height: "16"
    };
    const slashIconBase = {
      ...ciIconBase,
      width: "12",
      height: "12"
    };
    return <div className="p0-chat-input-wrapper">
        {slashOpen ? <div className="p0-chat-input__dropdown-slot">
            <div className="p0-slash-dropdown" role="listbox" aria-label="Slash command suggestions">
              <div className="p0-slash-dropdown__header">
                <svg {...slashIconBase}>
                  <path d="M22 2 2 22" />
                </svg>
                <span>Commands matching /</span>
              </div>
              <ul className="p0-slash-dropdown__list">
                {SLASH_PREVIEW.map((c, i) => <li key={c.command} className={i === 0 ? "p0-slash-dropdown__item p0-slash-dropdown__item--active" : "p0-slash-dropdown__item"} role="option" aria-selected={i === 0}>
                    <code className="p0-slash-dropdown__command">{c.command}</code>
                    <span className="p0-slash-dropdown__description">{c.description}</span>
                  </li>)}
              </ul>
            </div>
          </div> : null}
        <div className="p0-chat-input" role="group" aria-label="p0 chat input mock">
          <button type="button" className="p0-chat-input__icon-btn" aria-label="Attach file" tabIndex={-1}>
            <svg {...ciIconBase}>
              <path d="m16 6-8.414 8.586a2 2 0 0 0 2.829 2.829l8.414-8.586a4 4 0 1 0-5.657-5.657l-8.379 8.551a6 6 0 1 0 8.485 8.485l8.379-8.551" />
            </svg>
          </button>
          <span className="p0-chat-input__field" aria-hidden="true">
            {placeholder}
          </span>
          <button type="button" className="p0-chat-input__send" aria-label="Send message" tabIndex={-1}>
            <svg {...ciIconBase}>
              <path d="m5 12 7-7 7 7" />
              <path d="M12 19V5" />
            </svg>
          </button>
        </div>
      </div>;
  }
  if (kind === "slashDropdown") {
    const {query = "/"} = rest;
    const SLASH_COMMANDS = [{
      command: "/agent",
      description: "Switch to Agent mode (applies changes directly)"
    }, {
      command: "/clear",
      description: "Start a new conversation (creates new sub-chat)"
    }, {
      command: "/compact",
      description: "Compact conversation context to reduce token usage"
    }, {
      command: "/config",
      description: "View and modify configuration settings"
    }, {
      command: "/cost",
      description: "Show token usage and cost for the session"
    }, {
      command: "/doctor",
      description: "Check the health of your p0 installation"
    }, {
      command: "/help",
      description: "Show available commands and help"
    }, {
      command: "/mcp",
      description: "View and manage MCP server connections"
    }, {
      command: "/memory",
      description: "View and edit CLAUDE.md memory files"
    }, {
      command: "/model",
      description: "Switch AI model"
    }, {
      command: "/permissions",
      description: "View and manage tool permissions"
    }, {
      command: "/plan",
      description: "Switch to Plan mode (creates plan before making changes)"
    }, {
      command: "/pr-comments",
      description: "Ask the agent to generate PR review comments"
    }, {
      command: "/release-notes",
      description: "Ask the agent to generate release notes"
    }, {
      command: "/review",
      description: "Ask the agent to review your code"
    }, {
      command: "/security-review",
      description: "Ask the agent to perform a security audit"
    }, {
      command: "/skills",
      description: "Manage your skills"
    }, {
      command: "/status",
      description: "Show current session status and context"
    }, {
      command: "/build-from-spec",
      description: "Run the end-to-end spec → build → QA pipeline"
    }, {
      command: "/create-standards",
      description: "Generate engineering standards for your workspace"
    }, {
      command: "/refine",
      description: "Make incremental changes to a recently built feature"
    }, {
      command: "/import-spec",
      description: "Import a product spec and ask clarifying questions"
    }];
    const sdIconBase = {
      ...iconBase,
      width: "12",
      height: "12"
    };
    const needle = (query || "/").toLowerCase();
    const matches = SLASH_COMMANDS.filter(c => c.command.toLowerCase().startsWith(needle));
    return <div className="p0-slash-dropdown" role="listbox" aria-label="Slash command suggestions">
        <div className="p0-slash-dropdown__header">
          <svg {...sdIconBase}>
            <path d="M22 2 2 22" />
          </svg>
          <span>Commands matching {query}</span>
        </div>
        {matches.length === 0 ? <div className="p0-slash-dropdown__empty">No commands match.</div> : <ul className="p0-slash-dropdown__list">
            {matches.map((c, i) => <li key={c.command} className={i === 0 ? "p0-slash-dropdown__item p0-slash-dropdown__item--active" : "p0-slash-dropdown__item"} role="option" aria-selected={i === 0}>
                <code className="p0-slash-dropdown__command">{c.command}</code>
                <span className="p0-slash-dropdown__description">{c.description}</span>
              </li>)}
          </ul>}
      </div>;
  }
  if (kind === "ticketTree") {
    const {phases = []} = rest;
    const STATUS_META = {
      todo: {
        label: "Todo",
        modifier: "todo",
        shapes: [{
          tag: "circle",
          attrs: {
            cx: "12",
            cy: "12",
            r: "10"
          }
        }]
      },
      in_progress: {
        label: "In progress",
        modifier: "in-progress",
        shapes: [{
          tag: "path",
          attrs: {
            d: "M21 12a9 9 0 1 1-6.219-8.56"
          }
        }]
      },
      completed: {
        label: "Completed",
        modifier: "completed",
        shapes: [{
          tag: "circle",
          attrs: {
            cx: "12",
            cy: "12",
            r: "10"
          }
        }, {
          tag: "path",
          attrs: {
            d: "m9 12 2 2 4-4"
          }
        }]
      },
      failed: {
        label: "Failed",
        modifier: "failed",
        shapes: [{
          tag: "circle",
          attrs: {
            cx: "12",
            cy: "12",
            r: "10"
          }
        }, {
          tag: "path",
          attrs: {
            d: "m15 9-6 6"
          }
        }, {
          tag: "path",
          attrs: {
            d: "m9 9 6 6"
          }
        }]
      }
    };
    return <div className="p0-ticket-tree" role="tree" aria-label="Build progress">
        <ul className="p0-ticket-tree__phases">
          {phases.map(phase => <li key={phase.name} className="p0-ticket-tree__phase">
              <div className="p0-ticket-tree__phase-name">{phase.name}</div>
              <ul className="p0-ticket-tree__tickets">
                {phase.tickets.map(ticket => {
      const meta = STATUS_META[ticket.status] ?? STATUS_META.todo;
      return <li key={ticket.id} className="p0-ticket-tree__ticket" data-status={ticket.status}>
                      <span className={`p0-ticket-tree__dot p0-ticket-tree__dot--${meta.modifier}`} role="img" aria-label={meta.label}>
                        <svg {...iconBase} aria-hidden="true">
                          {renderShapes(meta.shapes)}
                        </svg>
                      </span>
                      <code className="p0-ticket-tree__ticket-id">{ticket.id}</code>
                      <span className="p0-ticket-tree__ticket-name">{ticket.name}</span>
                    </li>;
    })}
              </ul>
            </li>)}
        </ul>
      </div>;
  }
  if (kind === "diffView") {
    const {mode = "unified", file, before = "", after = ""} = rest;
    const computeUnifiedLines = (b, a) => {
      const beforeLines = b.split("\n");
      const afterLines = a.split("\n");
      const lines = [];
      const max = Math.max(beforeLines.length, afterLines.length);
      for (let i = 0; i < max; i++) {
        const bl = beforeLines[i];
        const al = afterLines[i];
        if (bl === al) {
          if (bl !== undefined) lines.push({
            kind: "context",
            text: bl
          });
        } else {
          if (bl !== undefined) lines.push({
            kind: "remove",
            text: bl
          });
          if (al !== undefined) lines.push({
            kind: "add",
            text: al
          });
        }
      }
      return lines;
    };
    const PREFIX = {
      add: "+",
      remove: "-",
      context: " "
    };
    const MODIFIER = {
      add: "add",
      remove: "remove",
      context: "context"
    };
    const computeSplitRows = (b, a) => {
      const beforeLines = b.split("\n");
      const afterLines = a.split("\n");
      const max = Math.max(beforeLines.length, afterLines.length);
      const rows = [];
      for (let i = 0; i < max; i++) {
        const bl = beforeLines[i];
        const al = afterLines[i];
        const sameRow = bl === al;
        rows.push({
          before: bl === undefined ? {
            kind: "empty",
            text: ""
          } : sameRow ? {
            kind: "context",
            text: bl
          } : {
            kind: "remove",
            text: bl
          },
          after: al === undefined ? {
            kind: "empty",
            text: ""
          } : sameRow ? {
            kind: "context",
            text: al
          } : {
            kind: "add",
            text: al
          }
        });
      }
      return rows;
    };
    const unifiedLines = mode === "unified" ? computeUnifiedLines(before, after) : [];
    const splitRows = mode === "split" ? computeSplitRows(before, after) : [];
    return <div className={`p0-diff-view p0-diff-view--${mode}`} role="figure" aria-label={`Diff for ${file}`}>
        <div className="p0-diff-view__header">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" width="14" height="14" aria-hidden="true">
            <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
            <path d="M14 2v4a2 2 0 0 0 2 2h4" />
            <path d="M9 10h6" />
            <path d="M12 13v-6" />
            <path d="M9 17h6" />
          </svg>
          <code className="p0-diff-view__file">{file}</code>
        </div>

        {mode === "split" ? <div className="p0-diff-view__body p0-diff-view__body--split">
            <div className="p0-diff-view__column" aria-label="Before">
              {splitRows.map((row, i) => row.before.kind === "empty" ? <div key={`b-${i}`} className="p0-diff-view__line p0-diff-view__line--empty" aria-hidden="true">
                    <span className="p0-diff-view__text">{" "}</span>
                  </div> : <div key={`b-${i}`} className={`p0-diff-view__line p0-diff-view__line--${MODIFIER[row.before.kind]}`} data-kind={row.before.kind}>
                    <span className="p0-diff-view__prefix" aria-hidden="true">
                      {PREFIX[row.before.kind]}
                    </span>
                    <span className="p0-diff-view__text">{row.before.text || " "}</span>
                  </div>)}
            </div>
            <div className="p0-diff-view__column" aria-label="After">
              {splitRows.map((row, i) => row.after.kind === "empty" ? <div key={`a-${i}`} className="p0-diff-view__line p0-diff-view__line--empty" aria-hidden="true">
                    <span className="p0-diff-view__text">{" "}</span>
                  </div> : <div key={`a-${i}`} className={`p0-diff-view__line p0-diff-view__line--${MODIFIER[row.after.kind]}`} data-kind={row.after.kind}>
                    <span className="p0-diff-view__prefix" aria-hidden="true">
                      {PREFIX[row.after.kind]}
                    </span>
                    <span className="p0-diff-view__text">{row.after.text || " "}</span>
                  </div>)}
            </div>
          </div> : <div className="p0-diff-view__body">
            {unifiedLines.map((line, i) => <div key={i} className={`p0-diff-view__line p0-diff-view__line--${MODIFIER[line.kind]}`} data-kind={line.kind}>
                <span className="p0-diff-view__prefix" aria-hidden="true">
                  {PREFIX[line.kind]}
                </span>
                <span className="p0-diff-view__text">{line.text || " "}</span>
              </div>)}
          </div>}
      </div>;
  }
  if (kind === "terminalPane") {
    const {prompt = "$", command, output} = rest;
    return <div className="p0-terminal-pane" role="figure" aria-label="Terminal output">
        <div className="p0-terminal-pane__chrome" aria-hidden="true">
          <span className="p0-terminal-pane__dot p0-terminal-pane__dot--red" />
          <span className="p0-terminal-pane__dot p0-terminal-pane__dot--yellow" />
          <span className="p0-terminal-pane__dot p0-terminal-pane__dot--green" />
          <span className="p0-terminal-pane__title">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" width="12" height="12" aria-hidden="true">
              <path d="m7 11 2-2-2-2" />
              <path d="M11 13h4" />
              <rect width="18" height="18" x="3" y="3" rx="2" ry="2" />
            </svg>
            {" "}terminal
          </span>
        </div>
        <pre className="p0-terminal-pane__body">
          <code>
            <span className="p0-terminal-pane__line">
              <span className="p0-terminal-pane__prompt">{prompt}</span>
              <span className="p0-terminal-pane__command">{command}</span>
            </span>
            {output ? <span className="p0-terminal-pane__output">{"\n" + output}</span> : null}
          </code>
        </pre>
      </div>;
  }
  if (kind === "devToolsPanel") {
    const {defaultTab = "terminal", terminal, changes, run} = rest;
    const SECTIONS = [{
      id: "terminal",
      label: "Terminal",
      shapes: [{
        tag: "path",
        attrs: {
          d: "m7 11 2-2-2-2"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M11 13h4"
        }
      }, {
        tag: "rect",
        attrs: {
          width: "18",
          height: "18",
          x: "3",
          y: "3",
          rx: "2",
          ry: "2"
        }
      }]
    }, {
      id: "changes",
      label: "Changes",
      shapes: [{
        tag: "path",
        attrs: {
          d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M14 2v4a2 2 0 0 0 2 2h4"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M9 10h6"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M12 13v-6"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M9 17h6"
        }
      }]
    }, {
      id: "run",
      label: "Run",
      shapes: [{
        tag: "polygon",
        attrs: {
          points: "6 3 20 12 6 21 6 3"
        }
      }]
    }];
    const panes = {
      terminal,
      changes,
      run
    };
    return <div className="p0-devtools-panel" role="region" aria-label="DevTools panel">
        {SECTIONS.map(section => {
      const isEmphasized = section.id === defaultTab;
      return <section key={section.id} id={`p0-devtools-panel__section--${section.id}`} className={"p0-devtools-panel__section" + (isEmphasized ? " p0-devtools-panel__section--active" : "")} aria-label={section.label}>
              <h4 className="p0-devtools-panel__section-heading">
                <svg {...iconBase} aria-hidden="true">
                  {renderShapes(section.shapes)}
                </svg>
                <span>{section.label}</span>
              </h4>
              <div className="p0-devtools-panel__section-body">
                {panes[section.id]}
              </div>
            </section>;
    })}
      </div>;
  }
  if (kind === "howToP0Dialog") {
    const htpIconBase = {
      ...iconBase,
      width: "16",
      height: "16"
    };
    const ICON_SHAPES = {
      archive: [{
        tag: "rect",
        attrs: {
          width: "20",
          height: "5",
          x: "2",
          y: "3",
          rx: "1"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M10 12h4"
        }
      }],
      book: [{
        tag: "path",
        attrs: {
          d: "M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v17a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"
        }
      }],
      calendarDays: [{
        tag: "path",
        attrs: {
          d: "M8 2v4"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M16 2v4"
        }
      }, {
        tag: "rect",
        attrs: {
          width: "18",
          height: "18",
          x: "3",
          y: "4",
          rx: "2"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M3 10h18"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M8 14h.01"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M12 14h.01"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M16 14h.01"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M8 18h.01"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M12 18h.01"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M16 18h.01"
        }
      }],
      code: [{
        tag: "polyline",
        attrs: {
          points: "16 18 22 12 16 6"
        }
      }, {
        tag: "polyline",
        attrs: {
          points: "8 6 2 12 8 18"
        }
      }],
      gitBranch: [{
        tag: "line",
        attrs: {
          x1: "6",
          x2: "6",
          y1: "3",
          y2: "15"
        }
      }, {
        tag: "circle",
        attrs: {
          cx: "18",
          cy: "6",
          r: "3"
        }
      }, {
        tag: "circle",
        attrs: {
          cx: "6",
          cy: "18",
          r: "3"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M18 9a9 9 0 0 1-9 9"
        }
      }],
      gitCompare: [{
        tag: "circle",
        attrs: {
          cx: "5",
          cy: "6",
          r: "3"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M12 6h5a2 2 0 0 1 2 2v7"
        }
      }, {
        tag: "circle",
        attrs: {
          cx: "19",
          cy: "18",
          r: "3"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M12 18H7a2 2 0 0 1-2-2V9"
        }
      }],
      gitPullRequestArrow: [{
        tag: "circle",
        attrs: {
          cx: "5",
          cy: "6",
          r: "3"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M5 9v12"
        }
      }, {
        tag: "circle",
        attrs: {
          cx: "19",
          cy: "18",
          r: "3"
        }
      }, {
        tag: "path",
        attrs: {
          d: "m15 9-3-3 3-3"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M12 6h5a2 2 0 0 1 2 2v7"
        }
      }],
      keyRound: [{
        tag: "path",
        attrs: {
          d: "M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z"
        }
      }, {
        tag: "circle",
        attrs: {
          cx: "16.5",
          cy: "7.5",
          r: ".5",
          fill: "currentColor"
        }
      }],
      lightbulb: [{
        tag: "path",
        attrs: {
          d: "M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M9 18h6"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M10 22h4"
        }
      }],
      messageCircle: [{
        tag: "path",
        attrs: {
          d: "M7.9 20A9 9 0 1 0 4 16.1L2 22z"
        }
      }],
      messageSquare: [{
        tag: "path",
        attrs: {
          d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"
        }
      }],
      notebookText: [{
        tag: "path",
        attrs: {
          d: "M2 6h4"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M2 10h4"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M2 14h4"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M2 18h4"
        }
      }, {
        tag: "rect",
        attrs: {
          width: "16",
          height: "20",
          x: "4",
          y: "2",
          rx: "2"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M9.5 8h5"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M9.5 12H16"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M9.5 16H14"
        }
      }],
      play: [{
        tag: "polygon",
        attrs: {
          points: "6 3 20 12 6 21 6 3"
        }
      }],
      rocket: [{
        tag: "path",
        attrs: {
          d: "M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z"
        }
      }, {
        tag: "path",
        attrs: {
          d: "m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"
        }
      }],
      terminal: [{
        tag: "polyline",
        attrs: {
          points: "4 17 10 11 4 5"
        }
      }, {
        tag: "line",
        attrs: {
          x1: "12",
          x2: "20",
          y1: "19",
          y2: "19"
        }
      }],
      testTube2: [{
        tag: "path",
        attrs: {
          d: "M21 7 6.82 21.18a2.83 2.83 0 0 1-3.99-.01a2.83 2.83 0 0 1 0-4L17 3"
        }
      }, {
        tag: "path",
        attrs: {
          d: "m16 2 6 6"
        }
      }, {
        tag: "path",
        attrs: {
          d: "M12 16H4"
        }
      }]
    };
    const SECTIONS = [{
      id: "modes-of-working",
      label: "Modes of Working",
      description: "p0 has different modes for different tasks. Pick the right one to get the best results.",
      tips: [{
        id: "brainstorm-mode",
        title: "Plan & Build Mode",
        description: "Use Plan & Build to flesh out an idea into a product spec, then let p0 build and QA it autonomously.",
        icon: "lightbulb"
      }, {
        id: "quick-changes",
        title: "Quick Changes (Chat)",
        description: "Ask p0 to fix bugs, refactor code, or make quick changes — just describe what you need.",
        icon: "messageSquare"
      }]
    }, {
      id: "project-setup",
      label: "Project Setup",
      description: "Open the Repositories manager from your sidebar to configure your project for p0.",
      tips: [{
        id: "engineering-standards",
        title: "Create Engineering Standards",
        description: "Define your coding conventions so p0 follows your team's patterns and preferences.",
        icon: "notebookText"
      }, {
        id: "qa-loops",
        title: "Create QA Loops",
        description: "Teach agents how to verify their work in your environment — URLs, credentials, and testing workflows.",
        icon: "testTube2"
      }, {
        id: "env-variables",
        title: "Set Up Environment Variables",
        description: "Configure .env files so p0 can run your project with the right secrets and config.",
        icon: "keyRound"
      }, {
        id: "run-commands",
        title: "Configure Run Commands",
        description: "Define how to start, build, or test your project so p0 can run it for you.",
        icon: "play"
      }, {
        id: "default-branch",
        title: "Set Default Branch",
        description: "Choose which branch p0 branches off from and creates PRs into for each repo.",
        icon: "gitPullRequestArrow"
      }]
    }, {
      id: "toolbar-actions",
      label: "Toolbar Actions",
      description: "On the top right of each session you'll find these tools to run, edit, and review your code.",
      tips: [{
        id: "open-terminal",
        title: "Open Terminal",
        description: "Launch a terminal inside your session's worktree to run commands without switching apps.",
        icon: "terminal"
      }, {
        id: "run-project",
        title: "Run Your Project",
        description: "Start your dev server or build process right from the session's worktree.",
        icon: "rocket"
      }, {
        id: "open-in-editor",
        title: "Open in Code Editor",
        description: "Open the session's worktree in your preferred code editor (VS Code, Cursor, etc.).",
        icon: "code"
      }, {
        id: "review-changes",
        title: "Review Changes",
        description: "See a diff of all changes p0 has made in the current session before committing.",
        icon: "gitCompare"
      }]
    }, {
      id: "advanced",
      label: "Advanced",
      description: "Power-user features that give you more control over how p0 works with your codebase.",
      tips: [{
        id: "worktrees",
        title: "Worktrees",
        description: "Each session branches off your repo's default branch into an isolated worktree — your main branch stays clean.",
        icon: "gitBranch"
      }, {
        id: "archive-sessions",
        title: "Archive & Unarchive Sessions",
        description: "Keep your sidebar clean by archiving old sessions. Right-click any session to archive or restore it.",
        icon: "archive"
      }]
    }];
    return <div className="p0-howto-dialog" role="img" aria-label="How to p0 dialog mock">
        <div className="p0-howto-dialog__header">
          <h3 className="p0-howto-dialog__title">How to p0</h3>
          <p className="p0-howto-dialog__subtitle">
            Learn everything p0 can do for you.
          </p>
        </div>

        {SECTIONS.map(section => <div key={section.id} className="p0-howto-dialog__section">
            <h4 className="p0-howto-dialog__section-heading">{section.label}</h4>
            <p className="p0-howto-dialog__section-desc">{section.description}</p>
            <ul className="p0-howto-dialog__tip-list">
              {section.tips.map(tip => <li key={tip.id} className="p0-howto-dialog__tip">
                  <span className="p0-howto-dialog__tip-check" aria-hidden="true" />
                  <span className="p0-howto-dialog__tip-body">
                    <span className="p0-howto-dialog__tip-title-row">
                      <svg {...htpIconBase} className="p0-howto-dialog__tip-icon">
                        {renderShapes(ICON_SHAPES[tip.icon] || [])}
                      </svg>
                      <span className="p0-howto-dialog__tip-title">{tip.title}</span>
                    </span>
                    <span className="p0-howto-dialog__tip-desc">{tip.description}</span>
                  </span>
                </li>)}
            </ul>
          </div>)}

        <div className="p0-howto-dialog__footer">
          <span className="p0-howto-dialog__footer-link">
            <svg {...htpIconBase} className="p0-howto-dialog__footer-icon">
              {renderShapes(ICON_SHAPES.book)}
            </svg>
            Open Documentation
          </span>
          <span className="p0-howto-dialog__footer-link">
            <svg {...htpIconBase} className="p0-howto-dialog__footer-icon">
              {renderShapes(ICON_SHAPES.messageCircle)}
            </svg>
            Join Community
          </span>
          <span className="p0-howto-dialog__footer-link">
            <svg {...htpIconBase} className="p0-howto-dialog__footer-icon">
              {renderShapes(ICON_SHAPES.calendarDays)}
            </svg>
            Book a Call
          </span>
        </div>
      </div>;
  }
  if (kind === "modelPicker") {
    const {current = "claude"} = rest;
    const mpIconBase = {
      ...iconBase,
      width: "16",
      height: "16"
    };
    const CHEVRON_SHAPES = [{
      tag: "path",
      attrs: {
        d: "m6 9 6 6 6-6"
      }
    }];
    const SPARKLES_SHAPES = [{
      tag: "path",
      attrs: {
        d: "M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"
      }
    }, {
      tag: "path",
      attrs: {
        d: "M20 3v4"
      }
    }, {
      tag: "path",
      attrs: {
        d: "M22 5h-4"
      }
    }, {
      tag: "path",
      attrs: {
        d: "M4 17v2"
      }
    }, {
      tag: "path",
      attrs: {
        d: "M5 18H3"
      }
    }];
    const CPU_SHAPES = [{
      tag: "rect",
      attrs: {
        width: "16",
        height: "16",
        x: "4",
        y: "4",
        rx: "2"
      }
    }, {
      tag: "rect",
      attrs: {
        width: "6",
        height: "6",
        x: "9",
        y: "9",
        rx: "1"
      }
    }, {
      tag: "path",
      attrs: {
        d: "M15 2v2"
      }
    }, {
      tag: "path",
      attrs: {
        d: "M15 20v2"
      }
    }, {
      tag: "path",
      attrs: {
        d: "M2 15h2"
      }
    }, {
      tag: "path",
      attrs: {
        d: "M2 9h2"
      }
    }, {
      tag: "path",
      attrs: {
        d: "M20 15h2"
      }
    }, {
      tag: "path",
      attrs: {
        d: "M20 9h2"
      }
    }, {
      tag: "path",
      attrs: {
        d: "M9 2v2"
      }
    }, {
      tag: "path",
      attrs: {
        d: "M9 20v2"
      }
    }];
    const MODEL_META = {
      claude: {
        label: "Claude",
        shapes: SPARKLES_SHAPES
      },
      codex: {
        label: "Codex",
        shapes: CPU_SHAPES
      }
    };
    const active = MODEL_META[current] ?? MODEL_META.claude;
    const alternateId = current === "claude" ? "codex" : "claude";
    const alternate = MODEL_META[alternateId];
    return <span className="p0-model-picker" role="img" aria-label={`Model picker mock, current selection ${active.label}`}>
        <button type="button" className="p0-model-picker__chip" aria-haspopup="listbox" aria-expanded="false">
          <svg {...mpIconBase} className="p0-model-picker__icon">
            {renderShapes(active.shapes)}
          </svg>
          <span className="p0-model-picker__label">{active.label}</span>
          <svg {...mpIconBase} className="p0-model-picker__chevron">
            {renderShapes(CHEVRON_SHAPES)}
          </svg>
        </button>
        <span className="p0-model-picker__menu" role="listbox" aria-hidden="true">
          <span className="p0-model-picker__option p0-model-picker__option--active">
            <svg {...mpIconBase} className="p0-model-picker__icon">
              {renderShapes(active.shapes)}
            </svg>
            <span className="p0-model-picker__label">{active.label}</span>
          </span>
          <span className="p0-model-picker__option">
            <svg {...mpIconBase} className="p0-model-picker__icon">
              {renderShapes(alternate.shapes)}
            </svg>
            <span className="p0-model-picker__label">{alternate.label}</span>
          </span>
        </span>
      </span>;
  }
  if (kind === "prCelebration") {
    const {prNumber, tokens, costCents} = rest;
    const formatCostCents = cents => {
      const safe = Number.isFinite(cents) ? Math.max(0, cents) : 0;
      return `$${(safe / 100).toFixed(2)}`;
    };
    const formatTokens = t => {
      const safe = Number.isFinite(t) ? Math.max(0, Math.floor(t)) : 0;
      return safe.toLocaleString("en-US");
    };
    const costLabel = formatCostCents(costCents);
    const tokenLabel = formatTokens(tokens);
    return <div className="p0-pr-celebration" role="img" aria-label={`PR shipped celebration overlay mock for PR #${prNumber}`}>
        <div className="p0-pr-celebration__backdrop" aria-hidden="true" />
        <div className="p0-pr-celebration__panel">
          <div className="p0-pr-celebration__icon" aria-hidden="true">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" width="16" height="16" className="p0-pr-celebration__icon-glyph" aria-hidden="true">
              <path d="M5.8 11.3 2 22l10.7-3.79" />
              <path d="M4 3h.01" />
              <path d="M22 8h.01" />
              <path d="M15 2h.01" />
              <path d="M22 20h.01" />
              <path d="m22 2-2.24.75a2.9 2.9 0 0 0-1.96 3.12c.1.86-.57 1.63-1.45 1.63h-.38c-.86 0-1.6.6-1.76 1.44L14 10" />
              <path d="m22 13-1.7.3c-.87.16-1.46.94-1.42 1.81v.5c.04.87-.55 1.65-1.42 1.81L16 18" />
              <path d="M3 7v4c0 1.1.9 2 2 2h4" />
              <path d="m7.5 11 4.55-4.55c.36-.36.85-.55 1.36-.45L17 7" />
            </svg>
          </div>
          <h3 className="p0-pr-celebration__title">Pull Request Created!</h3>
          <p className="p0-pr-celebration__pr">PR #{prNumber}</p>
          <p className="p0-pr-celebration__stats">
            <span className="p0-pr-celebration__stat-value">{tokenLabel}</span> tokens
            {" · "}
            <span className="p0-pr-celebration__stat-value">{costLabel}</span>
          </p>
          <div className="p0-pr-celebration__actions">
            <span className="p0-pr-celebration__btn p0-pr-celebration__btn--secondary">
              Continue
            </span>
            <span className="p0-pr-celebration__btn p0-pr-celebration__btn--primary">
              View PR
            </span>
          </div>
        </div>
      </div>;
  }
  if (kind === "contributionHeatmap") {
    const {weeks, seed} = rest;
    const ROWS = 7;
    const DEFAULT_WEEKS = 52;
    const DEFAULT_SEED = 42;
    const LEVELS = 5;
    const resolvedWeeks = weeks === undefined ? DEFAULT_WEEKS : weeks;
    const resolvedSeed = seed === undefined ? DEFAULT_SEED : seed;
    const makeRng = s => {
      let state = s >>> 0 || 1;
      return () => {
        state = Math.imul(state, 1664525) + 1013904223 >>> 0;
        return state;
      };
    };
    const pickLevel = rng => {
      const r = rng() >>> 16;
      if (r < 0.3 * 65536) return 0;
      if (r < 0.55 * 65536) return 1;
      if (r < 0.75 * 65536) return 2;
      if (r < 0.9 * 65536) return 3;
      return 4;
    };
    const rng = makeRng(resolvedSeed);
    const cells = [];
    for (let col = 0; col < resolvedWeeks; col++) {
      const column = [];
      for (let row = 0; row < ROWS; row++) {
        column.push(pickLevel(rng));
      }
      cells.push(column);
    }
    return <div className="p0-heatmap" role="img" aria-label={`Contribution heatmap mock — ${resolvedWeeks} weeks of activity`}>
        <div className="p0-heatmap__grid" aria-hidden="true">
          {cells.map((column, colIdx) => <div className="p0-heatmap__col" key={`col-${colIdx}`}>
              {column.map((level, rowIdx) => <span className={`p0-heatmap__cell p0-heatmap__cell--level-${level}`} key={`cell-${colIdx}-${rowIdx}`} />)}
            </div>)}
        </div>
        <div className="p0-heatmap__legend" aria-hidden="true">
          <span className="p0-heatmap__legend-label">Less</span>
          {Array.from({
      length: LEVELS
    }).map((_, i) => <span className={`p0-heatmap__cell p0-heatmap__cell--level-${i}`} key={`legend-${i}`} />)}
          <span className="p0-heatmap__legend-label">More</span>
        </div>
      </div>;
  }
  if (kind === "shareSheet") {
    const {link, teammates = [], expiry} = rest;
    const getInitials = name => {
      if (!name) return "?";
      const parts = name.trim().split(/\s+/);
      if (parts.length === 1) return parts[0].charAt(0).toUpperCase();
      return parts[0].charAt(0).toUpperCase() + parts[parts.length - 1].charAt(0).toUpperCase();
    };
    return <div className="p0-share-sheet" role="dialog" aria-label="Share session">
        <div className="p0-share-sheet__header">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" width="16" height="16" className="p0-share-sheet__icon" aria-hidden="true">
            <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" />
            <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" />
          </svg>
          <span className="p0-share-sheet__title">Share session</span>
        </div>

        <div className="p0-share-sheet__link-row">
          <input className="p0-share-sheet__link-input" type="text" value={link} readOnly aria-label="Share link" />
          <button className="p0-share-sheet__copy" type="button" aria-label="Copy link" onClick={event => event.preventDefault()}>
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" width="14" height="14" aria-hidden="true">
              <rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
              <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
            </svg>
            <span>Copy</span>
          </button>
        </div>

        {teammates.length > 0 ? <div className="p0-share-sheet__teammates">
            <span className="p0-share-sheet__label">Shared with</span>
            <div className="p0-share-sheet__avatars">
              {teammates.map((member, idx) => member.avatar ? <img key={`${member.name}-${idx}`} className="p0-share-sheet__avatar p0-share-sheet__avatar--img" src={member.avatar} alt={member.name} /> : <span key={`${member.name}-${idx}`} className="p0-share-sheet__avatar p0-share-sheet__avatar--initials" aria-label={member.name} title={member.name}>
                    {getInitials(member.name)}
                  </span>)}
            </div>
          </div> : null}

        {expiry ? <div className="p0-share-sheet__expiry">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" width="12" height="12" aria-hidden="true">
              <circle cx="12" cy="12" r="10" />
              <polyline points="12 6 12 12 16 14" />
            </svg>
            <span>{expiry}</span>
          </div> : null}
      </div>;
  }
  if (kind === "reviewsBell") {
    const {unread} = rest;
    const BADGE_CAP = 99;
    const count = Number.isFinite(unread) ? unread : 0;
    const showBadge = count > 0;
    const label = count > BADGE_CAP ? `${BADGE_CAP}+` : String(count);
    return <span className={`p0-reviews-bell${showBadge ? " p0-reviews-bell--has-unread" : ""}`} role="status" aria-label={showBadge ? `Reviews — ${count} unread` : "Reviews — no unread feedback"}>
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" width="18" height="18" className="p0-reviews-bell__icon" aria-hidden="true">
          <path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9" />
          <path d="M10.3 21a1.94 1.94 0 0 0 3.4 0" />
        </svg>
        {showBadge ? <span className="p0-reviews-bell__badge" aria-hidden="true">
            {label}
          </span> : null}
      </span>;
  }
  if (kind === "remoteControlQR") {
    const {code = "PURPLE"} = rest;
    const SIZE = 21;
    const FINDER = 7;
    const djb2 = input => {
      let hash = 5381;
      for (let i = 0; i < input.length; i++) {
        hash = (hash << 5) + hash + input.charCodeAt(i) | 0;
      }
      return hash >>> 0;
    };
    const makeRng = seed => {
      let state = seed >>> 0 || 1;
      return () => {
        state = Math.imul(state, 1664525) + 1013904223 >>> 0;
        return state;
      };
    };
    const isFinderCell = (row, col) => {
      const inTopLeft = row < FINDER && col < FINDER;
      const inTopRight = row < FINDER && col >= SIZE - FINDER;
      const inBottomLeft = row >= SIZE - FINDER && col < FINDER;
      return inTopLeft || inTopRight || inBottomLeft;
    };
    const finderFill = (row, col) => {
      let r = row;
      let c = col;
      if (col >= SIZE - FINDER) c = col - (SIZE - FINDER);
      if (row >= SIZE - FINDER) r = row - (SIZE - FINDER);
      const onOuterRing = r === 0 || r === 6 || c === 0 || c === 6;
      const inInnerSquare = r >= 2 && r <= 4 && c >= 2 && c <= 4;
      return onOuterRing || inInnerSquare;
    };
    const rng = makeRng(djb2(String(code)));
    const cells = [];
    for (let row = 0; row < SIZE; row++) {
      for (let col = 0; col < SIZE; col++) {
        let fill;
        if (isFinderCell(row, col)) {
          fill = finderFill(row, col);
        } else {
          fill = rng() >>> 31 === 1;
        }
        cells.push(fill);
      }
    }
    return <div className="p0-remote-qr" role="img" aria-label={`Illustrative QR mock for pairing code ${code}`}>
        <div className="p0-remote-qr__grid" style={{
      gridTemplateColumns: `repeat(${SIZE}, 1fr)`,
      gridTemplateRows: `repeat(${SIZE}, 1fr)`
    }} aria-hidden="true">
          {cells.map((fill, idx) => <span key={`qr-${idx}`} className={`p0-remote-qr__cell${fill ? " p0-remote-qr__cell--on" : ""}`} />)}
        </div>
        <div className="p0-remote-qr__caption">
          <span className="p0-remote-qr__illustrative">Illustrative</span>
          <span className="p0-remote-qr__code">{code}</span>
        </div>
        <div className="p0-remote-qr__status" role="status">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" width="14" height="14" className="p0-remote-qr__status-icon" aria-hidden="true">
            <rect x="5" y="2" width="14" height="20" rx="2" ry="2" />
            <path d="M12 18h.01" />
          </svg>
          <span>Waiting for phone…</span>
        </div>
      </div>;
  }
  if (kind === "kbdRow") {
    const {keys = [], description} = rest;
    return <span className="p0-kbd-row" role="group" aria-label={description}>
        <span className="p0-kbd-row__chips" aria-hidden="true">
          {keys.map((key, idx) => <span className="p0-kbd-row__chip" key={`kbd-${idx}-${key}`}>
              {idx > 0 ? <span className="p0-kbd-row__plus">+</span> : null}
              <kbd className="p0-kbd">{key}</kbd>
            </span>)}
        </span>
        <span className="p0-kbd-row__description">{description}</span>
      </span>;
  }
  if (kind === "renamedCallout") {
    const {from, to, version} = rest;
    return <span className="p0-renamed-callout" role="note">
        Renamed in v{version}:{" "}
        <span className="p0-renamed-callout__from">{from}</span>
        {" → "}
        <span className="p0-renamed-callout__to">{to}</span>
      </span>;
  }
  if (kind === "slashCommandsTable") {
    const SLASH_COMMANDS = [{
      command: "/agent",
      description: "Switch to Agent mode (applies changes directly)"
    }, {
      command: "/clear",
      description: "Start a new conversation (creates new sub-chat)"
    }, {
      command: "/compact",
      description: "Compact conversation context to reduce token usage"
    }, {
      command: "/config",
      description: "View and modify configuration settings"
    }, {
      command: "/cost",
      description: "Show token usage and cost for the session"
    }, {
      command: "/doctor",
      description: "Check the health of your p0 installation"
    }, {
      command: "/help",
      description: "Show available commands and help"
    }, {
      command: "/mcp",
      description: "View and manage MCP server connections"
    }, {
      command: "/memory",
      description: "View and edit CLAUDE.md memory files"
    }, {
      command: "/model",
      description: "Switch AI model"
    }, {
      command: "/permissions",
      description: "View and manage tool permissions"
    }, {
      command: "/plan",
      description: "Switch to Plan mode (creates plan before making changes)"
    }, {
      command: "/pr-comments",
      description: "Ask the agent to generate PR review comments"
    }, {
      command: "/release-notes",
      description: "Ask the agent to generate release notes"
    }, {
      command: "/review",
      description: "Ask the agent to review your code"
    }, {
      command: "/security-review",
      description: "Ask the agent to perform a security audit"
    }, {
      command: "/skills",
      description: "Manage your skills"
    }, {
      command: "/status",
      description: "Show current session status and context"
    }, {
      command: "/build-from-spec",
      description: "Run the end-to-end spec → build → QA pipeline"
    }, {
      command: "/create-standards",
      description: "Generate engineering standards for your workspace"
    }, {
      command: "/refine",
      description: "Make incremental changes to a recently built feature"
    }, {
      command: "/import-spec",
      description: "Import a product spec and ask clarifying questions"
    }];
    return <table>
        <thead>
          <tr>
            <th>Command</th>
            <th>What it does</th>
            <th>Where to find it</th>
          </tr>
        </thead>
        <tbody>
          {SLASH_COMMANDS.map(row => <tr key={row.command}>
              <td><code>{row.command}</code></td>
              <td>{row.description}</td>
              <td>Chat input · slash menu</td>
            </tr>)}
        </tbody>
      </table>;
  }
  return null;
};

A run script is a shell command saved on a repo. When you press **Play** in the run sidebar, p0 spawns the script in a PTY rooted at the repo's checkout.

## Configuring a script

Each repo row in the [repo manager](/repo-manager) has a run-script editor (it's also reachable from the run sidebar's "No run script configured" empty state). The dialog is titled **Run Script** and contains:

* A textarea for the command. Placeholder is `e.g. bun run dev`. Any shell command goes here — single line or multi-line.
* A button labeled **Add path-specific run command** for monorepos. Each entry is a sub-path inside the repo (e.g. `apps/api`) with its own script. The path input autocompletes from the repo's directory listing.

Saving the dialog with an empty textarea clears the root script. Toast: *Run script cleared for {repo}*.

## How p0 invokes it

When you press Play, p0:

1. Looks up the saved script for that repo (or sub-path).
2. Writes it to a temp file — `.sh` with a `#!/bin/bash` shebang on macOS/Linux, `.cmd` on Windows.
3. Spawns a PTY with the working directory set to `{worktree}/repos/{repo-name}` (plus the sub-path, if any) and runs the temp file (`exec bash <path>` on Unix, `call "<path>" & exit /B` on Windows).
4. Streams stdout/stderr into the xterm.js pane in the run sidebar.

The PTY accepts stdin, so prompts like "Ok to proceed? (y)" work — type into the pane and the keystrokes go to the process.

<Mock kind="terminalPane" prompt="$" command="bun run dev" output="VITE v5.0.0  ready in 312 ms\n\n  ➜  Local:   http://localhost:5173/" />

## Multiple scripts per repo

There's one root script per repo. On top of that, you can add any number of **path-specific** scripts for sub-directories — useful for monorepos where `apps/web` and `apps/api` each need their own dev command. Every sub-path with a script becomes its own tab in the run sidebar, labelled `{repo}/{sub-path}`.

## Lifecycle: Start, Stop, restart

The controls bar on each run-sidebar tab has a single Play/Stop button plus a status dot:

* **Gray dot** — idle, not started this session.
* **Green dot** — running.
* **Red dot** — exited. The exit code shows on the right when it's non-zero.

Start is idempotent — pressing Play while the process is already running is a no-op and returns the same pane. Stop is lenient — it returns success even if the process has already exited. Pressing Play after an exit resets the terminal and spawns a fresh process.
