[object Object]

← back to Ventura Claw

Rebrand Commerce Claw / BusinessClaw → VenturaClaw

181cd5f2130702e8e9fb7101795ed7332390030a · 2026-05-06 10:21:48 -0700 · Steve Abrams

Rename the product and live hostname end-to-end:
- 96 user-visible refs swapped across public HTML, server.js, marketing
  pages, login, oauth-setup, JSON-LD/OG tags. Brand-name keeps the
  italic-gold treatment by splitting Ventura<em>Claw</em>.
- Subtitle 'Connected Commerce' → 'Connected Operations'.
- Footer email info@businessclaw.com → info@venturaclaw.agentabrams.com
  (mailbox provisioned on Purelymail with full MX/SPF/DKIM/DMARC).
- Bulk-select-and-connect on /connections: per-tile checkboxes plus a
  Select-all / Connect-selected control bar that walks selected
  providers through their OAuth popups in a sessionStorage-backed
  queue, with a Continue button between each so each popup gets a
  fresh user gesture and avoids browser pop-up blocks.
- Hardcoded log tag [commerce-claw] → [ventura-claw].
- launchd job com.steve.businessclaw-sync → com.steve.venturaclaw-sync;
  sync-tokens.js paths + default BC_URL repointed to venturaclaw.

Live at https://venturaclaw.agentabrams.com (Let's Encrypt SSL,
nginx → 127.0.0.1:9788). businessclaw.agentabrams.com 301-redirects
all paths except /oauth/* + /healthz so existing OAuth callback URLs
registered in each provider's developer console keep working.

Files touched

Diff

commit 181cd5f2130702e8e9fb7101795ed7332390030a
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed May 6 10:21:48 2026 -0700

    Rebrand Commerce Claw / BusinessClaw → VenturaClaw
    
    Rename the product and live hostname end-to-end:
    - 96 user-visible refs swapped across public HTML, server.js, marketing
      pages, login, oauth-setup, JSON-LD/OG tags. Brand-name keeps the
      italic-gold treatment by splitting Ventura<em>Claw</em>.
    - Subtitle 'Connected Commerce' → 'Connected Operations'.
    - Footer email info@businessclaw.com → info@venturaclaw.agentabrams.com
      (mailbox provisioned on Purelymail with full MX/SPF/DKIM/DMARC).
    - Bulk-select-and-connect on /connections: per-tile checkboxes plus a
      Select-all / Connect-selected control bar that walks selected
      providers through their OAuth popups in a sessionStorage-backed
      queue, with a Continue button between each so each popup gets a
      fresh user gesture and avoids browser pop-up blocks.
    - Hardcoded log tag [commerce-claw] → [ventura-claw].
    - launchd job com.steve.businessclaw-sync → com.steve.venturaclaw-sync;
      sync-tokens.js paths + default BC_URL repointed to venturaclaw.
    
    Live at https://venturaclaw.agentabrams.com (Let's Encrypt SSL,
    nginx → 127.0.0.1:9788). businessclaw.agentabrams.com 301-redirects
    all paths except /oauth/* + /healthz so existing OAuth callback URLs
    registered in each provider's developer console keep working.
---
 .gitignore                             |   2 +
 API.md                                 |  12 +-
 DEPLOY.md                              |   2 +-
 MARKETING.md                           |  10 +-
 PLAN.md                                |   4 +-
 app/app/ai/page.tsx                    |   2 +-
 app/app/approval-queue/page.tsx        |   2 +-
 app/app/audit-log/page.tsx             |   2 +-
 app/app/chat/page.tsx                  |   2 +-
 app/app/connectors/page.tsx            |   2 +-
 app/app/dashboard/page.tsx             |   2 +-
 app/app/login/page.tsx                 |   2 +-
 app/app/orders/page.tsx                |   2 +-
 app/app/payments/page.tsx              |   2 +-
 app/app/settings/page.tsx              |   2 +-
 app/app/social-publisher/page.tsx      |   2 +-
 app/app/workflows/page.tsx             |   2 +-
 app/icon.svg                           |   4 +
 app/lib/mcp/all-connectors.ts          |   2 +-
 app/lib/mcp/framework.ts               |   2 +-
 docs/research/connectors.md            |   2 +-
 relay/server.js                        |  14 +-
 scripts/auto-build.sh                  |   4 +-
 scripts/build-connectors.sh            |   4 +-
 scripts/populate-credentials.js        |   2 +-
 scripts/sync-tokens.js                 |  12 +-
 server/connectors.json                 |  12 ++
 server/connectors/archive.js           | 129 ++++++++++++
 server/connectors/cloudflare.js        |   2 +-
 server/connectors/index.js             |   5 +-
 server/connectors/slack.js             |   2 +-
 server/connectors/stripe.js            |   2 +-
 server/data/connector-acquisition.json |   8 +
 server/lib/comms-compliance.js         |   2 +-
 server/lib/oauth-refresh.js            |   2 +-
 server/llm.js                          |   2 +-
 server/public/admin-approvals.html     |   6 +-
 server/public/admin-audit.html         |   6 +-
 server/public/admin-connectors.html    |   6 +-
 server/public/admin-users.html         |   6 +-
 server/public/admin.html               |   6 +-
 server/public/brand.html               |   8 +-
 server/public/chat.html                |  56 +++++-
 server/public/connections-import.html  |   6 +-
 server/public/connections.html         | 353 +++++++++++++++++++++++++++++++--
 server/public/fill.html                | 146 ++++++++++++++
 server/public/homepage.html            |  36 ++--
 server/public/login.html               |  24 +--
 server/public/oauth-setup.html         |  12 +-
 server/public/style.css                |   2 +-
 server/server.js                       | 140 +++++++++----
 server/tests/integration.test.js       |   6 +-
 viewer/public/app.js                   |   2 +-
 viewer/public/index.html               |   4 +-
 viewer/public/style.css                |   2 +-
 viewer/server.js                       |   2 +-
 56 files changed, 915 insertions(+), 180 deletions(-)

diff --git a/.gitignore b/.gitignore
index a60cf22..298a133 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,8 @@ server/data/oauth-state.json
 server/data/audit.json
 server/data/approvals.json
 server/data/comms-suppression.json
+server/data/chat-history.json
+server/data/credentials.review-sample.json
 
 # Backups
 *.tmp.*
diff --git a/API.md b/API.md
index 5183904..441eb41 100644
--- a/API.md
+++ b/API.md
@@ -1,4 +1,4 @@
-# Commerce Claw API Reference
+# VenturaClaw API Reference
 
 Production endpoint: `https://businessclaw.agentabrams.com`
 
@@ -6,7 +6,7 @@ Production endpoint: `https://businessclaw.agentabrams.com`
 
 ## Authentication & Sessions
 
-Commerce Claw uses HMAC-signed cookies for session management. All protected endpoints require a valid `cc_session` cookie.
+VenturaClaw uses HMAC-signed cookies for session management. All protected endpoints require a valid `cc_session` cookie.
 
 ### POST /api/auth/login
 **Public** — Create a user session
@@ -92,7 +92,7 @@ curl -X POST https://businessclaw.agentabrams.com/api/auth/logout \
 
 ## Connectors
 
-Commerce Claw connectors are pre-built integrations (Stripe, Cloudflare, Shopify, 56+ total). Users authenticate connectors individually by storing credentials.
+VenturaClaw connectors are pre-built integrations (Stripe, Cloudflare, Shopify, 56+ total). Users authenticate connectors individually by storing credentials.
 
 ### GET /api/connectors
 **Session required** — List all available connectors with configuration status
@@ -376,7 +376,7 @@ EOF
 
 ## OAuth Configuration (Admin)
 
-Commerce Claw supports 10 OAuth providers (Google, Slack, Stripe Connect, Notion, HubSpot, Mailchimp, Discord, and 3 more). An admin registers each vendor's OAuth app once. Users then click "Connect Vendor" to grant permissions.
+VenturaClaw supports 10 OAuth providers (Google, Slack, Stripe Connect, Notion, HubSpot, Mailchimp, Discord, and 3 more). An admin registers each vendor's OAuth app once. Users then click "Connect Vendor" to grant permissions.
 
 ### GET /api/admin/oauth/providers
 **Admin required** — List OAuth providers + setup status + redirect URIs
@@ -1098,12 +1098,12 @@ All data persists to JSON files in `/server/data/`:
 
 ## Public Domain
 
-Commerce Claw is deployed to `https://businessclaw.agentabrams.com`. All subdomains/paths require SSL. Robots.txt blocks `/admin` and `/api` from search indexing.
+VenturaClaw is deployed to `https://businessclaw.agentabrams.com`. All subdomains/paths require SSL. Robots.txt blocks `/admin` and `/api` from search indexing.
 
 ---
 
 ## Support
 
-For API issues, contact `info@agentabrams.com` or file an issue in the Commerce Claw project.
+For API issues, contact `info@agentabrams.com` or file an issue in the VenturaClaw project.
 
 Last updated: 2026-05-05
diff --git a/DEPLOY.md b/DEPLOY.md
index adb2cd3..139353c 100644
--- a/DEPLOY.md
+++ b/DEPLOY.md
@@ -1,4 +1,4 @@
-# Commerce Claw — Go-Live Deployment
+# VenturaClaw — Go-Live Deployment
 
 **Target:** `businessclaw.agentabrams.com` → Kamatera (45.61.58.125) → port 9788, fronted by nginx + Cloudflare proxy.
 
diff --git a/MARKETING.md b/MARKETING.md
index dafa2d4..28e7d07 100644
--- a/MARKETING.md
+++ b/MARKETING.md
@@ -1,10 +1,10 @@
-# Commerce Claw — launch comms drafts
+# VenturaClaw — launch comms drafts
 
 ## Show HN draft
-**Title:** Show HN: Commerce Claw – Type one sentence, AI runs the right SaaS tool
+**Title:** Show HN: VenturaClaw – Type one sentence, AI runs the right SaaS tool
 
 **Body:**
-> I built Commerce Claw because every workflow-builder I tried — Zapier, Make, n8n — felt like more work than the work it was supposed to replace. Drag, wire, debug, maintain. The actual job ("refund this order", "post in #launch", "purge the cache") is one sentence; the canvas was a tax.
+> I built VenturaClaw because every workflow-builder I tried — Zapier, Make, n8n — felt like more work than the work it was supposed to replace. Drag, wire, debug, maintain. The actual job ("refund this order", "post in #launch", "purge the cache") is one sentence; the canvas was a tax.
 >
 > So this tool sells the outcome, not the canvas. You type what you want; a local LLM (qwen3:14b on a Mac Studio in my office) picks the connector and runs it. 56 SaaS tools pre-wired out of the box. Sensitive actions are gated by an approval queue with the parsed intent shown in plain English. API keys are AES-256-GCM encrypted at rest with a versioned key envelope.
 >
@@ -28,7 +28,7 @@
 
 ## Twitter / X announce (280 chars)
 
-> Commerce Claw is live: type one sentence ("refund order 1234 on shopify"), the local LLM picks the right SaaS tool from 56 wired connectors, runs it. Sensitive actions gated by approval queue. No workflow builder. No third-party LLM. https://businessclaw.agentabrams.com/
+> VenturaClaw is live: type one sentence ("refund order 1234 on shopify"), the local LLM picks the right SaaS tool from 56 wired connectors, runs it. Sensitive actions gated by approval queue. No workflow builder. No third-party LLM. https://businessclaw.agentabrams.com/
 
 ---
 
@@ -39,7 +39,7 @@
 **Body:**
 Hey IH,
 
-I just shipped Commerce Claw at https://businessclaw.agentabrams.com/. Quick summary:
+I just shipped VenturaClaw at https://businessclaw.agentabrams.com/. Quick summary:
 
 **The problem:** Zapier, Make, n8n all sell you the *canvas*. You drag triggers to actions, wire them up, maintain them. The actual job is one English sentence; the canvas is a tax.
 
diff --git a/PLAN.md b/PLAN.md
index fd7f4ae..172fb44 100644
--- a/PLAN.md
+++ b/PLAN.md
@@ -1,9 +1,9 @@
-# Commerce Claw — Auto-Build Plan
+# VenturaClaw — Auto-Build Plan
 
 > Run end-to-end without user interaction. Live build viewer at http://127.0.0.1:9785
 
 ## Product
-**Commerce Claw** — AI command center for small-business commerce, payments, social, support, automation, security. Liquid-glass / Apple Web 4.0 UI. Admin + User roles. Mock-first MCP connectors with real-server hooks.
+**VenturaClaw** — AI command center for small-business commerce, payments, social, support, automation, security. Liquid-glass / Apple Web 4.0 UI. Admin + User roles. Mock-first MCP connectors with real-server hooks.
 
 ## Stack
 - Next.js 15 App Router + TypeScript + Tailwind
diff --git a/app/app/ai/page.tsx b/app/app/ai/page.tsx
index 867a4dd..9d3ee6e 100644
--- a/app/app/ai/page.tsx
+++ b/app/app/ai/page.tsx
@@ -1,4 +1,4 @@
 import { GlassCard } from "@/components/glass";
 export default function Page() {
-  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">ai</h1><p className="opacity-70 mt-2">Commerce Claw — ai screen scaffold.</p></GlassCard></main>;
+  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">ai</h1><p className="opacity-70 mt-2">VenturaClaw — ai screen scaffold.</p></GlassCard></main>;
 }
diff --git a/app/app/approval-queue/page.tsx b/app/app/approval-queue/page.tsx
index dd515e7..4d7bafa 100644
--- a/app/app/approval-queue/page.tsx
+++ b/app/app/approval-queue/page.tsx
@@ -1,4 +1,4 @@
 import { GlassCard } from "@/components/glass";
 export default function Page() {
-  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">approval-queue</h1><p className="opacity-70 mt-2">Commerce Claw — approval-queue screen scaffold.</p></GlassCard></main>;
+  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">approval-queue</h1><p className="opacity-70 mt-2">VenturaClaw — approval-queue screen scaffold.</p></GlassCard></main>;
 }
diff --git a/app/app/audit-log/page.tsx b/app/app/audit-log/page.tsx
index bfaa052..388e256 100644
--- a/app/app/audit-log/page.tsx
+++ b/app/app/audit-log/page.tsx
@@ -1,4 +1,4 @@
 import { GlassCard } from "@/components/glass";
 export default function Page() {
-  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">audit-log</h1><p className="opacity-70 mt-2">Commerce Claw — audit-log screen scaffold.</p></GlassCard></main>;
+  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">audit-log</h1><p className="opacity-70 mt-2">VenturaClaw — audit-log screen scaffold.</p></GlassCard></main>;
 }
diff --git a/app/app/chat/page.tsx b/app/app/chat/page.tsx
index 57c9a98..07a012a 100644
--- a/app/app/chat/page.tsx
+++ b/app/app/chat/page.tsx
@@ -71,7 +71,7 @@ export default function ChatPage() {
       <GlassCard className="flex flex-col p-4 h-[calc(100vh-3rem)]">
         <div className="flex items-center justify-between mb-3">
           <div>
-            <div className="text-lg font-semibold">Commerce Claw — Chat</div>
+            <div className="text-lg font-semibold">VenturaClaw — Chat</div>
             <div className="text-xs opacity-60">All connectors active. Sensitive actions go to the approval queue.</div>
           </div>
           <a href="/approval-queue" className="text-xs opacity-70 hover:opacity-100">Approval queue →</a>
diff --git a/app/app/connectors/page.tsx b/app/app/connectors/page.tsx
index 97f7368..9a3d1fb 100644
--- a/app/app/connectors/page.tsx
+++ b/app/app/connectors/page.tsx
@@ -1,4 +1,4 @@
 import { GlassCard } from "@/components/glass";
 export default function Page() {
-  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">connectors</h1><p className="opacity-70 mt-2">Commerce Claw — connectors screen scaffold.</p></GlassCard></main>;
+  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">connectors</h1><p className="opacity-70 mt-2">VenturaClaw — connectors screen scaffold.</p></GlassCard></main>;
 }
diff --git a/app/app/dashboard/page.tsx b/app/app/dashboard/page.tsx
index 7a22747..5fc04b8 100644
--- a/app/app/dashboard/page.tsx
+++ b/app/app/dashboard/page.tsx
@@ -1,4 +1,4 @@
 import { GlassCard } from "@/components/glass";
 export default function Page() {
-  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">dashboard</h1><p className="opacity-70 mt-2">Commerce Claw — dashboard screen scaffold.</p></GlassCard></main>;
+  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">dashboard</h1><p className="opacity-70 mt-2">VenturaClaw — dashboard screen scaffold.</p></GlassCard></main>;
 }
diff --git a/app/app/login/page.tsx b/app/app/login/page.tsx
index 36d419e..0d219b9 100644
--- a/app/app/login/page.tsx
+++ b/app/app/login/page.tsx
@@ -25,7 +25,7 @@ export default function LoginPage() {
         <div className="flex items-center gap-3 mb-8">
           <div className="w-10 h-10 rounded-xl bg-gradient-to-br from-cyan-300 via-violet-400 to-fuchsia-400" />
           <div>
-            <div className="text-xl font-semibold">Commerce Claw</div>
+            <div className="text-xl font-semibold">VenturaClaw</div>
             <div className="text-xs uppercase tracking-widest opacity-60">login</div>
           </div>
         </div>
diff --git a/app/app/orders/page.tsx b/app/app/orders/page.tsx
index 1ac6c95..e7a4d81 100644
--- a/app/app/orders/page.tsx
+++ b/app/app/orders/page.tsx
@@ -1,4 +1,4 @@
 import { GlassCard } from "@/components/glass";
 export default function Page() {
-  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">orders</h1><p className="opacity-70 mt-2">Commerce Claw — orders screen scaffold.</p></GlassCard></main>;
+  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">orders</h1><p className="opacity-70 mt-2">VenturaClaw — orders screen scaffold.</p></GlassCard></main>;
 }
diff --git a/app/app/payments/page.tsx b/app/app/payments/page.tsx
index 44e6b66..3abd097 100644
--- a/app/app/payments/page.tsx
+++ b/app/app/payments/page.tsx
@@ -1,4 +1,4 @@
 import { GlassCard } from "@/components/glass";
 export default function Page() {
-  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">payments</h1><p className="opacity-70 mt-2">Commerce Claw — payments screen scaffold.</p></GlassCard></main>;
+  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">payments</h1><p className="opacity-70 mt-2">VenturaClaw — payments screen scaffold.</p></GlassCard></main>;
 }
diff --git a/app/app/settings/page.tsx b/app/app/settings/page.tsx
index 301e613..1d245fc 100644
--- a/app/app/settings/page.tsx
+++ b/app/app/settings/page.tsx
@@ -1,4 +1,4 @@
 import { GlassCard } from "@/components/glass";
 export default function Page() {
-  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">settings</h1><p className="opacity-70 mt-2">Commerce Claw — settings screen scaffold.</p></GlassCard></main>;
+  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">settings</h1><p className="opacity-70 mt-2">VenturaClaw — settings screen scaffold.</p></GlassCard></main>;
 }
diff --git a/app/app/social-publisher/page.tsx b/app/app/social-publisher/page.tsx
index 342495a..a9cfbe3 100644
--- a/app/app/social-publisher/page.tsx
+++ b/app/app/social-publisher/page.tsx
@@ -1,4 +1,4 @@
 import { GlassCard } from "@/components/glass";
 export default function Page() {
-  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">social-publisher</h1><p className="opacity-70 mt-2">Commerce Claw — social-publisher screen scaffold.</p></GlassCard></main>;
+  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">social-publisher</h1><p className="opacity-70 mt-2">VenturaClaw — social-publisher screen scaffold.</p></GlassCard></main>;
 }
diff --git a/app/app/workflows/page.tsx b/app/app/workflows/page.tsx
index 5cfad4d..f2dc246 100644
--- a/app/app/workflows/page.tsx
+++ b/app/app/workflows/page.tsx
@@ -1,4 +1,4 @@
 import { GlassCard } from "@/components/glass";
 export default function Page() {
-  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">workflows</h1><p className="opacity-70 mt-2">Commerce Claw — workflows screen scaffold.</p></GlassCard></main>;
+  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">workflows</h1><p className="opacity-70 mt-2">VenturaClaw — workflows screen scaffold.</p></GlassCard></main>;
 }
diff --git a/app/icon.svg b/app/icon.svg
new file mode 100644
index 0000000..65b4e06
--- /dev/null
+++ b/app/icon.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
+<rect width="32" height="32" rx="6" fill="#10b981"/>
+<text x="50%" y="55%" text-anchor="middle" dominant-baseline="middle" font-size="20" font-family="Apple Color Emoji, Segoe UI Emoji, sans-serif" fill="white">B</text>
+</svg>
\ No newline at end of file
diff --git a/app/lib/mcp/all-connectors.ts b/app/lib/mcp/all-connectors.ts
index c5fb30c..969d9e2 100644
--- a/app/lib/mcp/all-connectors.ts
+++ b/app/lib/mcp/all-connectors.ts
@@ -1,4 +1,4 @@
-// Commerce Claw — All 56 connectors with Zapier-style triggers + actions
+// VenturaClaw — All 56 connectors with Zapier-style triggers + actions
 import { register, type Connector } from "./framework";
 
 const sensitive = (id: string) => /\b(send|publish|create|update|delete|refund|cancel|adjust|purge|deploy|move|share|ship|assign|tag|reply|upload|invite|upsert|post|trigger|deactivate|fulfill|activate|capture)\b/.test(id);
diff --git a/app/lib/mcp/framework.ts b/app/lib/mcp/framework.ts
index c6d2885..fdc50c5 100644
--- a/app/lib/mcp/framework.ts
+++ b/app/lib/mcp/framework.ts
@@ -1,4 +1,4 @@
-// Commerce Claw — Connector Framework (Zapier-for-business)
+// VenturaClaw — Connector Framework (Zapier-for-business)
 // Every connector is a Zap-style bundle: Auth + Triggers + Actions + (optional) MCP server
 
 export type AuthMethod = "oauth2" | "api_key" | "hmac" | "basic" | "smtp" | "none";
diff --git a/docs/research/connectors.md b/docs/research/connectors.md
index 7beb105..1a83060 100644
--- a/docs/research/connectors.md
+++ b/docs/research/connectors.md
@@ -1,4 +1,4 @@
-# Commerce Claw — Connector Research Report
+# VenturaClaw — Connector Research Report
 
 **Generated:** 2026-05-05 by `exa-agent`
 **Connectors verified:** 56 / 56
diff --git a/relay/server.js b/relay/server.js
index 0d14902..74768a1 100644
--- a/relay/server.js
+++ b/relay/server.js
@@ -1,7 +1,7 @@
 #!/usr/bin/env node
-// Commerce Claw — local Mac relay (loopback only, never exposed to LAN/Internet).
+// VenturaClaw — local Mac relay (loopback only, never exposed to LAN/Internet).
 // Lets Steve paste KEY=value lines ONCE; writes to ~/Projects/secrets-manager/.env
-// and triggers immediate BusinessClaw sync via launchctl.
+// and triggers immediate VenturaClaw sync via launchctl.
 
 const http = require("http");
 const fs = require("fs");
@@ -70,7 +70,7 @@ function writeEnvMerge(p, kv) {
   return { added, updated };
 }
 
-function triggerBusinessClawSync() {
+function triggerVenturaClawSync() {
   return new Promise((resolve) => {
     const p = spawn("launchctl", ["start", "com.steve.businessclaw-sync"]);
     p.on("close", (code) => resolve({ code }));
@@ -81,7 +81,7 @@ function triggerBusinessClawSync() {
 const HTML = `<!doctype html>
 <html lang="en"><head>
 <meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
-<title>Commerce Claw — Local Token Relay</title>
+<title>VenturaClaw — Local Token Relay</title>
 <style>
   :root {
     --ink: #f4f1ea;
@@ -126,7 +126,7 @@ const HTML = `<!doctype html>
     <p style="font-size:13px;opacity:0.78;line-height:1.6;margin:8px 0 0">
       One paste writes <code>KEY=value</code> lines to <code>~/Projects/secrets-manager/.env</code>
       AND immediately triggers <code>com.steve.businessclaw-sync</code> so the
-      <a href="https://businessclaw.agentabrams.com/admin/connectors" style="color:var(--gold)">BusinessClaw connectors page</a>
+      <a href="https://businessclaw.agentabrams.com/admin/connectors" style="color:var(--gold)">VenturaClaw connectors page</a>
       flips tiles green within seconds. From this moment on, the launchd job keeps everything in sync — no further pasting ever.
     </p>
   </div>
@@ -193,7 +193,7 @@ const server = http.createServer(async (req, res) => {
   if (req.method === "GET" && req.url === "/healthz") return send(res, 200, { ok: true });
 
   // Expose MCP server config from ~/.claude.json — names + env-key names only, NEVER values.
-  // Used by BusinessClaw /api/anthropic/discover-mcps when running on the same machine.
+  // Used by VenturaClaw /api/anthropic/discover-mcps when running on the same machine.
   if (req.method === "GET" && req.url === "/api/mcp-config") {
     try {
       const j = JSON.parse(fs.readFileSync(path.join(os.homedir(), ".claude.json"), "utf8"));
@@ -246,7 +246,7 @@ const server = http.createServer(async (req, res) => {
         const kv = parseEnvBlob(paste);
         if (!Object.keys(kv).length) return send(res, 400, { error: "no recognized KEY=value lines" });
         const { added, updated } = writeEnvMerge(SECRETS_ENV, kv);
-        const sync = await triggerBusinessClawSync();
+        const sync = await triggerVenturaClawSync();
         send(res, 200, { added, updated, keys: Object.keys(kv), synced: !sync.error, syncError: sync.error || null });
       } catch (e) {
         send(res, 500, { error: e.message });
diff --git a/scripts/auto-build.sh b/scripts/auto-build.sh
index 58fe388..2b1d83c 100755
--- a/scripts/auto-build.sh
+++ b/scripts/auto-build.sh
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-# Commerce Claw — Auto-Build Orchestrator
+# VenturaClaw — Auto-Build Orchestrator
 # Runs all phases sequentially, no interaction, streams events to logs/build-events.jsonl
 set -euo pipefail
 ROOT="$(cd "$(dirname "$0")/.." && pwd)"
@@ -255,7 +255,7 @@ for r in dashboard connectors social-publisher payments orders ai workflows appr
   cat > "$ROOT/app/app/$r/page.tsx" <<TSX
 import { GlassCard } from "@/components/glass";
 export default function Page() {
-  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">$r</h1><p className="opacity-70 mt-2">Commerce Claw — $r screen scaffold.</p></GlassCard></main>;
+  return <main className="p-8"><GlassCard className="p-8"><h1 className="text-2xl">$r</h1><p className="opacity-70 mt-2">VenturaClaw — $r screen scaffold.</p></GlassCard></main>;
 }
 TSX
 done
diff --git a/scripts/build-connectors.sh b/scripts/build-connectors.sh
index b75d2d2..575b98d 100644
--- a/scripts/build-connectors.sh
+++ b/scripts/build-connectors.sh
@@ -103,7 +103,7 @@ while IFS='|' read -r slug name category docs auth env triggers actions; do
   env_json="${env_json%,}"
 
   cat > "$OUT/${slug}.ts" <<TS
-// AUTO-GENERATED by build-connectors.sh — Commerce Claw
+// AUTO-GENERATED by build-connectors.sh — VenturaClaw
 // Connector: ${name} (${slug})
 import { register, type Connector } from "../framework";
 
@@ -139,7 +139,7 @@ done <<< "$MANIFEST"
 
 # index file
 {
-  echo "// AUTO-GENERATED — Commerce Claw connector index"
+  echo "// AUTO-GENERATED — VenturaClaw connector index"
   for f in "$OUT"/*.ts; do
     [ "$(basename "$f")" = "index.ts" ] && continue
     base="$(basename "$f" .ts)"
diff --git a/scripts/populate-credentials.js b/scripts/populate-credentials.js
index 7c8dde1..023721e 100644
--- a/scripts/populate-credentials.js
+++ b/scripts/populate-credentials.js
@@ -90,7 +90,7 @@ function main() {
     }
   }
 
-  console.log(`\n=== Commerce Claw credential populator ===`);
+  console.log(`\n=== VenturaClaw credential populator ===`);
   console.log(`  ${matched.length} connector(s) ready to populate from your secrets-manager`);
   console.log(`  ${partial.length} connector(s) partially mapped (missing some env vars)`);
   console.log(`  ${waiting.length} connector(s) waiting on token onboarding\n`);
diff --git a/scripts/sync-tokens.js b/scripts/sync-tokens.js
index 520268d..68da27a 100755
--- a/scripts/sync-tokens.js
+++ b/scripts/sync-tokens.js
@@ -1,17 +1,17 @@
 #!/usr/bin/env node
-// Commerce Claw — token sync agent.
-// Runs locally on Steve's Mac (launchd com.steve.businessclaw-sync).
-// Reads ~/.claude.json MCP env + ~/Projects/secrets-manager/.env, POSTs to https://businessclaw.agentabrams.com
-// Token values NEVER leave Steve's machine except to land in his own BusinessClaw account.
+// VenturaClaw — token sync agent.
+// Runs locally on Steve's Mac (launchd com.steve.venturaclaw-sync).
+// Reads ~/.claude.json MCP env + ~/Projects/secrets-manager/.env, POSTs to https://venturaclaw.agentabrams.com
+// Token values NEVER leave Steve's machine except to land in his own VenturaClaw account.
 
 const fs = require("fs");
 const path = require("path");
 const os = require("os");
 
-const PROD  = process.env.BC_URL  || "https://businessclaw.agentabrams.com";
+const PROD  = process.env.BC_URL  || "https://venturaclaw.agentabrams.com";
 const EMAIL = process.env.BC_USER || "steve@businessclaw.com";
 const PASS  = process.env.BC_PASS || "149940c2c5b209fb";
-const LOG   = path.join(os.homedir(), "Projects", "business-claw", "logs", "sync.log");
+const LOG   = path.join(os.homedir(), "Projects", "ventura-claw", "logs", "sync.log");
 fs.mkdirSync(path.dirname(LOG), { recursive: true });
 const log = (m) => { const line = `[${new Date().toISOString()}] ${m}\n`; fs.appendFileSync(LOG, line); process.stdout.write(line); };
 
diff --git a/server/connectors.json b/server/connectors.json
index 8abe209..a59c9dc 100644
--- a/server/connectors.json
+++ b/server/connectors.json
@@ -658,5 +658,17 @@
     "logo": "airtable",
     "tint": "#FCB400",
     "sensitive": false
+  },
+  {
+    "id": "archive",
+    "name": "Archive (Wayback)",
+    "category": "data",
+    "docs": "https://archive.org/help/wayback_api.php",
+    "auth": "none",
+    "triggers": 0,
+    "actions": 4,
+    "logo": "internetarchive",
+    "tint": "#000000",
+    "sensitive": false
   }
 ]
\ No newline at end of file
diff --git a/server/connectors/archive.js b/server/connectors/archive.js
new file mode 100644
index 0000000..f713f23
--- /dev/null
+++ b/server/connectors/archive.js
@@ -0,0 +1,129 @@
+// Internet Archive / Wayback connector — REAL.
+// No API key required for read operations.
+// Strict license filter: only items with public-domain / CC0 / CC-BY / CC-BY-SA licenses are returned.
+// Docs: https://archive.org/help/wayback_api.php · https://archive.org/advancedsearch.php
+
+// License URL → category. Anything not in this map is rejected from results.
+const ALLOWED_LICENSES = {
+  "creativecommons.org/publicdomain/zero/1.0":   "CC0",
+  "creativecommons.org/publicdomain/mark/1.0":   "Public Domain",
+  "creativecommons.org/licenses/by/4.0":         "CC-BY 4.0",
+  "creativecommons.org/licenses/by/3.0":         "CC-BY 3.0",
+  "creativecommons.org/licenses/by/2.0":         "CC-BY 2.0",
+  "creativecommons.org/licenses/by-sa/4.0":      "CC-BY-SA 4.0",
+  "creativecommons.org/licenses/by-sa/3.0":      "CC-BY-SA 3.0",
+  // CC-NC/CC-ND deliberately excluded — non-commercial restricts SMB use, ND blocks edits.
+};
+function classifyLicense(url) {
+  if (!url) return null;
+  const u = String(url).toLowerCase().replace(/^https?:\/\//, "").replace(/\/$/, "");
+  for (const k of Object.keys(ALLOWED_LICENSES)) if (u.includes(k)) return ALLOWED_LICENSES[k];
+  // Public-domain explicit text
+  if (/\bpublic\s*domain\b/i.test(url)) return "Public Domain";
+  return null;
+}
+
+async function callJson(url, c) {
+  const r = await fetch(url, {
+    headers: { "User-Agent": "Commerce-Claw/1.0 (steve@businessclaw.com)", "Accept": "application/json" },
+    signal: AbortSignal.timeout(15_000)
+  });
+  if (!r.ok) throw new Error(`archive ${r.status}: ${await r.text().then(t => t.slice(0,180)).catch(()=> "")}`);
+  return r.json();
+}
+
+const archive = {
+  meta: { id: "archive", name: "Archive (Wayback)", category: "data", docsUrl: "https://archive.org/help/wayback_api.php", auth: "none", realImpl: true },
+  fields: [], // No token needed
+  configured() { return true; }, // Always available
+  async health() {
+    try {
+      const r = await fetch("https://archive.org/wayback/available?url=example.com", { signal: AbortSignal.timeout(15000) });
+      return { ok: r.ok, status: r.ok ? "live" : `http ${r.status}`, license_policy: "public-domain + CC0 + CC-BY + CC-BY-SA only" };
+    } catch (e) { return { ok: false, reason: e.message }; }
+  },
+  actions: {
+    // Wayback Availability — closest snapshot of a URL on a date
+    async "wayback.available"({ url, timestamp }) {
+      if (!url) throw new Error("url required");
+      const qs = new URLSearchParams({ url });
+      if (timestamp) qs.set("timestamp", timestamp);
+      const d = await callJson(`https://archive.org/wayback/available?${qs}`);
+      const snap = d?.archived_snapshots?.closest;
+      return snap ? { available: true, ...snap } : { available: false };
+    },
+
+    // Search items — license-filtered to public-domain + CC-BY family only.
+    async "search"({ q, mediatype, rows, page }) {
+      if (!q) throw new Error("q (query) required");
+      // Force license filter at query level — much faster than client-side
+      const license = '(licenseurl:"https://creativecommons.org/publicdomain/zero/1.0/" OR licenseurl:"https://creativecommons.org/publicdomain/mark/1.0/" OR licenseurl:"https://creativecommons.org/licenses/by/4.0/" OR licenseurl:"https://creativecommons.org/licenses/by-sa/4.0/" OR licenseurl:"https://creativecommons.org/licenses/by/3.0/" OR licenseurl:"https://creativecommons.org/licenses/by-sa/3.0/" OR licenseurl:"https://creativecommons.org/licenses/by/2.0/")';
+      const fullQ = `(${q}) AND ${license}` + (mediatype ? ` AND mediatype:${mediatype}` : "");
+      const qs = new URLSearchParams({
+        q: fullQ,
+        fl: "identifier,title,creator,date,mediatype,licenseurl,description,downloads",
+        rows: String(Math.min(rows || 25, 200)),
+        page: String(page || 1),
+        output: "json"
+      });
+      const d = await callJson(`https://archive.org/advancedsearch.php?${qs}`);
+      const docs = (d.response?.docs || []).map(x => ({
+        identifier: x.identifier,
+        title: x.title,
+        creator: x.creator,
+        date: x.date,
+        mediatype: x.mediatype,
+        license: classifyLicense(x.licenseurl),
+        license_url: x.licenseurl,
+        description: typeof x.description === "string" ? x.description.slice(0, 240) : x.description,
+        downloads: x.downloads,
+        details_url: `https://archive.org/details/${x.identifier}`,
+      })).filter(d => d.license); // belt-and-suspenders
+      return { total: d.response?.numFound || 0, page: d.response?.start || 0, items: docs };
+    },
+
+    // Get full metadata + file list for one item (license enforced)
+    async "metadata"({ identifier }) {
+      if (!identifier) throw new Error("identifier required");
+      const d = await callJson(`https://archive.org/metadata/${encodeURIComponent(identifier)}`);
+      const license = classifyLicense(d.metadata?.licenseurl);
+      if (!license) {
+        return { ok: false, reason: "license not in allowed set", license_url: d.metadata?.licenseurl || null };
+      }
+      const files = (d.files || []).filter(f => f.format && /jpeg|png|gif|jpg|mp4|webm|ogg|mp3|pdf|epub|txt/i.test(f.format)).map(f => ({
+        name: f.name,
+        format: f.format,
+        size: f.size ? parseInt(f.size, 10) : null,
+        url: `https://archive.org/download/${d.metadata.identifier}/${encodeURIComponent(f.name)}`,
+      }));
+      return {
+        ok: true,
+        identifier: d.metadata.identifier,
+        title: d.metadata.title,
+        creator: d.metadata.creator,
+        date: d.metadata.date,
+        mediatype: d.metadata.mediatype,
+        license, license_url: d.metadata.licenseurl,
+        description: typeof d.metadata.description === "string" ? d.metadata.description : (d.metadata.description?.[0] || ""),
+        attribution_required: license.startsWith("CC-BY"),
+        attribution_text: license.startsWith("CC-BY") ? `Source: ${d.metadata.title} by ${d.metadata.creator || "Internet Archive"}, ${license}, archive.org/details/${d.metadata.identifier}` : null,
+        files,
+        details_url: `https://archive.org/details/${d.metadata.identifier}`,
+      };
+    },
+
+    // CDX list of every snapshot of a URL
+    async "wayback.cdx"({ url, from, to, limit }) {
+      if (!url) throw new Error("url required");
+      const qs = new URLSearchParams({ url, output: "json", limit: String(Math.min(limit || 50, 500)) });
+      if (from) qs.set("from", from);
+      if (to)   qs.set("to", to);
+      const d = await callJson(`https://web.archive.org/cdx/search/cdx?${qs}`);
+      if (!Array.isArray(d) || !d.length) return { snapshots: [] };
+      const [headers, ...rows] = d;
+      return { snapshots: rows.map(r => Object.fromEntries(headers.map((h, i) => [h, r[i]]))) };
+    },
+  }
+};
+
+module.exports = archive;
diff --git a/server/connectors/cloudflare.js b/server/connectors/cloudflare.js
index 7276b6e..35cbfb5 100644
--- a/server/connectors/cloudflare.js
+++ b/server/connectors/cloudflare.js
@@ -1,4 +1,4 @@
-// Commerce Claw — Cloudflare connector (REAL API)
+// VenturaClaw — Cloudflare connector (REAL API)
 // Reads CF_API_TOKEN from env (account-scoped or zone-scoped per Steve's MEMORY note about token leak).
 // Docs: https://developers.cloudflare.com/api/
 
diff --git a/server/connectors/index.js b/server/connectors/index.js
index 65efaf0..b30b133 100644
--- a/server/connectors/index.js
+++ b/server/connectors/index.js
@@ -12,14 +12,16 @@ const canva      = require("./canva");
 const etsy       = require("./etsy");
 const gmail      = require("./gmail");
 const purelymail = require("./purelymail");
+const archive    = require("./archive");
 
-const REAL = { slack, stripe, cloudflare, mailchimp, hubspot, notion, airtable, twilio, figma, canva, etsy, gmail, purelymail };
+const REAL = { slack, stripe, cloudflare, mailchimp, hubspot, notion, airtable, twilio, figma, canva, etsy, gmail, purelymail, archive };
 
 // Phase 8 — central sensitivity registry. Source of truth for "this action mutates state."
 // Anything in WRITE_ACTIONS[id] requires the approval gate. Anything NOT listed is treated as read-only.
 // Unknown connector or unknown action → fail-safe to "write" (require approval).
 const WRITE_ACTIONS = {
   airtable:   new Set(["record.create", "record.update"]),
+  archive:    new Set([]),  // Internet Archive read-only — no writes exposed
   canva:      new Set([]),
   cloudflare: new Set(["cache.purge_all", "cache.purge_files", "dns.create", "dns.update"]),
   etsy:       new Set([]),
@@ -37,6 +39,7 @@ const WRITE_ACTIONS = {
 // Read actions enumerated per connector — explicit allowlist for fail-safe behavior.
 const READ_ACTIONS = {
   airtable:   new Set(["bases.list", "tables.list", "records.list"]),
+  archive:    new Set(["wayback.available", "wayback.cdx", "search", "metadata"]),
   canva:      new Set(["me", "design.get", "designs.list", "folders.list"]),
   cloudflare: new Set(["dns.list", "zone.list"]),
   etsy:       new Set(["me", "shops.findByUser", "listings.active", "receipts.list"]),
diff --git a/server/connectors/slack.js b/server/connectors/slack.js
index 1011d8b..5fc8f06 100644
--- a/server/connectors/slack.js
+++ b/server/connectors/slack.js
@@ -1,4 +1,4 @@
-// Commerce Claw — Slack connector (REAL API)
+// VenturaClaw — Slack connector (REAL API)
 // Reads SLACK_BOT_TOKEN from env. Inject via /secrets skill; pm2 restart --update-env.
 // Docs: https://docs.slack.dev/apis/web-api/
 
diff --git a/server/connectors/stripe.js b/server/connectors/stripe.js
index f47fb93..ab8c42e 100644
--- a/server/connectors/stripe.js
+++ b/server/connectors/stripe.js
@@ -1,4 +1,4 @@
-// Commerce Claw — Stripe connector (REAL API)
+// VenturaClaw — Stripe connector (REAL API)
 // Reads STRIPE_SECRET_KEY from env. Use /secrets skill to inject; pm2 restart --update-env.
 // Docs: https://docs.stripe.com/api
 
diff --git a/server/data/connector-acquisition.json b/server/data/connector-acquisition.json
index eb6ca8f..0cd4997 100644
--- a/server/data/connector-acquisition.json
+++ b/server/data/connector-acquisition.json
@@ -146,6 +146,14 @@
       "get_key_steps": "New Application → Bot → Reset Token → copy. OAuth2 → URL Generator → bot scope → install to your server.",
       "fields": [{ "key": "DISCORD_BOT_TOKEN", "label": "Bot Token", "type": "password", "required": true }]
     },
+    "archive": {
+      "name": "Archive (Wayback)",
+      "auth": "none",
+      "oauth": false,
+      "get_key_url": "https://archive.org/help/wayback_api.php",
+      "get_key_steps": "No key required. Free public Internet Archive APIs. Results filtered to public-domain + CC0 + CC-BY + CC-BY-SA only (no NC/ND).",
+      "fields": []
+    },
     "anthropic": {
       "name": "Anthropic / Claude",
       "auth": "api_key",
diff --git a/server/lib/comms-compliance.js b/server/lib/comms-compliance.js
index ed942d0..8df2285 100644
--- a/server/lib/comms-compliance.js
+++ b/server/lib/comms-compliance.js
@@ -1,4 +1,4 @@
-// Commerce Claw — comms-compliance gate (CAN-SPAM / §17529.5 / TCPA / DNC scrub)
+// VenturaClaw — comms-compliance gate (CAN-SPAM / §17529.5 / TCPA / DNC scrub)
 // Runs before any sensitive comms action executes.
 // Per Steve's MEMORY.md project_comms_compliance_agent.md: fail-closed if list missing or stale.
 
diff --git a/server/lib/oauth-refresh.js b/server/lib/oauth-refresh.js
index 000e475..8584a99 100644
--- a/server/lib/oauth-refresh.js
+++ b/server/lib/oauth-refresh.js
@@ -1,4 +1,4 @@
-// Commerce Claw — OAuth refresh-token rotation.
+// VenturaClaw — OAuth refresh-token rotation.
 // Called before every connector action to auto-refresh expired access tokens.
 // Returns possibly-updated creds (caller saves if changed).
 
diff --git a/server/llm.js b/server/llm.js
index 24a84c2..c005ab2 100644
--- a/server/llm.js
+++ b/server/llm.js
@@ -1,4 +1,4 @@
-// Commerce Claw — local-only LLM router
+// VenturaClaw — local-only LLM router
 // Hard rule (next 8h, set by Steve 2026-05-05): NO Claude / Anthropic / OpenAI calls from this project.
 // Targets Mac Studio 1 Ollama by default per memory.feedback_ollama_default_ms1.
 
diff --git a/server/public/admin-approvals.html b/server/public/admin-approvals.html
index 1982a2d..550741f 100644
--- a/server/public/admin-approvals.html
+++ b/server/public/admin-approvals.html
@@ -1,7 +1,7 @@
 <!doctype html>
 <html lang="en"><head>
 <meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
-<title>Approvals — Commerce Claw</title>
+<title>Approvals — VenturaClaw</title>
 <link rel="stylesheet" href="/static/style.css" />
 <style>
   .filter-bar { padding: 14px 18px; display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin-bottom: 16px; }
@@ -27,7 +27,7 @@
 </style>
 </head><body>
 <header class="topbar">
-  <div class="brand"><div class="logo-dot"></div><div><div class="brand-name">Commerce <em style="font-style:italic;color:var(--gold)">Claw</em></div><div class="brand-sub">Approval Queue</div></div></div>
+  <div class="brand"><div class="logo-dot"></div><div><div class="brand-name">Ventura<em style="font-style:italic;color:var(--gold)">Claw</em></div><div class="brand-sub">Approval Queue</div></div></div>
   <nav class="nav" style="display:flex;gap:6px;font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase">
     <a href="/admin"            style="padding:8px 14px;color:var(--ink-soft)">Dashboard</a>
     <a href="/admin/users"      style="padding:8px 14px;color:var(--ink-soft)">Users</a>
@@ -59,7 +59,7 @@
   <div id="rows"></div>
 </main>
 
-<div class="footer">Commerce Claw · businessclaw.agentabrams.com</div>
+<div class="footer">VenturaClaw</div>
 
 <script>
 const esc = s => String(s == null ? "" : s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
diff --git a/server/public/admin-audit.html b/server/public/admin-audit.html
index cbc8c43..253e691 100644
--- a/server/public/admin-audit.html
+++ b/server/public/admin-audit.html
@@ -1,7 +1,7 @@
 <!doctype html>
 <html lang="en"><head>
 <meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
-<title>Audit — Commerce Claw</title>
+<title>Audit — VenturaClaw</title>
 <link rel="stylesheet" href="/static/style.css" />
 <style>
   .filter-bar { padding: 14px 18px; display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 14px; }
@@ -22,7 +22,7 @@
 </style>
 </head><body>
 <header class="topbar">
-  <div class="brand"><div class="logo-dot"></div><div><div class="brand-name">Commerce <em style="font-style:italic;color:var(--gold)">Claw</em></div><div class="brand-sub">Audit Log</div></div></div>
+  <div class="brand"><div class="logo-dot"></div><div><div class="brand-name">Ventura<em style="font-style:italic;color:var(--gold)">Claw</em></div><div class="brand-sub">Audit Log</div></div></div>
   <nav class="nav" style="display:flex;gap:6px;font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase">
     <a href="/admin"            style="padding:8px 14px;color:var(--ink-soft)">Dashboard</a>
     <a href="/admin/users"      style="padding:8px 14px;color:var(--ink-soft)">Users</a>
@@ -57,7 +57,7 @@
   <div style="text-align:center;padding:14px;font-family:var(--mono);font-size:10px;color:var(--ink-mute)" id="footer-stats"></div>
 </main>
 
-<div class="footer">Commerce Claw · businessclaw.agentabrams.com</div>
+<div class="footer">VenturaClaw</div>
 
 <script>
 const esc = s => String(s == null ? "" : s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
diff --git a/server/public/admin-connectors.html b/server/public/admin-connectors.html
index 48b259e..5a23f28 100644
--- a/server/public/admin-connectors.html
+++ b/server/public/admin-connectors.html
@@ -1,7 +1,7 @@
 <!doctype html>
 <html lang="en"><head>
 <meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
-<title>Connectors — Commerce Claw</title>
+<title>Connectors — VenturaClaw</title>
 <link rel="stylesheet" href="/static/style.css" />
 <style>
   .tile { border: 1px solid var(--rule); transition: border-color 200ms ease, box-shadow 200ms ease; }
@@ -24,7 +24,7 @@
 </style>
 </head><body>
 <header class="topbar">
-  <div class="brand"><div class="logo-dot"></div><div><div class="brand-name">Commerce <em style="font-style:italic;color:var(--gold)">Claw</em></div><div class="brand-sub">Connectors</div></div></div>
+  <div class="brand"><div class="logo-dot"></div><div><div class="brand-name">Ventura<em style="font-style:italic;color:var(--gold)">Claw</em></div><div class="brand-sub">Connectors</div></div></div>
   <nav class="nav" style="display:flex;gap:6px;font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase">
     <a href="/admin" style="padding:8px 14px;color:var(--ink-soft)">Dashboard</a>
     <a href="/admin/users" style="padding:8px 14px;color:var(--ink-soft)">Users</a>
@@ -67,7 +67,7 @@
   </div>
   <div class="glass" style="padding:18px"><div class="tile-grid" id="grid" role="region" aria-label="Connector grid" aria-live="polite"></div></div>
 </main>
-<div class="footer">Commerce Claw</div>
+<div class="footer">VenturaClaw</div>
 <script>
 let CONNECTORS = [];
 const HEALTH = {}; // { connector_id: { ok, reason, ... } }
diff --git a/server/public/admin-users.html b/server/public/admin-users.html
index d12b172..fbbfd8a 100644
--- a/server/public/admin-users.html
+++ b/server/public/admin-users.html
@@ -1,12 +1,12 @@
 <!doctype html>
 <html lang="en"><head>
 <meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
-<title>Users — Commerce Claw</title>
+<title>Users — VenturaClaw</title>
 <link rel="stylesheet" href="/static/style.css" />
 </head><body>
 <div class="bg-orb orb-1"></div><div class="bg-orb orb-2"></div><div class="bg-orb orb-3"></div>
 <header class="topbar glass">
-  <div class="brand"><div class="logo-dot"></div><div><div class="brand-name">Commerce Claw</div><div class="brand-sub">USERS</div></div></div>
+  <div class="brand"><div class="logo-dot"></div><div><div class="brand-name">VenturaClaw</div><div class="brand-sub">USERS</div></div></div>
   <nav class="nav">
     <a href="/admin">Dashboard</a><a class="active" href="/admin/users">Users</a><a href="/admin/connectors">Connectors</a>
     <a href="/admin/approvals">Approvals</a><a href="/admin/audit">Audit</a><a href="/chat">Chat</a>
@@ -33,7 +33,7 @@
     </form>
   </div>
 </main>
-<div class="footer">Commerce Claw · businessclaw.agentabrams.com</div>
+<div class="footer">VenturaClaw</div>
 <script>
 async function refresh() {
   const d = await (await fetch('/api/admin/users')).json();
diff --git a/server/public/admin.html b/server/public/admin.html
index 820884a..f091c02 100644
--- a/server/public/admin.html
+++ b/server/public/admin.html
@@ -1,7 +1,7 @@
 <!doctype html>
 <html lang="en"><head>
 <meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
-<title>Admin — Commerce Claw</title>
+<title>Admin — VenturaClaw</title>
 <link rel="stylesheet" href="/static/style.css" />
 <style>
   .stat-card { padding: 18px; transition: border-color 200ms; }
@@ -17,7 +17,7 @@
 </style>
 </head><body>
 <header class="topbar">
-  <div class="brand"><div class="logo-dot"></div><div><div class="brand-name">Commerce <em style="font-style:italic;color:var(--gold)">Claw</em></div><div class="brand-sub">Admin</div></div></div>
+  <div class="brand"><div class="logo-dot"></div><div><div class="brand-name">Ventura<em style="font-style:italic;color:var(--gold)">Claw</em></div><div class="brand-sub">Admin</div></div></div>
   <nav class="nav" style="display:flex;gap:6px;font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase">
     <a href="/admin"             style="padding:8px 14px;color:var(--gold);border-bottom:1px solid var(--gold)">Dashboard</a>
     <a href="/admin/users"       style="padding:8px 14px;color:var(--ink-soft)">Users</a>
@@ -64,7 +64,7 @@
 
 </main>
 
-<div class="footer">Commerce Claw · businessclaw.agentabrams.com · info@agentabrams.com</div>
+<div class="footer">VenturaClaw</div>
 
 <script>
 const esc = s => String(s == null ? "" : s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
diff --git a/server/public/brand.html b/server/public/brand.html
index e7ee02c..11106d1 100644
--- a/server/public/brand.html
+++ b/server/public/brand.html
@@ -1,7 +1,7 @@
 <!doctype html>
 <html lang="en"><head>
 <meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
-<title>Brand Kit — Commerce Claw</title>
+<title>Brand Kit — VenturaClaw</title>
 <link rel="stylesheet" href="/static/style.css" />
 <style>
 /* ─── Brand Kit page ─────────────────────────────────────────────────── */
