diff --git a/README.md b/README.md
index 869c9c69..cbc62152 100644
--- a/README.md
+++ b/README.md
@@ -114,9 +114,13 @@ pnpm dev
### First run
-1. Onboarding probes your shell PATH for `node` (agents call the local HTTP API via `node -e`).
-2. Settings → Providers. Sign in or drop a key.
-3. Create a company: name, mission, goal, mode, workspace.
+1. Requirements. Welcome screen, then a Node.js check. CLI runtimes call the local API through `node -e`.
+2. Providers. Connect at least one runtime.
+3. Company. Enter name, description, and workspace.
+4. Team Models. Enable the models available to the CEO and workers.
+5. Mode. Default is `ai_ceo`; `ai_cofounder` keeps key decisions human-reviewed.
+6. Mission. Capture the first goal and acceptance description.
+7. Launch. AgentCompany creates the company, CEO agent, workspace, kickoff task, and initial run handoff.
---
diff --git a/docs/rebuild/05-design-system-and-flows.md b/docs/rebuild/05-design-system-and-flows.md
new file mode 100644
index 00000000..845eb0a6
--- /dev/null
+++ b/docs/rebuild/05-design-system-and-flows.md
@@ -0,0 +1,321 @@
+# Phase 5 — Design System & Desktop Flows
+
+> Visual + interaction system for the rebuild. Anchors: desktop-native, two-mode (AI CEO / AI Co-Founder), thread-runtime first, knowledge-backed. No web-dashboard-in-a-shell affordances.
+
+---
+
+## 1. Design intent
+
+A control-plane for an autonomous company. Calm. Information-dense. Keyboard-first. Pause moments are intentional — when AI Co-Founder mode pauses for review, the UI **feels** like a checkpoint, not a delay.
+
+The aesthetic baseline already lives in `landing/` and `screenshots/Dashboard.jpeg`: dusty navy (`#4a5d7a`), graphite text, off-white surfaces, restrained accent. We keep that palette and tighten the IA.
+
+## 2. Information architecture
+
+### 2.1 Top-level navigation (left rail)
+
+```
+┌─────────────────────────────────────┐
+│ ⌂ Dashboard │
+│ 📥 Inbox ⓘ │
+│ 🧵 Threads │
+│ ✓ Tasks & Approvals │
+│ 💼 Workspaces │
+│ 📚 Knowledge │
+│ ── │
+│ ⚙ Settings │
+│ 📊 Diagnostics │
+└─────────────────────────────────────┘
+```
+
+Sidebar collapses to icons at < 1100 px. Active item shows a subtle vertical accent bar.
+
+### 2.2 Top bar
+
+Per company: company picker · execution-mode pill (AI CEO / AI Co-Founder) · provider chip with active connector + cost-this-month · search · profile.
+
+The mode pill is interactive: clicking opens a small panel explaining the difference, with a switch.
+
+### 2.3 Onboarding (first run)
+
+Welcome opens the flow. The setup panel then runs 7 sections:
+
+1. **Requirements** — checks Node.js because CLI runtimes call the local API through `node -e`.
+2. **Providers** — connects at least one runtime.
+3. **Company** — captures company name, description, and workspace.
+4. **Team Models** — enables the models available to the CEO and workers.
+5. **Mode** — defaults to `ai_ceo`; `ai_cofounder` keeps key decisions human-reviewed.
+6. **Mission** — captures the first goal and acceptance description.
+7. **Launch** — creates the company, CEO agent, workspace, kickoff task, and initial run handoff.
+
+The user lands in Control Center after launch.
+
+### 2.4 Dashboard
+
+Top: 4 KPI tiles (Active agents, Tasks in review, Spend month-to-date, Waiting-on-you).
+Below: 3 columns —
+- "What's happening now" (live runs with brief status)
+- "Decisions waiting for you" (approval queue mirrors Inbox)
+- "Recent deliverables" (documents/work-products with reviewer)
+
+Empty states explain what each panel will hold once activity begins.
+
+### 2.5 Inbox
+
+A single ordered feed of `inbox_items`:
+
+| Type | Source | Action |
+|---|---|---|
+| Wait-on-you (approval) | `thread_wait_states` `waiting_for='human'` + linked approval | Approve / Deny inline |
+| @mention | `agent_messages.body` mention scan | Reply |
+| Subscribed thread update | `thread_subscriptions` + `conversation_events` | Open |
+| Deliverable for review | `tasks.requires_user_review` true | Open task |
+
+Counts shown in sidebar mirror the unread/wait totals.
+
+### 2.6 Threads
+
+A two-pane view: left = thread list (filter: All / Subscribed / Wait / Recent); right = thread transcript with composer.
+
+Transcript items: agent messages, tool executions (collapsible), tool results (collapsible), human posts, wait-state markers ("Waiting on @you to approve `bash` call …").
+
+Composer: posts a `user` message into the active thread → triggers `wakeup_request` for the assigned agent.
+
+### 2.7 Tasks & Approvals
+
+Existing task/approval surfaces preserved; added:
+
+- "Pending tool approvals" section grouped by run (each item shows tool, args summary, "Approve in thread" deep link).
+
+### 2.8 Workspaces
+
+Existing surface preserved. Adds workspace lock indicator and a "Reveal in Finder/Explorer/Files" button (uses `openPath`).
+
+### 2.9 Knowledge
+
+Existing surface preserved. Adds "Inject into agent" affordance — moves a knowledge entry into the prompt-builder context for the next run.
+
+### 2.10 Settings
+
+Sub-pages:
+
+```
+Settings
+ • Profile
+ • Providers ← new (the key addition)
+ • Execution defaults (mode default, thinking level, retry counts)
+ • Budgets
+ • Workspaces
+ • Skills
+ • Updates
+ • Advanced (logs path, profile dir, vault info)
+```
+
+### 2.11 Diagnostics
+
+Read-only:
+- Recent runs with status colours
+- Recent IPC errors
+- Vault backend label (e.g. "macOS Keychain" or "encrypted file")
+- Current pi-mono package versions
+- Open log directory button
+
+## 3. Settings → Providers panel (the central new surface)
+
+### 3.1 Layout
+
+```
+┌──────────────────────────────────────────────────────────────────────┐
+│ Providers │
+│ Search [ ] View: [Configured ▾] [+ Add provider]│
+│ │
+│ ── Configured (4) ──────────────────────────────────────────────── │
+│ ● Claude Pro/Max OAuth · claude.pro@gmail.com [Re-login][⋯] │
+│ ● Anthropic API Key · sk-ant-…abcd [Edit] [⋯] │
+│ ● AWS Bedrock AWS · profile=prod region=us-east-1 [Edit] │
+│ ! Gemini CLI OAuth · refresh failed [Re-login] │
+│ │
+│ ── Available (21) ─────────────────────────────────────────────── │
+│ ○ ChatGPT Plus/Pro (Codex) OAuth [Login] │
+│ ○ GitHub Copilot OAuth [Login] │
+│ ○ Antigravity OAuth [Login] │
+│ ○ OpenAI API Key [Add] │
+│ … │
+└──────────────────────────────────────────────────────────────────────┘
+```
+
+Status dot colours:
+- `●` green — `active`
+- `◐` amber — `expired` (refresh failed)
+- `!` red — `error`
+- `○` neutral — `not configured`
+
+### 3.2 Forms
+
+Five hand-written forms (no universal generator):
+
+1. **OAuthRow** — "Login" button, optional GHE domain prompt for GitHub Copilot (renders `OAuthPromptDialog`), shows progress (`onProgress` messages) inline as a tiny status line.
+2. **ApiKeyForm** — single password input (masked) + "Reveal" toggle + dropdown "Source: Inline value | Env var name". Save button.
+3. **AzureForm** — fields: `baseUrl`, `resourceName`, `apiVersion`, `deploymentMap` (key/value editor), `apiKey`. Save button.
+4. **AwsForm** — radio: "AWS profile" / "IAM keys" / "Bearer token", each revealing fields. Region (default `us-east-1`). Advanced toggles for `forceCache`, `endpointUrl`, `skipAuth`, `forceHttp1`.
+5. **VertexForm** — fields: `project`, `location`, `credentialsPath` (file picker, optional), "Use ADC" checkbox.
+
+Each form has a "Test connection" button that performs `streamSimple(... { maxTokens: 1 })` against the connector's default model with a 1-character prompt. Outcome: ✅ "OK — used $0.0001" / ❌ "".
+
+### 3.3 OAuthPromptDialog
+
+Modal triggered by `oauth:prompt-request` (e.g. GHE domain) and `oauth:manual-code-request` (fallback when callback server is blocked):
+
+```
+┌─────────────────────────────────────┐
+│ GitHub Copilot │
+│ │
+│ Enter your GitHub Enterprise domain. │
+│ Leave blank for github.com. │
+│ │
+│ [github.com_______________________] │
+│ │
+│ [Cancel] [Submit →] │
+└─────────────────────────────────────┘
+```
+
+## 4. Mode UX
+
+Mode pill in top bar:
+
+- **AI CEO** — solid green pill. Tooltip: "Tools execute without review. Approvals only for explicit policy gates."
+- **AI Co-Founder** — outlined navy pill. Tooltip: "Agents pause at write-side tools (bash, edit, write). You approve in Inbox."
+
+Switching modes is per-company. The switch action writes `companies.execution_mode` and a confirmation toast.
+
+### Pause state in a thread
+
+When a run pauses at `beforeToolCall`, the thread shows:
+
+```
+┌───────────────────────────────────────────┐
+│ ⟳ engineer-01 wants to run │
+│ │
+│ [bash] npm install │
+│ in workspaces/web-frontend │
+│ │
+│ [Approve] [Deny] [Approve & don't ask]│
+└───────────────────────────────────────────┘
+```
+
+"Approve & don't ask" sets a per-task auto-approval for the same tool with the same arg shape (writes `agent_permissions.permissions_json`).
+
+## 5. Visual system
+
+### 5.1 Tokens (Tailwind config)
+
+```
+colors:
+ navy.700 #2c3a4f
+ navy.600 #4a5d7a ← brand accent
+ navy.500 #6f8198
+ graphite #1f1f23 ← primary text
+ ash #56575a ← secondary text
+ fog #efeff1 ← surface alt
+ paper #f8f8f9 ← surface
+ accent #c98c5a ← warm accent (warnings, awaiting human)
+ ok #4a8d6f
+ warn #c79a45
+ err #b75252
+
+font:
+ sans Inter, ui-sans-serif
+ mono "JetBrains Mono", ui-monospace
+
+radius:
+ sm 4px / md 8px / lg 12px
+
+shadow:
+ card 0 1px 2px rgba(0,0,0,0.06), 0 0 0 1px rgba(0,0,0,0.04)
+```
+
+Dark mode: invert paper/fog/graphite axis; navy.600 preserved as accent.
+
+### 5.2 Spacing scale
+
+`4 / 8 / 12 / 16 / 24 / 32 / 48 / 64` px. No off-grid spacing.
+
+### 5.3 Components reused
+
+`src/renderer/components/ui/` already exposes primitives, layout, feedback, hooks. We extend it (no rewrite) with:
+
+- ``
+- ``
+- `` (Azure deployment map, custom env)
+- ``
+- ``
+
+### 5.4 Density + responsive
+
+- Default density: comfortable. Toggle to compact in Settings → Profile.
+- Window min size: `1024 × 720`. Sidebar collapses < 1100. Right panels collapse < 1280.
+- Drag-and-drop affordances:
+ - Knowledge entries → agent context (drag onto agent card).
+ - Files into Workspaces (already supported by underlying tooling; UI affordance added).
+
+### 5.5 Keyboard
+
+| Shortcut | Action |
+|---|---|
+| `⌘/Ctrl + K` | Quick open (companies, threads, tasks) |
+| `⌘/Ctrl + 1..9` | Switch sidebar item |
+| `⌘/Ctrl + Enter` | Submit composer / Approve highlighted item |
+| `Esc` | Close dialogs |
+| `?` | Show shortcuts overlay |
+
+## 6. Empty + loading + error states (mandatory per screen)
+
+Every new screen ships:
+
+- Empty illustration + 1-line explanation + 1-CTA.
+- Loading: skeleton blocks (no spinners except > 2 s).
+- Error: a `` with an action button (retry / open logs).
+
+No placeholder copy. No "Coming soon" text on any provider — every provider has either an active form or an inactive form with a clear "Configure" path.
+
+## 7. Microcopy rules
+
+- Lead with verbs ("Approve", "Deny", "Re-login").
+- Status text uses past tense ("Refreshed 2 min ago").
+- Cost expressed as `$0.012` (3 decimals when < $1, otherwise 2).
+- Token counts use grouping `12,345`.
+- Times use locale-aware format with absolute hover tooltip.
+
+## 8. Thread runtime UX bindings
+
+| Renderer concept | Binding |
+|---|---|
+| "Wait card" in thread | `thread_wait_states` row resolved == null |
+| "Read receipt" | (not in this rebuild) |
+| "Subscribed" badge | `thread_subscriptions` row exists |
+| "Mention" highlight | `agent_messages.body` mentions parsed at render time (existing helper) |
+| "Inject knowledge" | calls `agentCompany.addThreadEvent` with `event_type: 'knowledge_injection'`, then `wakeup_request` |
+
+## 9. Onboarding mode-explainer copy
+
+```
+AI CEO
+The CEO agent runs without pausing. Tools execute autonomously.
+Best for: research sprints, content batches, long-running automation.
+
+AI Co-Founder
+The CEO agent pauses before any tool that writes to your filesystem,
+modifies code, or runs a shell command. You approve in your Inbox.
+Best for: code in your real workspaces, anything you'd want to review first.
+
+You can switch any company between modes from the top bar.
+```
+
+## 10. Done criteria for Phase 5
+
+- Every screen is named.
+- Every form is a dedicated component.
+- Every state (empty/loading/error) has a rule.
+- Every status surface has a token.
+- The Providers panel is fully specified per the contract.
+- The mode UX is concrete, not aspirational.
diff --git a/landing/README.md b/landing/README.md
new file mode 100644
index 00000000..b179faed
--- /dev/null
+++ b/landing/README.md
@@ -0,0 +1,14 @@
+# AgentCompany Landing
+
+Next.js landing page for the AgentCompany desktop release lane.
+
+## Copy Sources
+
+| Surface | Source |
+|---|---|
+| Download cards | `landing/components/release-links.generated.ts` |
+| Platform FAQ | `landing/lib/platform-support.ts` |
+| Hero, How It Works, software JSON-LD features | `landing/lib/product-narrative.ts` |
+| Runtime download URLs | generated from `scripts/generate-landing-release-links.mjs` |
+
+The public story mirrors the first-run desktop flow: Welcome, Requirements, Providers, Company, Team Models, Mode, Mission, Launch.
diff --git a/landing/app/layout.tsx b/landing/app/layout.tsx
index 6083fae1..dc2d4df6 100644
--- a/landing/app/layout.tsx
+++ b/landing/app/layout.tsx
@@ -1,6 +1,10 @@
import type { Metadata } from "next";
import "./globals.css";
import { ThemeProvider } from "../components/theme-provider";
+import {
+ landingHowItWorksNarrative,
+ landingStructuredDataNarrative,
+} from "../lib/product-narrative";
import { platformSupportSummary } from "../lib/platform-support";
const description =
@@ -8,7 +12,7 @@ const description =
export const metadata: Metadata = {
metadataBase: new URL("https://agent-company.dev"),
- title: "AgentCompany — Launch an Autonomous AI Company in Minutes",
+ title: "AgentCompany - Launch an Autonomous AI Company from Your Desktop",
description,
keywords: [
"AI company",
@@ -32,7 +36,7 @@ export const metadata: Metadata = {
"AI company builder",
],
openGraph: {
- title: "AgentCompany — Launch an Autonomous AI Company in Minutes",
+ title: "AgentCompany - Launch an Autonomous AI Company from Your Desktop",
description,
url: "https://agent-company.dev/",
siteName: "AgentCompany",
@@ -49,7 +53,7 @@ export const metadata: Metadata = {
},
twitter: {
card: "summary_large_image",
- title: "AgentCompany — Launch an Autonomous AI Company in Minutes",
+ title: "AgentCompany - Launch an Autonomous AI Company from Your Desktop",
description,
images: ["/screenshots/Dashboard.jpeg"],
},
@@ -76,19 +80,9 @@ const softwareJsonLd = {
url: "https://agent-company.dev",
downloadUrl: "https://agent-company.dev/#download",
screenshot: "https://agent-company.dev/screenshots/Dashboard.jpeg",
- datePublished: "2026-03-01",
- softwareVersion: "1.0",
+ softwareVersion: landingStructuredDataNarrative.softwareVersion,
description,
- featureList: [
- "One-click AI company creation",
- "Self-organizing AI agent teams",
- "Autonomous task management",
- "Real-time agent communication",
- "Human-in-the-loop approvals",
- "AI document generation",
- "Multi-connector support (Claude, Codex, Gemini)",
- "Cross-platform (macOS, Windows, Linux)",
- ],
+ featureList: landingStructuredDataNarrative.featureList,
author: { "@type": "Organization", name: "AgentCompany", url: "https://agent-company.dev" },
};
@@ -104,27 +98,13 @@ const howToJsonLd = {
"@context": "https://schema.org",
"@type": "HowTo",
name: "How to Launch an Autonomous AI Company with AgentCompany",
- description: "Create a fully autonomous AI company in three steps using the AgentCompany desktop app.",
- step: [
- {
- "@type": "HowToStep",
- position: 1,
- name: "Set Your Goal",
- text: "Describe the company, its mission, and what you want delivered. Connect your preferred AI runtime.",
- },
- {
- "@type": "HowToStep",
- position: 2,
- name: "Agents Self-Organize",
- text: "A CEO agent analyzes your goal, hires specialists, creates departments, and delegates the work autonomously.",
- },
- {
- "@type": "HowToStep",
- position: 3,
- name: "Collect Results",
- text: "Review deliverables, approve critical decisions, and download finished work including code, content, and research.",
- },
- ],
+ description: "Complete the AgentCompany desktop first-run flow and queue the first mission.",
+ step: landingHowItWorksNarrative.steps.map((step) => ({
+ "@type": "HowToStep",
+ position: step.number,
+ name: step.title,
+ text: step.description,
+ })),
};
const faqJsonLd = {
diff --git a/landing/components/hero.tsx b/landing/components/hero.tsx
index 77dc9564..1cf01bf8 100644
--- a/landing/components/hero.tsx
+++ b/landing/components/hero.tsx
@@ -2,6 +2,7 @@
import { motion } from "framer-motion";
import { AsciiBackground } from "./ascii-background";
+import { landingHeroNarrative } from "../lib/product-narrative";
const sharedEase: [number, number, number, number] = [0.16, 1, 0.3, 1];
@@ -54,7 +55,7 @@ export function Hero() {
- Agent Company
+ {landingHeroNarrative.eyebrow}
@@ -62,16 +63,15 @@ export function Hero() {
{...heroMotion(0.15)}
className="mt-8 font-serif text-[clamp(2.75rem,2rem+3.8vw,5rem)] font-normal leading-[1.0] tracking-[-0.03em] text-[var(--text)]"
>
- Launch an AI Company
- in Minutes
+ {landingHeroNarrative.titleLine1}
+ {landingHeroNarrative.titleLine2}
- Describe your company's mission. A CEO agent recruits the team, delegates work, and delivers real
- results — code, content, research, and more. You're the founder.
+ {landingHeroNarrative.description}
@@ -104,7 +104,7 @@ export function Hero() {
- Available on macOS, Windows & Linux
+ {landingHeroNarrative.availability}
diff --git a/landing/components/how-it-works.tsx b/landing/components/how-it-works.tsx
index d4b974a2..79bd784f 100644
--- a/landing/components/how-it-works.tsx
+++ b/landing/components/how-it-works.tsx
@@ -2,32 +2,19 @@
import { motion, useInView } from "framer-motion";
import { useEffect, useRef, useState } from "react";
+import { landingHowItWorksNarrative } from "../lib/product-narrative";
-const demoMessages = [
- { agent: "You", role: "system", text: "Build a SaaS landing page with pricing, blog, and auth.", delay: 0 },
- { agent: "CEO", role: "ceo", text: "Analyzing goal... Creating departments: Engineering, Design, Content.", delay: 800 },
- { agent: "CEO", role: "ceo", text: "Hiring 4 specialists for this mission.", delay: 1600 },
- { agent: "Lead Engineer", role: "engineer", text: "Picked up task: Set up Next.js project with auth routes.", delay: 2400 },
- { agent: "UI Designer", role: "designer", text: "Picked up task: Design landing page and pricing components.", delay: 3000 },
- { agent: "Researcher", role: "researcher", text: "Picked up task: Competitive analysis of SaaS pricing models.", delay: 3600 },
- { agent: "Lead Engineer", role: "engineer", text: "Completed: Auth scaffolding with JWT + session middleware.", delay: 4400 },
- { agent: "UI Designer", role: "designer", text: "Completed: Responsive landing page with 3-tier pricing grid.", delay: 5200 },
- { agent: "CEO", role: "ceo", text: "All tasks delivered. 3 documents ready for review.", delay: 6000 },
-];
+const demoMessages = landingHowItWorksNarrative.demoMessages;
const logTone: Record<(typeof demoMessages)[number]["role"], string> = {
system: "text-[var(--muted-strong)]",
- ceo: "text-[#ca8a04]",
- engineer: "text-[var(--accent)]",
- designer: "text-[#8b5cf6]",
- researcher: "text-[#059669]",
};
-const steps = [
- { number: 1, title: "Set Your Goal", description: "Describe the company, its mission, and what you want delivered." },
- { number: 2, title: "Agents Self-Organize", description: "A CEO analyzes your goal, hires specialists, and delegates the work." },
- { number: 3, title: "Collect Results", description: "Review deliverables, approve decisions, and download finished work." },
-];
+const dotTone: Record<(typeof demoMessages)[number]["role"], string> = {
+ system: "bg-[var(--muted-strong)]",
+};
+
+const steps = landingHowItWorksNarrative.steps;
function DemoPanel() {
const anchorRef = useRef(null);
@@ -72,17 +59,7 @@ function DemoPanel() {
>
{message.agent}
@@ -106,7 +83,7 @@ function DemoPanel() {
- Company run complete. All deliverables ready.
+ {landingHowItWorksNarrative.completionText}
)}
@@ -126,7 +103,7 @@ export function HowItWorks() {
How It Works
- Watch a Company Come to Life
+ {landingHowItWorksNarrative.heading}
@@ -134,7 +111,7 @@ export function HowItWorks() {
-
+
{steps.map((step, index) => (
{
+ it("uses the generated release version for software structured data", () => {
+ expect(releaseVersion).toMatch(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/);
+ expect(landingStructuredDataNarrative.softwareVersion).toBe(releaseVersion);
+ });
+
+ it("describes the current first-run setup flow", () => {
+ expect(landingHeroNarrative).toMatchObject({
+ eyebrow: "AgentCompany Desktop",
+ titleLine1: "Launch an Autonomous AI Company",
+ titleLine2: "from Your Desktop",
+ });
+ expect(landingHeroNarrative.description).toContain("AI CEO by default");
+ expect(landingHeroNarrative.description).toContain("AI Co-Founder for human-reviewed decisions");
+
+ expect(landingHowItWorksNarrative.steps.map((step) => step.title)).toEqual([
+ "Requirements",
+ "Providers",
+ "Company",
+ "Team Models",
+ "Mode",
+ "Mission",
+ "Launch",
+ ]);
+ expect(landingHowItWorksNarrative.demoMessages.map((message) => message.text)).toEqual([
+ "Node.js ready. CLI runtimes can call the local API.",
+ "Runtime connected.",
+ "Company profile and workspace saved.",
+ "Model pool enabled for CEO and workers.",
+ "AI CEO mode selected.",
+ "First goal and acceptance description captured.",
+ "Company, CEO agent, kickoff task, and initial run created.",
+ ]);
+ expect(landingStructuredDataNarrative.featureList).toContain(
+ "Multi-connector support (Claude Code, Codex CLI, Gemini CLI)",
+ );
+ });
+
+ it("keeps first-run documentation ordered by the same setup sections", () => {
+ const files = [
+ "README.md",
+ "docs/rebuild/05-design-system-and-flows.md",
+ "landing/README.md",
+ ];
+
+ for (const file of files) {
+ const text = readFileSync(file, "utf8");
+ const positions = [];
+ let searchOffset = 0;
+
+ for (const step of onboardingFlowNarrative.sections) {
+ const position = text.indexOf(step.title, searchOffset);
+ positions.push(position);
+ searchOffset = position + step.title.length;
+ }
+
+ expect(positions.every((position) => position >= 0)).toBe(true);
+ expect(positions).toEqual([...positions].sort((left, right) => left - right));
+ }
+ });
+});