@@ -129,8 +129,8 @@
   <div class="brand">
     <div class="logo-dot"></div>
     <div>
-      <div class="brand-name">Commerce <em style="font-style:italic;color:var(--gold)">Claw</em></div>
-      <div class="brand-sub">Connected Commerce</div>
+      <div class="brand-name">Ventura<em style="font-style:italic;color:var(--gold)">Claw</em></div>
+      <div class="brand-sub">Connected Operations</div>
     </div>
   </div>
   <div style="display:flex;gap:10px;align-items:center">
@@ -210,7 +210,7 @@
 
 </main>
 
-<footer class="footer">Commerce Claw · Brand Kit</footer>
+<footer class="footer">VenturaClaw · Brand Kit</footer>
 
 <script>
 const TEAM = [
diff --git a/server/public/chat.html b/server/public/chat.html
index 74be2b1..ffcac17 100644
--- a/server/public/chat.html
+++ b/server/public/chat.html
@@ -1,7 +1,7 @@
 <!doctype html>
 <html lang="en"><head>
 <meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
-<title>Chat — Commerce Claw</title>
+<title>Chat — VenturaClaw</title>
 <link rel="stylesheet" href="/static/style.css" />
 </head><body>
 
@@ -9,8 +9,8 @@
   <div class="brand">
     <div class="logo-dot"></div>
     <div>
-      <div class="brand-name">Commerce <em style="font-style:italic;color:var(--gold)">Claw</em></div>
-      <div class="brand-sub">Connected Commerce</div>
+      <div class="brand-name">Ventura<em style="font-style:italic;color:var(--gold)">Claw</em></div>
+      <div class="brand-sub">Connected Operations</div>
     </div>
   </div>
   <div style="display:flex;gap:10px;align-items:center">
@@ -38,7 +38,7 @@
   <section class="glass chat-panel" style="display:flex;flex-direction:column;padding:32px;height:calc(100vh - 130px)">
     <div class="chat-head" style="display:flex;justify-content:space-between;align-items:flex-start;padding-bottom:18px;border-bottom:1px solid var(--rule);margin-bottom:18px">
       <div>
-        <h1>Ask Commerce <em>Claw</em></h1>
+        <h1>Ask Ventura<em>Claw</em></h1>
         <div class="sub">Sensitive actions auto-route to the approval queue</div>
       </div>
       <a href="/admin/approvals" id="adm-link" class="btn btn-ghost" style="display:none">Approvals →</a>
@@ -50,8 +50,8 @@
     <div id="msgs" style="flex:1;overflow-y:auto;display:flex;flex-direction:column;gap:14px;padding-right:6px">
 
       <!-- COMPONENT 1: Typing indicator — appended here during sendMsg, removed on reply -->
-      <div id="typing-indicator" class="bubble assistant typing-indicator" style="display:none" aria-live="polite" aria-label="Commerce Claw is thinking">
-        <span class="typing-label">Commerce Claw is thinking</span>
+      <div id="typing-indicator" class="bubble assistant typing-indicator" style="display:none" aria-live="polite" aria-label="VenturaClaw is thinking">
+        <span class="typing-label">VenturaClaw is thinking</span>
         <span class="typing-dots" aria-hidden="true">
           <span class="typing-dot"></span>
           <span class="typing-dot"></span>
@@ -67,6 +67,11 @@
       <div id="ctx-chips" class="ctx-chips-row"></div>
     </div>
 
+    <!-- Frequent commands — auto-populated from this user's chat history (top 5 by count). Hidden until populated. -->
+    <div id="frequent-commands" class="prompt-chips" style="display:none;margin-top:8px">
+      <span style="font-family:var(--mono);font-size:9px;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-mute);margin-right:6px;align-self:center">Your frequent</span>
+    </div>
+
     <div id="prompt-suggestions" class="prompt-chips" style="display:none">
       <button class="prompt-chip" data-prompt="Post our newest product to all 10 social channels">Post newest to all socials</button>
       <button class="prompt-chip" data-prompt="Draft a Mailchimp campaign for our new arrivals">Draft Mailchimp for new arrivals</button>
@@ -109,9 +114,42 @@ let CONNECTORS = [];
   cc.textContent = CONNECTORS.length;
   document.getElementById('conn-count').textContent = CONNECTORS.length;
   drawConnectors();
-  pushMsg('assistant', `Hello ${me.user.name.split(' ')[0]}. I'm wired into all ${CONNECTORS.length} of your connectors. Pick a starting point below — or just tell me what you'd like to do.`);
-  document.getElementById('empty-tagline').style.display = 'block';
-  sugg.style.display = 'flex';
+  // Frequent commands strip — auto-loaded from history. Click to re-fire.
+  fetch('/api/chat/frequent').then(r => r.json()).then(f => {
+    if (!f.top || !f.top.length) return;
+    const host = document.getElementById('frequent-commands');
+    for (const item of f.top) {
+      const b = document.createElement('button');
+      b.className = 'prompt-chip';
+      b.dataset.prompt = item.text;
+      b.title = `used ${item.count}×`;
+      b.textContent = item.text.length > 50 ? item.text.slice(0, 47) + '…' : item.text;
+      b.addEventListener('click', () => sendMsg(item.text));
+      host.appendChild(b);
+    }
+    host.style.display = 'flex';
+  }).catch(() => {});
+
+  // Restore prior conversation if any
+  try {
+    const h = await (await fetch('/api/chat/history?limit=80')).json();
+    if (h.messages && h.messages.length) {
+      for (const m of h.messages) {
+        pushMsg(m.role, m.text);
+        if (m.role === 'assistant' && m.toolCalls) {
+          for (const c of m.toolCalls) pushMsg('tool', `→ ${c.name||c.connector}.${c.action} ${c.queued?'(queued for approval)':'(executed)'}`);
+        }
+      }
+    } else {
+      pushMsg('assistant', `Hello ${me.user.name.split(' ')[0]}. I'm wired into all ${CONNECTORS.length} of your connectors. Pick a starting point below — or just tell me what you'd like to do.`);
+      document.getElementById('empty-tagline').style.display = 'block';
+      sugg.style.display = 'flex';
+    }
+  } catch {
+    pushMsg('assistant', `Hello ${me.user.name.split(' ')[0]}. ${CONNECTORS.length} connectors ready.`);
+    document.getElementById('empty-tagline').style.display = 'block';
+    sugg.style.display = 'flex';
+  }
 })();
 
 /* ─── Connector sidebar ─────────────────────────────────────────────────── */
diff --git a/server/public/connections-import.html b/server/public/connections-import.html
index 6621edd..f03b470 100644
--- a/server/public/connections-import.html
+++ b/server/public/connections-import.html
@@ -1,7 +1,7 @@
 <!doctype html>
 <html lang="en"><head>
 <meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
-<title>Import Connections — Commerce Claw</title>
+<title>Import Connections — VenturaClaw</title>
 <link rel="stylesheet" href="/static/style.css" />
 <style>
 .import-page { max-width: 880px; margin: 0 auto; padding: 28px; }
@@ -34,8 +34,8 @@ textarea { width: 100%; min-height: 280px; font-family: var(--mono); font-size:
   <div class="brand">
     <div class="logo-dot"></div>
     <div>
-      <div class="brand-name">Commerce <em style="font-style:italic;color:var(--gold)">Claw</em></div>
-      <div class="brand-sub">Connected Commerce</div>
+      <div class="brand-name">Ventura<em style="font-style:italic;color:var(--gold)">Claw</em></div>
+      <div class="brand-sub">Connected Operations</div>
     </div>
   </div>
   <div style="display:flex;gap:10px;align-items:center">
diff --git a/server/public/connections.html b/server/public/connections.html
index 431b05a..2601795 100644
--- a/server/public/connections.html
+++ b/server/public/connections.html
@@ -1,7 +1,7 @@
 <!doctype html>
 <html lang="en"><head>
 <meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
-<title>My Connections — Commerce Claw</title>
+<title>My Connections — VenturaClaw</title>
 <link rel="stylesheet" href="/static/style.css" />
 <style>
   /* OAuth tile grid */
@@ -93,6 +93,124 @@
   }
   .oauth-tile.flash-new { animation: flash-connected 1.6s ease-out forwards; }
 
+  /* per-tile select checkbox */
+  .oauth-tile { position: relative; }
+  .oauth-tile-check {
+    position: absolute;
+    top: 10px;
+    right: 10px;
+    width: 16px;
+    height: 16px;
+    cursor: pointer;
+    accent-color: var(--gold);
+  }
+  .oauth-tile.is-selected {
+    border-color: var(--gold);
+    box-shadow: 0 0 0 1px var(--gold) inset;
+  }
+
+  /* bulk control bar */
+  .bulk-bar {
+    display: flex;
+    align-items: center;
+    gap: 14px;
+    padding: 10px 12px;
+    margin-bottom: 14px;
+    border: 1px solid var(--rule);
+    border-radius: 3px;
+    background: rgba(244,241,234,0.03);
+    flex-wrap: wrap;
+  }
+  .bulk-bar label {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    cursor: pointer;
+    font-family: var(--mono);
+    font-size: 11px;
+    letter-spacing: 0.10em;
+    text-transform: uppercase;
+    color: var(--ink);
+  }
+  .bulk-bar input[type=checkbox] { accent-color: var(--gold); width: 14px; height: 14px; cursor: pointer; }
+  .bulk-bar .bulk-count {
+    font-family: var(--mono);
+    font-size: 10px;
+    letter-spacing: 0.10em;
+    color: var(--ink-mute);
+  }
+  .bulk-bar .bulk-spacer { flex: 1; }
+  .btn-bulk-go {
+    font-family: var(--mono);
+    font-size: 11px;
+    letter-spacing: 0.12em;
+    text-transform: uppercase;
+    background: var(--gold);
+    color: var(--bg);
+    border: 1px solid var(--gold);
+    border-radius: 2px;
+    padding: 7px 16px;
+    cursor: pointer;
+    font-weight: 600;
+  }
+  .btn-bulk-go:disabled {
+    background: transparent;
+    color: var(--ink-mute);
+    border-color: var(--rule-strong);
+    cursor: not-allowed;
+    font-weight: normal;
+  }
+
+  /* queue continue bar */
+  .queue-bar {
+    display: flex;
+    align-items: center;
+    gap: 14px;
+    padding: 12px 14px;
+    margin-bottom: 14px;
+    border: 1px solid var(--gold);
+    border-radius: 3px;
+    background: rgba(212,160,74,0.08);
+    flex-wrap: wrap;
+  }
+  .queue-bar .queue-msg {
+    font-family: var(--serif);
+    font-size: 14px;
+    color: var(--ink);
+  }
+  .queue-bar .queue-progress {
+    font-family: var(--mono);
+    font-size: 10px;
+    letter-spacing: 0.10em;
+    color: var(--ink-mute);
+  }
+  .queue-bar .queue-spacer { flex: 1; }
+  .queue-bar .btn-queue-next {
+    font-family: var(--mono);
+    font-size: 11px;
+    letter-spacing: 0.12em;
+    text-transform: uppercase;
+    background: var(--gold);
+    color: var(--bg);
+    border: 1px solid var(--gold);
+    border-radius: 2px;
+    padding: 7px 16px;
+    cursor: pointer;
+    font-weight: 600;
+  }
+  .queue-bar .btn-queue-cancel {
+    font-family: var(--mono);
+    font-size: 10px;
+    letter-spacing: 0.12em;
+    text-transform: uppercase;
+    background: transparent;
+    color: var(--ink-mute);
+    border: 1px solid var(--rule-strong);
+    border-radius: 2px;
+    padding: 6px 12px;
+    cursor: pointer;
+  }
+
   /* section heading */
   .section-heading {
     display: flex;
@@ -122,7 +240,7 @@
 
 <header class="topbar glass">
   <div class="brand"><div class="logo-dot"></div>
-    <div><div class="brand-name">Commerce Claw</div><div class="brand-sub">MY CONNECTIONS</div></div></div>
+    <div><div class="brand-name">VenturaClaw</div><div class="brand-sub">MY CONNECTIONS</div></div></div>
   <nav class="nav">
     <a href="/chat">Chat</a>
     <a class="active" href="/connections">My Connections</a>
@@ -141,9 +259,29 @@
       <span>OAuth 2.0</span>
     </div>
     <p style="font-size:13px;opacity:0.72;margin:0 0 16px;line-height:1.55">
-      Grant Commerce Claw access to your accounts without pasting API keys.
-      Click <strong style="color:var(--ink)">Connect</strong> — you'll approve access on the provider's site and land back here automatically.
+      Grant VenturaClaw access to your accounts without pasting API keys.
+      Tick the providers you want, hit <strong style="color:var(--ink)">Connect selected</strong>, and we'll walk you through each one in order — or click Connect on any single tile.
     </p>
+
+    <!-- bulk select bar -->
+    <div class="bulk-bar" id="bulk-bar" style="display:none">
+      <label><input type="checkbox" id="bulk-select-all" /> Select all available</label>
+      <span class="bulk-count" id="bulk-count">0 selected</span>
+      <span class="bulk-spacer"></span>
+      <button class="btn-bulk-go" id="bulk-go" disabled>Connect selected →</button>
+    </div>
+
+    <!-- queue progress bar (shown during bulk connect) -->
+    <div class="queue-bar" id="queue-bar" style="display:none">
+      <div>
+        <div class="queue-msg" id="queue-msg">Ready to connect.</div>
+        <div class="queue-progress" id="queue-progress"></div>
+      </div>
+      <span class="queue-spacer"></span>
+      <button class="btn-queue-cancel" id="queue-cancel">Cancel queue</button>
+      <button class="btn-queue-next" id="queue-next">Continue →</button>
+    </div>
+
     <div id="oauth-grid">
       <!-- tiles injected by JS -->
       <div style="font-family:var(--mono);font-size:11px;color:var(--ink-mute);padding:8px 0" id="oauth-loading">Loading providers…</div>
@@ -165,9 +303,19 @@
   <div id="grid" style="display:flex;flex-direction:column;gap:14px"></div>
 </main>
 
-<div class="footer">Commerce Claw · businessclaw.agentabrams.com · info@agentabrams.com</div>
+<div class="footer">VenturaClaw</div>
 
 <script>
+// ── OAuth-popup auto-close ──
+// When this page loads inside an OAuth popup we opened ourselves (window.opener exists and the
+// popup name matches `cc_oauth_<vendor>`), close the popup so the parent's queue can advance.
+// We close on a tiny delay so the cookie/session write from the OAuth callback fully commits.
+try {
+  if (window.opener && !window.opener.closed && /^cc_oauth_/.test(window.name)) {
+    setTimeout(() => { try { window.close(); } catch {} }, 200);
+  }
+} catch {}
+
 // ── OAuth provider metadata (mirrors server OAUTH_PROVIDERS) ──
 // icon: simpleicons slug; tint: brand hex used for icon tint
 const OAUTH_PROVIDERS = [
@@ -181,18 +329,23 @@ const OAUTH_PROVIDERS = [
 ];
 
 // ── State ──
-// oauthFilledIds: set of vendor IDs the server says are already connected via OAuth
-// We detect it from /api/me/connections — a connector filled via OAuth has _via=oauth stored,
-// but the masked endpoint doesn't expose that. Instead we load both endpoints and cross-reference:
-// any vendor whose id matches an OAUTH_PROVIDERS entry AND has filled=true in /api/me/connections.
 let oauthFilledIds = new Set();
-// newlyConnectedId: vendor that just came back from OAuth (detected via ?oauth_vendor= param or
-// by comparing filled state before and after. We use a sessionStorage snapshot approach.)
 let newlyConnectedId = null;
+// Selection set for bulk connect — vendor ids the user ticked.
+let selectedIds = new Set();
 
 // ── DOM refs ──
 const oauthGrid = document.getElementById('oauth-grid');
 const manualGrid = document.getElementById('grid');
+const bulkBar = document.getElementById('bulk-bar');
+const bulkSelectAll = document.getElementById('bulk-select-all');
+const bulkCount = document.getElementById('bulk-count');
+const bulkGo = document.getElementById('bulk-go');
+const queueBar = document.getElementById('queue-bar');
+const queueMsg = document.getElementById('queue-msg');
+const queueProgress = document.getElementById('queue-progress');
+const queueNext = document.getElementById('queue-next');
+const queueCancel = document.getElementById('queue-cancel');
 
 // ── Detect return from OAuth callback ──
 // The server redirects back to /connections (no extra query param).
@@ -218,6 +371,7 @@ function buildOAuthTile(provider, isConnected, isNew) {
   const iconUrl = `https://cdn.simpleicons.org/${iconSlug}/${tintClean}`;
 
   tile.innerHTML = `
+    ${isConnected ? '' : `<input type="checkbox" class="oauth-tile-check" data-select="${esc(provider.id)}" title="Select for bulk connect" />`}
     <img class="oauth-tile-logo" src="${esc(iconUrl)}" alt="${esc(provider.name)} logo"
          onerror="this.style.display='none'" loading="lazy" />
     <div>
@@ -290,13 +444,177 @@ function renderOAuthSection(connections) {
   saveSnapshot(oauthFilledIds);
 
   oauthGrid.innerHTML = '';
+  // Drop already-connected vendors from the selection set
+  for (const id of [...selectedIds]) if (oauthFilledIds.has(id)) selectedIds.delete(id);
+
   for (const p of OAUTH_PROVIDERS) {
     const isConnected = oauthFilledIds.has(p.id);
     const isNew = p.id === newlyConnectedId;
-    oauthGrid.appendChild(buildOAuthTile(p, isConnected, isNew));
+    const tileEl = buildOAuthTile(p, isConnected, isNew);
+    if (selectedIds.has(p.id)) tileEl.classList.add('is-selected');
+    oauthGrid.appendChild(tileEl);
   }
+
+  // Wire per-tile checkboxes
+  oauthGrid.querySelectorAll('[data-select]').forEach(cb => {
+    cb.checked = selectedIds.has(cb.dataset.select);
+    cb.addEventListener('change', () => {
+      const id = cb.dataset.select;
+      if (cb.checked) selectedIds.add(id); else selectedIds.delete(id);
+      const tile = cb.closest('.oauth-tile');
+      tile.classList.toggle('is-selected', cb.checked);
+      updateBulkBar();
+    });
+  });
+
+  updateBulkBar();
+  renderQueueBar();
 }
 
+// ── Bulk control bar ──
+function availableForBulk() {
+  return OAUTH_PROVIDERS.filter(p => !oauthFilledIds.has(p.id)).map(p => p.id);
+}
+function updateBulkBar() {
+  const avail = availableForBulk();
+  if (avail.length === 0) {
+    bulkBar.style.display = 'none';
+    return;
+  }
+  bulkBar.style.display = 'flex';
+  const n = selectedIds.size;
+  bulkCount.textContent = n === 0 ? `0 selected · ${avail.length} available`
+                                  : `${n} selected · ${avail.length} available`;
+  bulkGo.disabled = (n === 0) || queueIsActive();
+  // Master checkbox state
+  bulkSelectAll.checked = (n > 0 && n === avail.length);
+  bulkSelectAll.indeterminate = (n > 0 && n < avail.length);
+}
+bulkSelectAll.addEventListener('change', () => {
+  const avail = availableForBulk();
+  if (bulkSelectAll.checked) {
+    selectedIds = new Set(avail);
+  } else {
+    selectedIds = new Set();
+  }
+  // Re-render to reflect selection (cheap — same connection data)
+  renderOAuthSection(_lastConnections || []);
+});
+bulkGo.addEventListener('click', () => {
+  if (selectedIds.size === 0) return;
+  startQueue([...selectedIds]);
+});
+
+// ── Sequential OAuth queue ──
+// Each popup needs its own user gesture (Chrome consumes transient activation per popup),
+// so we open #1 here on click, then show a Continue button to open #2, etc.
+const QUEUE_KEY = 'cc_oauth_queue';
+function loadQueue() {
+  try { return JSON.parse(sessionStorage.getItem(QUEUE_KEY) || 'null'); } catch { return null; }
+}
+function saveQueue(q) {
+  if (!q) sessionStorage.removeItem(QUEUE_KEY);
+  else sessionStorage.setItem(QUEUE_KEY, JSON.stringify(q));
+}
+function queueIsActive() {
+  const q = loadQueue();
+  return !!(q && q.pending && q.pending.length > 0);
+}
+function providerName(id) {
+  return (OAUTH_PROVIDERS.find(p => p.id === id) || {}).name || id;
+}
+
+function startQueue(ids) {
+  // Filter out any already-connected (in case state changed)
+  const pending = ids.filter(id => !oauthFilledIds.has(id));
+  if (!pending.length) return;
+  saveQueue({ pending, completed: [], started_at: Date.now() });
+  // Open the first immediately on user click (transient activation present)
+  openNextInQueue(true);
+}
+
+function openNextInQueue(isUserGesture) {
+  const q = loadQueue();
+  if (!q || !q.pending.length) {
+    finishQueue();
+    return;
+  }
+  const id = q.pending[0];
+  // Skip if it became connected meanwhile
+  if (oauthFilledIds.has(id)) {
+    q.pending.shift();
+    q.completed.push(id);
+    saveQueue(q);
+    renderQueueBar();
+    refresh(true);
+    return;
+  }
+  // Save snapshot so the OAuth-return detection works
+  saveSnapshot(oauthFilledIds);
+  const popup = window.open(`/oauth/${id}/connect`, `cc_oauth_${id}`, 'width=600,height=700');
+  if (!popup) {
+    queueMsg.textContent = `Pop-up blocked. Allow pop-ups for this site, then click Continue.`;
+    return;
+  }
+  // Mark this id as in-flight; we leave it at the head of pending until we observe it connected
+  // or the user clicks "Skip"
+  renderQueueBar();
+  // Poll until the popup is closed; then refresh and either advance or wait for user click
+  const poll = setInterval(() => {
+    let closed = false;
+    try { closed = popup.closed; } catch { closed = true; }
+    if (closed) {
+      clearInterval(poll);
+      // Allow callback redirect to settle, then refresh
+      setTimeout(async () => {
+        await refresh(true);
+        const q2 = loadQueue();
+        if (!q2) return;
+        if (oauthFilledIds.has(id)) {
+          q2.pending.shift();
+          q2.completed.push(id);
+          saveQueue(q2);
+          renderQueueBar();
+          // Still pending? Show Continue button (need new user gesture to open next popup).
+          if (q2.pending.length === 0) finishQueue();
+        } else {
+          // Connect didn't complete (user closed early). Keep id at head; let user click Continue
+          // to retry, or Skip via cancel-then-deselect.
+          renderQueueBar(`Didn't finish ${providerName(id)}. Click Continue to retry, or Cancel.`);
+        }
+      }, 800);
+    }
+  }, 500);
+}
+
+function renderQueueBar(overrideMsg) {
+  const q = loadQueue();
+  if (!q || !q.pending.length) {
+    queueBar.style.display = 'none';
+    return;
+  }
+  queueBar.style.display = 'flex';
+  const total = q.pending.length + q.completed.length;
+  const done = q.completed.length;
+  const nextId = q.pending[0];
+  queueMsg.textContent = overrideMsg || `Next up: ${providerName(nextId)} — click Continue to open the OAuth window.`;
+  queueProgress.textContent = `${done}/${total} done · ${q.pending.length} remaining`;
+  queueNext.textContent = `Continue → ${providerName(nextId)}`;
+}
+
+function finishQueue() {
+  saveQueue(null);
+  queueBar.style.display = 'none';
+  selectedIds = new Set();
+  updateBulkBar();
+}
+
+queueNext.addEventListener('click', () => openNextInQueue(true));
+queueCancel.addEventListener('click', () => {
+  if (!confirm('Cancel the connect queue? Already-connected providers stay connected.')) return;
+  finishQueue();
+});
+
 // ── Manual connector tile ──
 function tile(c) {
   const el = document.createElement('div');
@@ -364,7 +682,7 @@ async function renderAnthropicBanner() {
     host.innerHTML = `
       <div>
         <div style="font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--gold)">⚡ CONNECT CLAUDE TO AUTO-IMPORT YOUR MCPs</div>
-        <div style="font-size:13px;margin-top:4px">Drop your Anthropic API key and BusinessClaw will auto-discover the MCP servers you've already wired in Claude Code.</div>
+        <div style="font-size:13px;margin-top:4px">Drop your Anthropic API key and VenturaClaw will auto-discover the MCP servers you've already wired in Claude Code.</div>
       </div>
       <div style="display:flex;gap:8px;align-items:center">
         <a class="btn" href="https://console.anthropic.com/settings/keys" target="_blank" rel="noopener">Get key ↗</a>
@@ -386,11 +704,11 @@ async function discoverMcps() {
   const d = await r.json();
   if (!r.ok) return alert(d.error + ': ' + (d.hint || ''));
   DISCOVERED_MCPS = new Set((d.mcps || []).filter(m => m.bc_connector).map(m => m.bc_connector));
-  alert(`Discovered ${d.discovered} MCP servers · ${d.mapped} map to BusinessClaw connectors · ${d.already_in_bc} already have tokens loaded.`);
+  alert(`Discovered ${d.discovered} MCP servers · ${d.mapped} map to VenturaClaw connectors · ${d.already_in_bc} already have tokens loaded.`);
   refresh();
 }
 async function autoImport() {
-  if (!confirm('Auto-import all token values from your local secrets-manager + MCP config into your BusinessClaw account?')) return;
+  if (!confirm('Auto-import all token values from your local secrets-manager + MCP config into your VenturaClaw account?')) return;
   const r = await fetch('/api/anthropic/auto-import', { method: 'POST' });
   const d = await r.json();
   if (!r.ok) return alert(d.error + (d.hint ? ': ' + d.hint : ''));
@@ -399,6 +717,7 @@ async function autoImport() {
 }
 
 // ── Main refresh ──
+let _lastConnections = [];
 async function refresh(silent) {
   if (!silent) renderAnthropicBanner();
   const d = await (await fetch('/api/me/connections')).json();
@@ -406,6 +725,8 @@ async function refresh(silent) {
   // Mark MCP-discovered connectors with a badge
   for (const c of d.connections) c.via_mcp = DISCOVERED_MCPS.has(c.id);
 
+  _lastConnections = d.connections;
+
   // Render OAuth section first
   renderOAuthSection(d.connections);
 
@@ -493,6 +814,8 @@ document.getElementById('logout').addEventListener('click', async e => {
 refresh().then(() => {
   const loading = document.getElementById('oauth-loading');
   if (loading) loading.remove();
+  // Resume any in-flight bulk-connect queue (e.g. user refreshed mid-flow)
+  renderQueueBar();
 });
 </script>
 </body></html>
diff --git a/server/public/fill.html b/server/public/fill.html
new file mode 100644
index 0000000..8145407
--- /dev/null
+++ b/server/public/fill.html
@@ -0,0 +1,146 @@
+<!doctype html>
+<html lang="en"><head>
+<meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
+<title>Fill in Tokens — VenturaClaw</title>
+<link rel="stylesheet" href="/static/style.css" />
+<style>
+  .progress { display: flex; align-items: center; gap: 14px; padding: 18px; border: 1px solid var(--gold); border-radius: 4px; background: rgba(212,160,74,0.06); margin-bottom: 18px; }
+  .progress-bar { flex: 1; height: 8px; background: rgba(244,241,234,0.06); border-radius: 999px; overflow: hidden; }
+  .progress-fill { height: 100%; background: var(--gold); transition: width 600ms ease; }
+  .progress-text { font-family: var(--mono); font-size: 11px; letter-spacing: .12em; color: var(--gold); white-space: nowrap; }
+  .row { padding: 18px; border: 1px solid var(--rule); border-radius: 4px; margin-bottom: 12px; transition: all 400ms ease; display: grid; grid-template-columns: 48px 1fr; gap: 16px; align-items: start; }
+  .row.done { border-color: var(--good); background: rgba(143,184,154,0.06); }
+  .row.removing { opacity: 0; transform: translateX(-20px); max-height: 0; padding: 0; margin: 0; border: 0; overflow: hidden; }
+  .logo { width: 40px; height: 40px; border-radius: 6px; background: rgba(244,241,234,0.92); padding: 6px; display: flex; align-items: center; justify-content: center; }
+  .logo img { width: 100%; height: 100%; object-fit: contain; }
+  .logo .fb { width: 100%; height: 100%; color: white; font-weight: 700; font-size: 16px; display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; }
+  .row h3 { font-family: var(--serif); font-weight: 500; font-size: 18px; margin: 0 0 4px; }
+  .row .meta { font-family: var(--mono); font-size: 10px; letter-spacing: .12em; color: var(--ink-mute); margin-bottom: 8px; }
+  .row .steps { font-size: 12px; color: var(--ink-soft); line-height: 1.55; margin-bottom: 12px; }
+  .row .actions { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
+  .row form { display: grid; grid-template-columns: 1fr auto auto; gap: 8px; align-items: stretch; margin-top: 10px; }
+  .row form.multi { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)) auto; }
+  .row form input { font-family: var(--mono); font-size: 12px; padding: 8px 12px; }
+  .row form button { white-space: nowrap; }
+  .row .result { font-family: var(--mono); font-size: 11px; margin-top: 8px; min-height: 14px; }
+  .row .result.ok  { color: var(--good); }
+  .row .result.err { color: var(--bad); }
+  .empty-state { text-align: center; padding: 60px 20px; }
+  .empty-state .big { font-family: var(--serif); font-size: 28px; font-style: italic; color: var(--gold); margin-bottom: 8px; }
+  .empty-state .small { font-family: var(--mono); font-size: 11px; letter-spacing: .12em; color: var(--ink-mute); }
+</style>
+</head><body>
+<header class="topbar">
+  <div class="brand"><div class="logo-dot"></div><div><div class="brand-name">Ventura<em style="font-style:italic;color:var(--gold)">Claw</em></div><div class="brand-sub">Fill in Tokens</div></div></div>
+  <nav class="nav" style="display:flex;gap:6px;font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase">
+    <a href="/chat"            style="padding:8px 14px;color:var(--ink-soft)">Chat</a>
+    <a href="/connections"     style="padding:8px 14px;color:var(--ink-soft)">Connections</a>
+    <a href="/fill"            style="padding:8px 14px;color:var(--gold);border-bottom:1px solid var(--gold)">Fill</a>
+    <a href="/admin/connectors" style="padding:8px 14px;color:var(--ink-soft)">Admin</a>
+    <a href="#" id="logout"     style="padding:8px 14px;color:var(--ink-soft)">Sign out</a>
+  </nav>
+</header>
+
+<main style="padding:24px 28px;max-width:920px;margin:0 auto">
+  <div class="progress">
+    <div class="progress-bar"><div class="progress-fill" id="bar" style="width:0%"></div></div>
+    <div class="progress-text" id="ptext">CHECKING…</div>
+  </div>
+
+  <div id="rows"></div>
+</main>
+
+<div class="footer">VenturaClaw · paste once, test on the spot. <a href="/connections" style="color:var(--gold)">advanced view →</a></div>
+
+<script>
+const esc = s => String(s == null ? "" : s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
+
+function logo(c) {
+  if (c.logo) return `<div class="logo"><img src="https://cdn.simpleicons.org/${c.logo}/${(c.tint||'').replace('#','')}" alt="${esc(c.name)}" loading="lazy" onerror="this.outerHTML='<div class=\\'fb\\' style=\\'background:${esc(c.tint||'#999')}\\'>${esc(c.name[0])}</div>'"></div>`;
+  return `<div class="logo"><div class="fb" style="background:${esc(c.tint||'#999')}">${esc(c.name[0])}</div></div>`;
+}
+
+async function load() {
+  const meta = await (await fetch('/api/connectors/acquisition')).json();
+  const conns = (meta.connectors || []).filter(c => c.real_impl);   // only real-impl connectors
+  const total = conns.length;
+
+  // Probe health for each filled connector — broken (red) tiles also need fill
+  const probes = await Promise.all(conns.filter(c => c.filled).map(async c => {
+    try { const h = await fetch(`/api/connectors/${c.id}/health`).then(r => r.json()); return { id: c.id, ok: h.ok }; }
+    catch { return { id: c.id, ok: false }; }
+  }));
+  const okSet = new Set(probes.filter(p => p.ok).map(p => p.id));
+
+  // Each connector: needs_fill = (!filled) OR (filled but health failed)
+  const needs = conns.filter(c => !c.filled || !okSet.has(c.id));
+  const done = total - needs.length;
+  document.getElementById('bar').style.width = `${Math.round(done * 100 / total)}%`;
+  document.getElementById('ptext').textContent = `${done} OF ${total} CONNECTED`;
+
+  if (!needs.length) {
+    document.getElementById('rows').innerHTML = `
+      <div class="empty-state">
+        <div class="big">all connected.</div>
+        <div class="small">every real-impl connector has a working token. nothing left to fill.</div>
+      </div>`;
+    return;
+  }
+
+  document.getElementById('rows').innerHTML = needs.map(c => {
+    const acq = c.acquisition;
+    const fields = (acq?.fields || c.fields || []);
+    const formCls = fields.length > 1 ? 'multi' : '';
+    const fieldHtml = fields.map(f => `<input name="${esc(f.key)}" type="${f.type==='password'?'password':'text'}" placeholder="${esc(f.label || f.key)}" autocomplete="off" required="${f.required ? '' : ''}" />`).join('');
+    return `<div class="row" data-id="${esc(c.id)}">
+      ${logo(c)}
+      <div>
+        <h3>${esc(c.name)}</h3>
+        <div class="meta">${esc(c.category)} · ${c.filled ? '<span style="color:var(--bad)">⚠ broken token</span>' : 'no token yet'}</div>
+        ${acq?.get_key_steps ? `<div class="steps">${esc(acq.get_key_steps)}</div>` : ''}
+        <div class="actions">
+          ${acq?.get_key_url ? `<a href="${esc(acq.get_key_url)}" target="_blank" rel="noopener" class="btn">Get key ↗</a>` : ''}
+          <a href="${esc(c.docs)}" target="_blank" rel="noopener" class="btn btn-ghost">Docs ↗</a>
+        </div>
+        <form data-form="${esc(c.id)}" class="${formCls}">
+          ${fieldHtml}
+          <button type="submit" class="btn btn-primary">Save & test</button>
+        </form>
+        <div class="result"></div>
+      </div>
+    </div>`;
+  }).join('');
+
+  document.querySelectorAll('form[data-form]').forEach(f => f.addEventListener('submit', async e => {
+    e.preventDefault();
+    const id = f.dataset.form;
+    const row = f.closest('.row');
+    const result = row.querySelector('.result');
+    const body = {};
+    for (const inp of f.querySelectorAll('input')) if (inp.value && inp.value.trim()) body[inp.name] = inp.value.trim();
+    if (!Object.keys(body).length) { result.className = 'result err'; result.textContent = 'enter at least one field'; return; }
+    result.className = 'result'; result.textContent = 'saving…';
+    const save = await fetch(`/api/me/connections/${id}`, { method:'POST', headers:{'content-type':'application/json'}, body: JSON.stringify(body) });
+    if (!save.ok) { const j = await save.json(); result.className = 'result err'; result.textContent = '✗ ' + (j.error || 'save failed'); return; }
+    result.textContent = 'testing…';
+    const h = await fetch(`/api/connectors/${id}/health`).then(r => r.json());
+    if (h.ok) {
+      result.className = 'result ok';
+      result.textContent = '✓ live · ' + (h.team || h.account_id || h.user || h.account || h.user_id || h.endpoint || 'verified');
+      row.classList.add('done');
+      setTimeout(() => { row.classList.add('removing'); }, 1000);
+      setTimeout(load, 1800); // refresh whole page state
+    } else {
+      result.className = 'result err';
+      result.textContent = '✗ saved but health failed: ' + (h.reason || 'unknown');
+    }
+  }));
+}
+
+document.getElementById('logout').addEventListener('click', async e => {
+  e.preventDefault(); await fetch('/api/auth/logout', { method: 'POST' }); location.href = '/login';
+});
+
+load();
+</script>
+</body></html>
diff --git a/server/public/homepage.html b/server/public/homepage.html
index f65d5a1..65143e4 100644
--- a/server/public/homepage.html
+++ b/server/public/homepage.html
@@ -2,24 +2,24 @@
 <html lang="en"><head>
 <meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
 <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
-<link rel="alternate" type="application/rss+xml" title="Commerce Claw changelog" href="/feed" />
+<link rel="alternate" type="application/rss+xml" title="VenturaClaw changelog" href="/feed" />
 <link rel="prefetch" href="/connectors" />
 <meta name="theme-color" content="#0e0e10" />
-<title>Commerce Claw — One AI command runs 56 SaaS tools</title>
+<title>VenturaClaw — One AI command runs 56 SaaS tools</title>
 <meta name="description" content="Type one sentence. The AI picks the right SaaS tool — Stripe, Shopify, Slack, Cloudflare, HubSpot — and runs the action. 56 connectors out of the box. Encrypted at rest, audit-trailed, sensitive actions gated by approval." />
-<link rel="canonical" href="https://businessclaw.agentabrams.com/" />
+<link rel="canonical" href="https://venturaclaw.agentabrams.com/" />
 <meta property="og:type" content="website" />
-<meta property="og:title" content="Commerce Claw — One AI command runs 56 SaaS tools" />
+<meta property="og:title" content="VenturaClaw — One AI command runs 56 SaaS tools" />
 <meta property="og:description" content="Type one sentence. The AI picks the tool and runs the action. 56 connectors. Zero workflow-building." />
-<meta property="og:url" content="https://businessclaw.agentabrams.com/" />
-<meta property="og:image" content="https://businessclaw.agentabrams.com/static/og-cover.svg" />
-<meta property="og:site_name" content="Commerce Claw" />
+<meta property="og:url" content="https://venturaclaw.agentabrams.com/" />
+<meta property="og:image" content="https://venturaclaw.agentabrams.com/static/og-cover.svg" />
+<meta property="og:site_name" content="VenturaClaw" />
 <meta name="twitter:card" content="summary_large_image" />
-<meta name="twitter:title" content="Commerce Claw — One AI command runs 56 SaaS tools" />
+<meta name="twitter:title" content="VenturaClaw — One AI command runs 56 SaaS tools" />
 <meta name="twitter:description" content="Type one sentence. The AI picks the tool and runs the action." />
-<meta name="twitter:image" content="https://businessclaw.agentabrams.com/static/og-cover.svg" />
+<meta name="twitter:image" content="https://venturaclaw.agentabrams.com/static/og-cover.svg" />
 <script type="application/ld+json">
-{"@context":"https://schema.org","@type":"SoftwareApplication","name":"Commerce Claw","applicationCategory":"BusinessApplication","operatingSystem":"Web","description":"AI agent that routes natural-language commands to 56 business connectors including Stripe, Shopify, Slack, Cloudflare, Notion, HubSpot, and Discord. Encrypted at rest, audit-trailed, with a sensitive-action approval queue.","url":"https://businessclaw.agentabrams.com","offers":{"@type":"Offer","price":"0","priceCurrency":"USD"},"publisher":{"@type":"Organization","name":"Steve Abrams","email":"info@agentabrams.com"}}
+{"@context":"https://schema.org","@type":"SoftwareApplication","name":"VenturaClaw","applicationCategory":"BusinessApplication","operatingSystem":"Web","description":"AI agent that routes natural-language commands to 56 business connectors including Stripe, Shopify, Slack, Cloudflare, Notion, HubSpot, and Discord. Encrypted at rest, audit-trailed, with a sensitive-action approval queue.","url":"https://venturaclaw.agentabrams.com","offers":{"@type":"Offer","price":"0","priceCurrency":"USD"},"publisher":{"@type":"Organization","name":"Steve Abrams","email":"info@venturaclaw.agentabrams.com"}}
 </script>
 <link rel="stylesheet" href="/static/style.css" />
 <link rel="stylesheet" href="/static/homepage.css" />
@@ -29,8 +29,8 @@
   <div class="brand" style="display:flex;gap:12px;align-items:center">
     <div class="logo-dot"></div>
     <div>
-      <div class="brand-name" style="font-family:var(--serif);font-size:20px;font-weight:500">Commerce <em style="font-style:italic;color:var(--gold)">Claw</em></div>
-      <div class="brand-sub" style="font-family:var(--mono);font-size:9px;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-mute)">Connected Commerce</div>
+      <div class="brand-name" style="font-family:var(--serif);font-size:20px;font-weight:500">Ventura<em style="font-style:italic;color:var(--gold)">Claw</em></div>
+      <div class="brand-sub" style="font-family:var(--mono);font-size:9px;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-mute)">Connected Operations</div>
     </div>
   </div>
   <nav style="display:flex;gap:18px;align-items:center;font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase">
@@ -158,7 +158,7 @@ audit log #4827 written ✓</pre>
       <div style="font-family:var(--mono);font-size:11px;line-height:1.7;color:var(--ink-soft)">Credit-metered AI assists. Bardeen's 1,000 Premium credits burn through in a single workday at 3 credits/row. The math is the moat — until it isn't.</div>
     </div>
     <div style="background:var(--bg-elevated);border:1px solid var(--rule);border-left:3px solid var(--gold);border-radius:4px;padding:22px 24px">
-      <div style="font-family:var(--serif);font-size:18px;color:var(--gold);margin-bottom:6px">Commerce <em style="font-style:italic">Claw</em></div>
+      <div style="font-family:var(--serif);font-size:18px;color:var(--gold);margin-bottom:6px">Ventura<em style="font-style:italic">Claw</em></div>
       <div style="font-family:var(--mono);font-size:11px;line-height:1.7;color:var(--ink-soft)">56 curated connectors, on-demand routing. The command layer IS the product, not a feature bolted on. Local LLM means your IP doesn't leak.</div>
     </div>
   </div>
@@ -172,9 +172,9 @@ audit log #4827 written ✓</pre>
     <details class="faq-item"><summary>Where do my API keys actually live?</summary><p>On disk, AES-256-GCM encrypted with a versioned key envelope (key_id rotation supported). The encryption key is derived from a server-side secret loaded only at boot and never logged. The plaintext leaves memory the moment it's saved.</p></details>
     <details class="faq-item"><summary>Does the AI ever see my full data?</summary><p>The local LLM only sees your <em>command</em> (e.g., "refund order 1234 on Shopify") to pick the connector and parse arguments. It does not see vendor responses or your other connectors' data. Routing runs on Steve's hardware — no third-party LLM API.</p></details>
     <details class="faq-item"><summary>What if the AI picks the wrong tool?</summary><p>Sensitive actions (refunds, posts, DNS edits, deletions) land in an approval queue with the parsed intent shown in plain English. Read it. Approve or reject. Reads execute immediately because they don't change state.</p></details>
-    <details class="faq-item"><summary>How does this differ from Zapier or Make?</summary><p>Those are workflow builders — you wire triggers to actions on a canvas, then maintain the wires. Commerce Claw is the opposite: type one sentence, the AI picks the connector. No canvas, no Zaps to maintain, no per-task pricing.</p></details>
+    <details class="faq-item"><summary>How does this differ from Zapier or Make?</summary><p>Those are workflow builders — you wire triggers to actions on a canvas, then maintain the wires. VenturaClaw is the opposite: type one sentence, the AI picks the connector. No canvas, no Zaps to maintain, no per-task pricing.</p></details>
     <details class="faq-item"><summary>What's the pricing?</summary><p>Currently free while in early access. The eventual model will be a flat workspace fee (no per-task metering, no credit math). If pricing changes, you'll get 30 days notice and can export your audit log + connector registrations on the way out.</p></details>
-    <details class="faq-item"><summary>Can I self-host?</summary><p>Not yet packaged for distribution. The architecture is a single Node process + JSON store + local Ollama, so it's straightforward to lift — email <a href="mailto:info@agentabrams.com" style="color:var(--gold)">info@agentabrams.com</a> if you want the Docker recipe.</p></details>
+    <details class="faq-item"><summary>Can I self-host?</summary><p>Not yet packaged for distribution. The architecture is a single Node process + JSON store + local Ollama, so it's straightforward to lift — email <a href="mailto:info@venturaclaw.agentabrams.com" style="color:var(--gold)">info@venturaclaw.agentabrams.com</a> if you want the Docker recipe.</p></details>
     <details class="faq-item"><summary>What if I want a connector that's not in the 56?</summary><p>Most modern SaaS tools speak OAuth2 + REST and slot in cleanly. Tell us what you need; new connectors typically ship in 1-3 days. Anything that exposes a webhook can be wired the same week.</p></details>
     <details class="faq-item"><summary>Is this production-ready?</summary><p>Encryption-at-rest, atomic writes with fsync, audit trail, sensitive-action approval queue, CSP+HSTS, rate limits — yes, by mainstream-SaaS standards. We're early-access because the connector matrix and UX are still hardening, not because the security floor is.</p></details>
   </div>
@@ -196,19 +196,19 @@ audit log #4827 written ✓</pre>
   <h2>Skip the canvas. <em>Just type.</em></h2>
   <div class="cta-row">
     <a href="/login" class="btn-cta">Sign in →</a>
-    <a href="mailto:info@agentabrams.com" class="btn-cta btn-cta-ghost">Talk to Steve</a>
+    <a href="mailto:info@venturaclaw.agentabrams.com" class="btn-cta btn-cta-ghost">Talk to Steve</a>
   </div>
 </section>
 
 <footer class="footer">
-  <div class="left">Commerce Claw · businessclaw.agentabrams.com</div>
+  <div class="left">VenturaClaw</div>
   <div class="right">
     <a href="/connectors">Connectors</a>
     <a href="/about">About</a>
     <a href="/privacy">Privacy</a>
     <a href="/terms">Terms</a>
     <a href="/sitemap.xml">Sitemap</a>
-    <a href="mailto:info@agentabrams.com">info@agentabrams.com</a>
+    <a href="mailto:info@venturaclaw.agentabrams.com">info@venturaclaw.agentabrams.com</a>
     <a href="/login">Sign in</a>
   </div>
 </footer>
diff --git a/server/public/login.html b/server/public/login.html
index acd7705..f6b1010 100644
--- a/server/public/login.html
+++ b/server/public/login.html
@@ -3,21 +3,21 @@
 <meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
 <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
 <meta name="theme-color" content="#0e0e10" />
-<title>Commerce Claw — AI agent for 56 business connectors</title>
+<title>VenturaClaw — AI agent for 56 business connectors</title>
 <meta name="description" content="Connect Stripe, Shopify, Slack, and 53 more SaaS tools to one AI command line. Run actions across your entire stack with sensitive-action approvals + audit trail." />
-<link rel="canonical" href="https://businessclaw.agentabrams.com/" />
+<link rel="canonical" href="https://venturaclaw.agentabrams.com/" />
 <meta property="og:type" content="website" />
-<meta property="og:title" content="Commerce Claw — AI agent for 56 business connectors" />
+<meta property="og:title" content="VenturaClaw — AI agent for 56 business connectors" />
 <meta property="og:description" content="Connect Stripe, Shopify, Slack, and 53 more SaaS tools to one AI command line." />
-<meta property="og:url" content="https://businessclaw.agentabrams.com/" />
-<meta property="og:image" content="https://businessclaw.agentabrams.com/static/og-cover.png" />
-<meta property="og:site_name" content="Commerce Claw" />
+<meta property="og:url" content="https://venturaclaw.agentabrams.com/" />
+<meta property="og:image" content="https://venturaclaw.agentabrams.com/static/og-cover.png" />
+<meta property="og:site_name" content="VenturaClaw" />
 <meta name="twitter:card" content="summary_large_image" />
-<meta name="twitter:title" content="Commerce Claw — AI agent for 56 business connectors" />
+<meta name="twitter:title" content="VenturaClaw — AI agent for 56 business connectors" />
 <meta name="twitter:description" content="Connect Stripe, Shopify, Slack, and 53 more SaaS tools to one AI command line." />
-<meta name="twitter:image" content="https://businessclaw.agentabrams.com/static/og-cover.png" />
+<meta name="twitter:image" content="https://venturaclaw.agentabrams.com/static/og-cover.png" />
 <script type="application/ld+json">
-{"@context":"https://schema.org","@type":"SoftwareApplication","name":"Commerce Claw","applicationCategory":"BusinessApplication","description":"AI agent that runs actions across 56 business connectors including Stripe, Shopify, Slack, Cloudflare, Notion, HubSpot, and Discord.","operatingSystem":"Web","url":"https://businessclaw.agentabrams.com","offers":{"@type":"Offer","price":"0","priceCurrency":"USD"},"publisher":{"@type":"Organization","name":"Steve Abrams","email":"info@businessclaw.com"}}
+{"@context":"https://schema.org","@type":"SoftwareApplication","name":"VenturaClaw","applicationCategory":"BusinessApplication","description":"AI agent that runs actions across 56 business connectors including Stripe, Shopify, Slack, Cloudflare, Notion, HubSpot, and Discord.","operatingSystem":"Web","url":"https://venturaclaw.agentabrams.com","offers":{"@type":"Offer","price":"0","priceCurrency":"USD"},"publisher":{"@type":"Organization","name":"Steve Abrams","email":"info@venturaclaw.agentabrams.com"}}
 </script>
 <link rel="stylesheet" href="/static/style.css" />
 </head><body>
@@ -26,8 +26,8 @@
   <div class="brand">
     <div class="logo-dot"></div>
     <div>
-      <div class="brand-name">Commerce <em style="font-style:italic;color:var(--gold)">Claw</em></div>
-      <div class="brand-sub">Connected Commerce</div>
+      <div class="brand-name">Ventura<em style="font-style:italic;color:var(--gold)">Claw</em></div>
+      <div class="brand-sub">Connected Operations</div>
     </div>
   </div>
   <h2>Sign <em style="font-style:italic;color:var(--gold)">in</em></h2>
@@ -45,7 +45,7 @@
   </p>
 </div>
 </main>
-<div class="footer">Commerce Claw</div>
+<div class="footer">VenturaClaw</div>
 <script>
 const f = document.getElementById('f'), err = document.getElementById('err');
 f.addEventListener('submit', async e => {
diff --git a/server/public/oauth-setup.html b/server/public/oauth-setup.html
index 75250f5..3a692d3 100644
--- a/server/public/oauth-setup.html
+++ b/server/public/oauth-setup.html
@@ -1,7 +1,7 @@
 <!doctype html>
 <html lang="en"><head>
 <meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
-<title>OAuth Setup — Commerce Claw</title>
+<title>OAuth Setup — VenturaClaw</title>
 <link rel="stylesheet" href="/static/style.css" />
 <style>
 .setup-page { max-width: 1080px; margin: 0 auto; padding: 28px; }
@@ -37,7 +37,7 @@
   <div class="brand">
     <div class="logo-dot"></div>
     <div>
-      <div class="brand-name">Commerce <em style="font-style:italic;color:var(--gold)">Claw</em></div>
+      <div class="brand-name">Ventura<em style="font-style:italic;color:var(--gold)">Claw</em></div>
       <div class="brand-sub">OAuth Setup · Admin</div>
     </div>
   </div>
@@ -55,12 +55,12 @@
     <div class="sub">Register vendor apps · paste credentials · users connect with one click</div>
   </div>
 
-  <p class="setup-lede">Each vendor below needs a one-time <em style="color:var(--gold)">OAuth app registration</em> in their developer portal. Use <code style="font-family:var(--mono);font-size:14px;color:var(--gold)">info@businessclaw.com</code> as the contact email everywhere. After registering, paste the Client ID + Client Secret here. Users then connect with a single button click.</p>
+  <p class="setup-lede">Each vendor below needs a one-time <em style="color:var(--gold)">OAuth app registration</em> in their developer portal. Use <code style="font-family:var(--mono);font-size:14px;color:var(--gold)">info@venturaclaw.agentabrams.com</code> as the contact email everywhere. After registering, paste the Client ID + Client Secret here. Users then connect with a single button click.</p>
 
   <div class="contact">
     <b>Default contact email →</b>
-    <code style="font-family:var(--mono);font-size:13px;color:var(--ink)">info@businessclaw.com</code>
-    <button onclick="navigator.clipboard.writeText('info@businessclaw.com')" class="copy" style="font-family:var(--mono);font-size:9px;padding:4px 10px;background:transparent;border:1px solid var(--rule);color:var(--ink-soft);cursor:pointer;border-radius:2px">Copy</button>
+    <code style="font-family:var(--mono);font-size:13px;color:var(--ink)">info@venturaclaw.agentabrams.com</code>
+    <button onclick="navigator.clipboard.writeText('info@venturaclaw.agentabrams.com')" class="copy" style="font-family:var(--mono);font-size:9px;padding:4px 10px;background:transparent;border:1px solid var(--rule);color:var(--ink-soft);cursor:pointer;border-radius:2px">Copy</button>
   </div>
 
   <div id="providers" role="region" aria-label="OAuth providers" aria-live="polite"></div>
@@ -87,7 +87,7 @@ async function loadProviders() {
 
       <div class="steps">
         <span class="num">1</span>
-        <span class="lbl"><b>Open</b> ${esc(p.name)} developer portal as <code>info@businessclaw.com</code></span>
+        <span class="lbl"><b>Open</b> ${esc(p.name)} developer portal as <code>info@venturaclaw.agentabrams.com</code></span>
         <span style="display:flex;gap:6px">
           <a href="${escAttr(p.register_url)}" target="_blank" rel="noopener" class="btn btn-primary" style="font-family:var(--mono);font-size:9px;padding:6px 14px">Open ↗</a>
           <button data-vendor="${escAttr(p.id)}" class="btn launch-bb" style="font-family:var(--mono);font-size:9px;padding:6px 14px;border-color:var(--gold);color:var(--gold)" title="Cloud browser — isolated, no cookie pollution, auto-expires in 1hr">☁ Cloud →</button>
diff --git a/server/public/style.css b/server/public/style.css
index f492b00..aae6cf1 100644
--- a/server/public/style.css
+++ b/server/public/style.css
@@ -1,4 +1,4 @@
-/* Commerce Claw — editorial dark · DW design language */
+/* VenturaClaw — editorial dark · DW design language */
 :root {
   --ink: #f4f1ea;             /* warm paper */
   --ink-soft: rgba(244,241,234,0.78);
diff --git a/server/server.js b/server/server.js
index 4a2945d..13fa921 100644
--- a/server/server.js
+++ b/server/server.js
@@ -1,5 +1,5 @@
 #!/usr/bin/env node
-// Commerce Claw — production Express server
+// VenturaClaw — production Express server
 // Routes: /login, /chat, /admin, /admin/users, /admin/connectors, /admin/approvals, /admin/audit
 // API:    /api/auth/login, /api/auth/logout, /api/me, /api/connectors, /api/chat,
 //         /api/approvals (list/create/decide), /api/audit, /api/admin/users (CRUD)
@@ -9,7 +9,7 @@ const cookieParser = require("cookie-parser");
 const bcrypt = require("bcrypt");
 const rateLimit = require("express-rate-limit");
 
-// Allowlist-based env loader. Only keys actually used by Commerce Claw are imported
+// Allowlist-based env loader. Only keys actually used by VenturaClaw are imported
 // — prevents the entire master secrets-manager .env (300+ keys) from spilling into process.env.
 (function loadCanonicalSecrets() {
   const fs = require('fs'), path = require('path'), os = require('os');
@@ -57,7 +57,7 @@ if (process.env.NODE_ENV === "production" && SECRET === "commerce-claw-dev-secre
   process.exit(1);
 }
 const DOMAIN = process.env.PUBLIC_DOMAIN || "businessclaw.agentabrams.com";
-const SUPPORT_EMAIL = process.env.SUPPORT_EMAIL || "info@agentabrams.com";
+const SUPPORT_EMAIL = process.env.SUPPORT_EMAIL || "info@venturaclaw.agentabrams.com";
 
 // HTML-escape — used in OAuth error pages where vendor responses are echoed
 const esc = (s) => String(s == null ? "" : s).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
@@ -150,6 +150,14 @@ let users = load("users", [
 // (removed: unconditional save("users", users) — was wiping rotated passwords on every restart)
 let approvals = load("approvals", []);
 let audit = load("audit", []);
+// Per-user chat history. Keyed by userId. Each entry: { ts, role: "user"|"assistant"|"tool", text, toolCalls? }.
+// Capped at 200 messages per user; oldest dropped on overflow.
+let chatHistory = load("chat-history", {});
+function pushChat(userId, msg) {
+  if (!chatHistory[userId]) chatHistory[userId] = [];
+  chatHistory[userId].push({ ts: new Date().toISOString(), ...msg });
+  if (chatHistory[userId].length > 200) chatHistory[userId] = chatHistory[userId].slice(-200);
+}
 // Encrypted at rest. credentials.json stores envelope { _enc:1, iv, tag, data } — never plaintext from now on.
 function loadCredentials() {
   const raw = load("credentials", {});
@@ -481,7 +489,7 @@ app.get("/robots.txt", (req, res) => {
   );
 });
 app.get("/sitemap.xml", (req, res) => {
-  const staticUrls = ["/", "/login", "/connectors", "/about", "/faq", "/docs", "/changelog", "/privacy", "/terms"];
+  const staticUrls = ["/", "/login", "/connectors", "/about", "/faq", "/docs", "/pricing", "/changelog", "/privacy", "/terms"];
   const connectorUrls = CONNECTORS.map(c => `/connectors/${c.id}`);
   const all = [...staticUrls, ...connectorUrls];
   const xml = `<?xml version="1.0" encoding="UTF-8"?>
@@ -723,8 +731,8 @@ function _renderConnectorIndex() {
     </section>`).join("");
   const ld = {
     "@context":"https://schema.org","@type":"ItemList",
-    "name":"Commerce Claw Connectors",
-    "description":"All SaaS tools that Commerce Claw can route AI commands to.",
+    "name":"VenturaClaw Connectors",
+    "description":"All SaaS tools that VenturaClaw can route AI commands to.",
     "numberOfItems":CONNECTORS.length,
     "itemListElement": CONNECTORS.map((c, i) => ({
       "@type":"ListItem","position":i+1,
@@ -733,15 +741,15 @@ function _renderConnectorIndex() {
     })),
   };
   return _shell({
-    title: `All ${CONNECTORS.length} Connectors — Commerce Claw`,
-    desc: `Browse every SaaS tool Commerce Claw routes to: ${CONNECTORS.slice(0,8).map(c=>c.name).join(', ')}, and ${CONNECTORS.length - 8} more. Type one command, the AI picks the right one.`,
+    title: `All ${CONNECTORS.length} Connectors — VenturaClaw`,
+    desc: `Browse every SaaS tool VenturaClaw routes to: ${CONNECTORS.slice(0,8).map(c=>c.name).join(', ')}, and ${CONNECTORS.length - 8} more. Type one command, the AI picks the right one.`,
     canonical: `https://${DOMAIN}/connectors`,
     jsonLd: ld,
     body: `
       <main class="page">
         <div class="eyebrow">All connectors · pre-wired</div>
         <h1>Every <em>tool</em>, ready to route.</h1>
-        <p class="lede">Commerce Claw ships with ${CONNECTORS.length} SaaS connectors out of the box. Browse by category below, or just type what you want on the <a href="/" style="color:var(--gold)">homepage demo</a> and let the AI pick.</p>
+        <p class="lede">VenturaClaw ships with ${CONNECTORS.length} SaaS connectors out of the box. Browse by category below, or just type what you want on the <a href="/" style="color:var(--gold)">homepage demo</a> and let the AI pick.</p>
         ${sections}
       </main>`
   });
@@ -765,13 +773,13 @@ function _renderConnectorPage(c) {
   };
   const exs = examples[cat] || [`use ${c.name} to do something`, `list things in ${c.name}`, `update something on ${c.name}`];
   const ld = {
-    "@context":"https://schema.org","@type":"SoftwareSourceCode","name":`${c.name} integration · Commerce Claw`,
+    "@context":"https://schema.org","@type":"SoftwareSourceCode","name":`${c.name} integration · VenturaClaw`,
     "applicationCategory":"BusinessApplication","programmingLanguage":"natural-language",
-    "description":`Connect ${c.name} to Commerce Claw and run actions with natural-language commands.`
+    "description":`Connect ${c.name} to VenturaClaw and run actions with natural-language commands.`
   };
   return _shell({
-    title: `${c.name} integration — Commerce Claw`,
-    desc: `Connect ${c.name} to Commerce Claw. Type "${exs[0]}" and the AI routes it. ${c.triggers} triggers · ${c.actions} actions${c.sensitive ? ' · sensitive actions gated by approval' : ''}.`,
+    title: `${c.name} integration — VenturaClaw`,
+    desc: `Connect ${c.name} to VenturaClaw. Type "${exs[0]}" and the AI routes it. ${c.triggers} triggers · ${c.actions} actions${c.sensitive ? ' · sensitive actions gated by approval' : ''}.`,
     canonical: `https://${DOMAIN}/connectors/${c.id}`,
     jsonLd: ld,
     body: `
@@ -789,7 +797,7 @@ function _renderConnectorPage(c) {
         </ul>
 
         <h2>How it works</h2>
-        <p>Type one of those sentences (or anything similar) on the <a href="/" style="color:var(--gold)">Commerce Claw homepage</a>. The local LLM detects intent and routes to <strong>${esc(c.name)}</strong>. ${c.sensitive ? 'Because writes to ' + esc(c.name) + ' are sensitive, the action lands in your approval queue with the parsed intent shown in plain English — you confirm before anything actually happens.' : 'Read-only actions execute immediately. Writes go through the approval queue.'}</p>
+        <p>Type one of those sentences (or anything similar) on the <a href="/" style="color:var(--gold)">VenturaClaw homepage</a>. The local LLM detects intent and routes to <strong>${esc(c.name)}</strong>. ${c.sensitive ? 'Because writes to ' + esc(c.name) + ' are sensitive, the action lands in your approval queue with the parsed intent shown in plain English — you confirm before anything actually happens.' : 'Read-only actions execute immediately. Writes go through the approval queue.'}</p>
 
         <h2>Auth</h2>
         <p>${c.auth === 'oauth2' ? `Connect ${esc(c.name)} via one-click OAuth at <a href="/login" style="color:var(--gold)">sign-in</a> → My Connections.` : `Paste your ${esc(c.name)} API key at sign-in → My Connections. Keys are AES-256-GCM encrypted at rest with a versioned envelope.`}</p>
@@ -851,7 +859,7 @@ h2 { font-family: var(--serif); font-weight: 500; font-size: 26px; margin: 40px
 </header>
 ${body}
 <footer style="max-width:1180px;margin:60px auto 0;padding:28px;border-top:1px solid var(--rule);font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-mute);display:flex;justify-content:space-between;flex-wrap:wrap;gap:18px">
-  <span>Commerce Claw · ${esc(DOMAIN)}</span>
+  <span>VenturaClaw · ${esc(DOMAIN)}</span>
   <span style="display:flex;gap:18px;flex-wrap:wrap">
     <a href="/connectors" style="color:var(--ink-soft);text-decoration:none">Connectors</a>
     <a href="/about" style="color:var(--ink-soft);text-decoration:none">About</a>
@@ -873,8 +881,8 @@ app.get("/connectors", (req, res) => {
 // through the same _shell template so design stays consistent.
 function _renderTextPage(title, eyebrow, h1, blocks) {
   return _shell({
-    title: `${title} — Commerce Claw`,
-    desc: `${title} for Commerce Claw — businessclaw.agentabrams.com.`,
+    title: `${title} — VenturaClaw`,
+    desc: `${title} for VenturaClaw — businessclaw.agentabrams.com.`,
     canonical: `https://${DOMAIN}/${title.toLowerCase()}`,
     body: `
       <main class="page page-narrow">
@@ -899,11 +907,11 @@ app.get("/privacy", (req, res) => {
 });
 app.get("/terms", (req, res) => {
   res.type("html").send(_renderTextPage("Terms", "Terms of use", `Plain-English <em>terms.</em>`, [
-    `Commerce Claw is provided as-is. The agent routes commands to vendor APIs that you've connected. You are responsible for the actions you authorize — including refunds, posts, DNS changes, and anything else with real-world consequences.`,
+    `VenturaClaw is provided as-is. The agent routes commands to vendor APIs that you've connected. You are responsible for the actions you authorize — including refunds, posts, DNS changes, and anything else with real-world consequences.`,
     `<strong>Sensitive actions are gated.</strong> Writes (refunds, posts, DNS edits, deletions) land in an approval queue with the parsed intent shown in plain English. Nothing actually happens until you approve. We strongly recommend reading what you're approving before clicking.`,
     `<strong>No fee-splitting, no commissions.</strong> We do not take a cut of any transactions you run through connected vendors. Your relationship with Stripe, Shopify, etc. is direct.`,
     `<strong>Acceptable use.</strong> Don't use this to spam, harass, defraud, or violate the terms of any connected vendor. We reserve the right to revoke access for misuse.`,
-    `<strong>Liability.</strong> To the maximum extent permitted by law, Commerce Claw is not liable for damages resulting from agent-routed actions, vendor outages, or LLM misclassification. Always review approval-queue items before approving.`,
+    `<strong>Liability.</strong> To the maximum extent permitted by law, VenturaClaw is not liable for damages resulting from agent-routed actions, vendor outages, or LLM misclassification. Always review approval-queue items before approving.`,
     `By signing in, you accept these terms.`,
   ]));
 });
@@ -912,7 +920,7 @@ app.get("/faq", (req, res) => {
     ["Where do my API keys actually live?", "On disk, AES-256-GCM encrypted with a versioned key envelope (key_id rotation supported). The encryption key is derived from a server-side secret loaded only at boot and never logged. Plaintext leaves memory the moment it's saved."],
     ["Does the AI ever see my full data?", "The local LLM only sees your <em>command</em> (e.g. \"refund order 1234 on Shopify\") to pick a connector and parse arguments. It never sees vendor responses or other connectors' data. Routing runs on Steve's hardware — no third-party LLM API."],
     ["What if the AI picks the wrong tool?", "Sensitive actions (refunds, posts, DNS edits, deletions) land in an approval queue with the parsed intent shown in plain English. Read it, approve or reject. Reads execute immediately because they don't change state."],
-    ["How does this differ from Zapier or Make?", "Those are workflow builders — you wire triggers to actions on a canvas, then maintain the wires. Commerce Claw is the opposite: type one sentence, the AI picks the connector. No canvas, no Zaps to maintain, no per-task pricing."],
+    ["How does this differ from Zapier or Make?", "Those are workflow builders — you wire triggers to actions on a canvas, then maintain the wires. VenturaClaw is the opposite: type one sentence, the AI picks the connector. No canvas, no Zaps to maintain, no per-task pricing."],
     ["What's the pricing?", "Free during early access. Eventual model is a flat workspace fee — no per-task metering, no credit math. Pricing changes will give 30 days notice; your audit log + connector registrations are exportable on the way out."],
     ["Can I self-host?", `Not yet packaged for distribution. Architecture is one Node process + JSON store + local Ollama, so it lifts cleanly. Email <a href="mailto:${SUPPORT_EMAIL}" style="color:var(--gold)">${SUPPORT_EMAIL}</a> for the Docker recipe.`],
     ["What if I want a connector that's not in the 56?", "Most modern SaaS speak OAuth2 + REST and slot in cleanly — new connectors typically ship in 1-3 days. Anything that exposes a webhook can be wired the same week."],
@@ -926,8 +934,8 @@ app.get("/faq", (req, res) => {
     })),
   };
   res.type("html").send(_shell({
-    title: "FAQ — Commerce Claw",
-    desc: "How Commerce Claw handles your API keys, what the AI sees, how sensitive actions are gated, and how it compares to Zapier/Make.",
+    title: "FAQ — VenturaClaw",
+    desc: "How VenturaClaw handles your API keys, what the AI sees, how sensitive actions are gated, and how it compares to Zapier/Make.",
     canonical: `https://${DOMAIN}/faq`,
     jsonLd: ld,
     body: `
@@ -1020,8 +1028,8 @@ set-cookie: cc_session=…; HttpOnly; Secure; SameSite=Lax
     },
   ];
   res.type("html").send(_shell({
-    title: "API docs — Commerce Claw",
-    desc: "5 curl examples covering the public + authenticated API surface for Commerce Claw — the AI agent that routes commands across 56 SaaS connectors.",
+    title: "API docs — VenturaClaw",
+    desc: "5 curl examples covering the public + authenticated API surface for VenturaClaw — the AI agent that routes commands across 56 SaaS connectors.",
     canonical: `https://${DOMAIN}/docs`,
     body: `
       <main class="page page-narrow">
@@ -1091,8 +1099,8 @@ const CHANGELOG = [
 ];
 app.get("/changelog", (req, res) => {
   res.type("html").send(_shell({
-    title: "Changelog — Commerce Claw",
-    desc: "Daily progress log for Commerce Claw. What shipped, when, and why it matters.",
+    title: "Changelog — VenturaClaw",
+    desc: "Daily progress log for VenturaClaw. What shipped, when, and why it matters.",
     canonical: `https://${DOMAIN}/changelog`,
     body: `
       <main class="page page-narrow">
@@ -1125,17 +1133,47 @@ app.get("/feed", (req, res) => {
     </item>`).join("");
   res.type("application/rss+xml").send(`<?xml version="1.0" encoding="UTF-8"?>
 <rss version="2.0"><channel>
-  <title>Commerce Claw · changelog</title>
+  <title>VenturaClaw · changelog</title>
   <link>https://${DOMAIN}/changelog</link>
-  <description>What shipped on Commerce Claw, in reverse chronological order.</description>
+  <description>What shipped on VenturaClaw, in reverse chronological order.</description>
   <language>en-us</language>
   ${items}
 </channel></rss>`);
 });
 
+app.get("/pricing", (req, res) => {
+  res.type("html").send(_shell({
+    title: "Pricing — VenturaClaw",
+    desc: "VenturaClaw pricing. Currently free during early access. Eventual model is a flat workspace fee — no per-task metering, no credit math.",
+    canonical: `https://${DOMAIN}/pricing`,
+    body: `
+      <main class="page page-narrow">
+        <div class="eyebrow">Pricing · honest answer</div>
+        <h1>Free <em>now.</em><br>Flat fee <em>later.</em></h1>
+        <p style="font-family:var(--mono);font-size:13px;line-height:1.7;color:var(--ink-soft);margin:0 0 36px;max-width:64ch">No per-task metering. No credit math. No surprise bills when your workflow gets popular. The eventual model is a flat workspace fee. The current model is zero — we want feedback more than revenue right now.</p>
+        <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px;margin-bottom:42px">
+          <div style="background:var(--bg-elevated);border:1px solid var(--gold);border-left:3px solid var(--gold);border-radius:4px;padding:24px 26px">
+            <div style="font-family:var(--mono);font-size:9px;letter-spacing:.18em;text-transform:uppercase;color:var(--gold);margin-bottom:8px">Today · Early access</div>
+            <div style="font-family:var(--serif);font-size:42px;font-style:italic;color:var(--ink);line-height:1;margin-bottom:14px">Free</div>
+            <ul style="font-family:var(--mono);font-size:11px;line-height:1.85;color:var(--ink-soft);padding-left:18px;margin:0"><li>56 connectors pre-wired</li><li>Local LLM routing (qwen3:14b)</li><li>Sensitive-action approval queue</li><li>AES-256-GCM at-rest token vault</li><li>Audit log · all events</li><li>Email support — <a href="mailto:${esc(SUPPORT_EMAIL)}" style="color:var(--gold)">${esc(SUPPORT_EMAIL)}</a></li></ul>
+          </div>
+          <div style="background:var(--bg-elevated);border:1px solid var(--rule);border-radius:4px;padding:24px 26px;opacity:0.78">
+            <div style="font-family:var(--mono);font-size:9px;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-mute);margin-bottom:8px">Eventual · TBD</div>
+            <div style="font-family:var(--serif);font-size:42px;font-style:italic;color:var(--ink-soft);line-height:1;margin-bottom:14px">Flat <span style="font-size:16px;color:var(--ink-mute)">/ workspace</span></div>
+            <ul style="font-family:var(--mono);font-size:11px;line-height:1.85;color:var(--ink-soft);padding-left:18px;margin:0"><li>No per-task fees · no Zap quotas</li><li>No credit metering on AI routing</li><li>Predictable bill regardless of volume</li><li>30 days notice before any pricing change</li><li>Audit log + connector registrations exportable on cancel</li></ul>
+          </div>
+        </div>
+        <h2 style="font-family:var(--serif);font-size:24px;margin:0 0 14px">Why not per-task?</h2>
+        <p style="font-family:var(--mono);font-size:12px;line-height:1.8;color:var(--ink-soft);margin:0 0 20px">Zapier charges per task. Make charges per operation. Bardeen meters credits at 3 per row. The math punishes you for being successful — your ops cost scales linearly with traffic, even though the marginal cost of routing a command is essentially electricity.</p>
+        <p style="font-family:var(--mono);font-size:12px;line-height:1.8;color:var(--ink-soft);margin:0 0 20px">We run inference on local hardware. The marginal cost of routing your 10,000th command this month is the same as your first. Pricing should reflect that — flat workspace fee, predictable, doesn't punish growth.</p>
+        <p style="margin-top:42px;font-family:var(--mono);font-size:11px;color:var(--ink-mute)">Questions? Email <a href="mailto:${esc(SUPPORT_EMAIL)}" style="color:var(--gold)">${esc(SUPPORT_EMAIL)}</a>.</p>
+      </main>`
+  }));
+});
+
 app.get("/about", (req, res) => {
   res.type("html").send(_renderTextPage("About", "About this project", `Built by <em>Steve.</em>`, [
-    `Commerce Claw is built and operated by Steve Abrams. It exists because every workflow-builder I tried — Zapier, Make, n8n — felt like more work than the work it was supposed to replace. Drag, wire, debug, maintain. The actual job (refund this, post that) is one sentence; the canvas was a tax.`,
+    `VenturaClaw is built and operated by Steve Abrams. It exists because every workflow-builder I tried — Zapier, Make, n8n — felt like more work than the work it was supposed to replace. Drag, wire, debug, maintain. The actual job (refund this, post that) is one sentence; the canvas was a tax.`,
     `So this tool sells the outcome, not the canvas. You type what you want; the local LLM picks the connector and runs it. 56 connectors are pre-wired. Sensitive actions are gated by approval. Tokens are encrypted at rest. Your business commands are routed through a self-hosted model — not a third-party API.`,
     `If you want to talk shop, reach me at <a href="mailto:${esc(SUPPORT_EMAIL)}" style="color:var(--gold)">${esc(SUPPORT_EMAIL)}</a>.`,
   ]));
@@ -1143,7 +1181,7 @@ app.get("/about", (req, res) => {
 app.get("/connectors/:id", (req, res) => {
   const c = _connectorsBy[req.params.id];
   if (!c) return res.status(404).type("html").send(_shell({
-    title: "Connector not found — Commerce Claw",
+    title: "Connector not found — VenturaClaw",
     desc: "That connector slug isn't in the catalog. Browse all 56 at /connectors.",
     canonical: `https://${DOMAIN}/connectors`,
     body: `<main class="page"><h1>Not <em>found.</em></h1><p class="lede">That connector isn't in the catalog. <a href="/connectors" style="color:var(--gold)">Browse all 56 →</a></p></main>`
@@ -1795,10 +1833,42 @@ app.post("/api/chat", requireAuth, async (req, res) => {
     const summary = await LLM.summarizeResult(message, out.toolCalls);
     if (summary) out.reply = summary;
   }
+  // Persist to per-user chat history
+  pushChat(req.session.sub, { role: "user", text: message });
+  pushChat(req.session.sub, { role: "assistant", text: out.reply, toolCalls: out.toolCalls });
+  save("chat-history", chatHistory);
   logEvent({ kind:"chat", userId: req.session.sub, message: message.slice(0,140), toolCalls: out.toolCalls.length });
   res.json(out);
 });
 
+// Chat history per user — read for restore-on-mount, delete to clear conversation.
+app.get("/api/chat/history", requireAuth, (req, res) => {
+  const limit = Math.min(parseInt(req.query.limit, 10) || 100, 200);
+  const list = chatHistory[req.session.sub] || [];
+  res.json({ messages: list.slice(-limit), total: list.length });
+});
+// Frequent commands: top-N of this user's actual chat phrases (case-insensitive, normalized).
+app.get("/api/chat/frequent", requireAuth, (req, res) => {
+  const list = chatHistory[req.session.sub] || [];
+  const counts = {};
+  for (const m of list) {
+    if (m.role !== "user") continue;
+    const norm = (m.text || "").trim().toLowerCase();
+    if (norm.length < 6 || norm.length > 200) continue;
+    counts[norm] = (counts[norm] || 0) + 1;
+  }
+  const top = Object.entries(counts).sort((a, b) => b[1] - a[1]).slice(0, 5)
+    .map(([text, count]) => ({ text, count }));
+  res.json({ top });
+});
+
+app.delete("/api/chat/history", requireAuth, (req, res) => {
+  delete chatHistory[req.session.sub];
+  save("chat-history", chatHistory);
+  logEvent({ kind: "chat_history_cleared", userId: req.session.sub });
+  res.json({ ok: true });
+});
+
 // approvals API
 app.get("/api/approvals", requireAuth, (req, res) => {
   const list = req.session.role === "admin" ? approvals : approvals.filter(a => a.userId === req.session.sub);
@@ -1906,8 +1976,8 @@ app.use((req, res) => {
     return res.status(404).json({ error: "not_found", path: req.path });
   }
   res.status(404).type("html").send(_shell({
-    title: "Not found — Commerce Claw",
-    desc: "That page doesn't exist on Commerce Claw.",
+    title: "Not found — VenturaClaw",
+    desc: "That page doesn't exist on VenturaClaw.",
     canonical: `https://${DOMAIN}/`,
     body: `
       <main class="page page-narrow" style="text-align:center;padding-top:120px">
@@ -1923,7 +1993,7 @@ app.use((req, res) => {
 });
 
 app.listen(PORT, HOST, () => {
-  console.log(`[commerce-claw] listening on http://${HOST}:${PORT} (public: ${DOMAIN})`);
+  console.log(`[ventura-claw] listening on http://${HOST}:${PORT} (public: ${DOMAIN})`);
   // Pre-warm the LLM (Mac1 + Mac2 fallback if configured) so the first visitor
   // doesn't pay a cold-load. Then prime the demo cache by classifying the 5 preset
   // queries — same warm window, so all 5 finish in seconds and are cached for 10min.
@@ -1958,8 +2028,8 @@ app.listen(PORT, HOST, () => {
         }
       } catch { /* skip on failure, keep going */ }
     }
-    console.log(`[commerce-claw] primed demo cache with ${primed}/${presets.length} preset queries`);
-  })().catch(e => console.warn(`[commerce-claw] cache prime failed: ${e.message}`));
+    console.log(`[ventura-claw] primed demo cache with ${primed}/${presets.length} preset queries`);
+  })().catch(e => console.warn(`[ventura-claw] cache prime failed: ${e.message}`));
 
   // Periodic keep-alive ping — re-warms qwen3 every 25 minutes if it's been idle,
   // so a visitor showing up after a quiet hour doesn't pay the cold-load penalty.
diff --git a/server/tests/integration.test.js b/server/tests/integration.test.js
index 16fd811..caaf3f1 100644
--- a/server/tests/integration.test.js
+++ b/server/tests/integration.test.js
@@ -1,5 +1,5 @@
 #!/usr/bin/env node
-// Commerce Claw — integration tests (bare node + assert, no test runner)
+// VenturaClaw — integration tests (bare node + assert, no test runner)
 // Target: http://127.0.0.1:9788 (pm2: commerce-claw)
 // Run: node tests/integration.test.js
 
@@ -66,7 +66,7 @@ async function test(name, fn) {
 // ---------------------------------------------------------------------------
 
 (async () => {
-  console.log("\nCommerce Claw — integration test suite");
+  console.log("\nVenturaClaw — integration test suite");
   console.log("=======================================\n");
 
   // ------------------------------------------------------------------
@@ -268,7 +268,7 @@ async function test(name, fn) {
   // 9. canonical-secrets allowlist: unrelated keys must NOT be in process.env
   // ------------------------------------------------------------------
   await test("canonical-secrets allowlist: unrelated env keys are undefined in process.env", () => {
-    // These keys exist in the master secrets-manager .env but are NOT in Commerce Claw's ALLOW set.
+    // These keys exist in the master secrets-manager .env but are NOT in VenturaClaw's ALLOW set.
     // Verifying here exercises the allowlist loader that runs at server boot — if any of these
     // leaked into process.env the allowlist filter is broken.
     //
diff --git a/viewer/public/app.js b/viewer/public/app.js
index 50db07e..9f2708a 100644
--- a/viewer/public/app.js
+++ b/viewer/public/app.js
@@ -1,4 +1,4 @@
-// Commerce Claw — Live Build Viewer
+// VenturaClaw — Live Build Viewer
 // Connector tiles, phase tracker, SSE event stream
 
 const PHASES = [
diff --git a/viewer/public/index.html b/viewer/public/index.html
index dab18d6..f0aa626 100644
--- a/viewer/public/index.html
+++ b/viewer/public/index.html
@@ -3,7 +3,7 @@
 <head>
 <meta charset="utf-8" />
 <meta name="viewport" content="width=device-width,initial-scale=1" />
-<title>Commerce Claw — Live Build</title>
+<title>VenturaClaw — Live Build</title>
 <link rel="stylesheet" href="/style.css" />
 </head>
 <body>
@@ -15,7 +15,7 @@
   <div class="brand">
     <div class="logo-dot"></div>
     <div>
-      <div class="brand-name">Commerce Claw</div>
+      <div class="brand-name">VenturaClaw</div>
       <div class="brand-sub">Live Build · :9785</div>
     </div>
   </div>
diff --git a/viewer/public/style.css b/viewer/public/style.css
index 1a5d55d..22109c9 100644
--- a/viewer/public/style.css
+++ b/viewer/public/style.css
@@ -1,4 +1,4 @@
-/* Commerce Claw — Liquid Glass / Web 4.0 viewer */
+/* VenturaClaw — Liquid Glass / Web 4.0 viewer */
 :root {
   --bg: #0a0e1a;
   --bg-2: #1a1330;
diff --git a/viewer/server.js b/viewer/server.js
index 6262e30..d74ac73 100755
--- a/viewer/server.js
+++ b/viewer/server.js
@@ -1,5 +1,5 @@
 #!/usr/bin/env node
-// Commerce Claw — Live Build Viewer
+// VenturaClaw — Live Build Viewer
 // Streams build-events.jsonl via SSE; serves liquid-glass UI on :9785
 
 const http = require('http');

← ee0bbe0 Launch comms drafts + og-cover.png raster + linter brand pol  ·  back to Ventura Claw  ·  Purge remaining businessclaw / commerce-claw refs across doc 5f60f03 →