Skip to content

Latest commit

Β 

History

History
363 lines (258 loc) Β· 17.3 KB

File metadata and controls

363 lines (258 loc) Β· 17.3 KB

WingmanAI β€” Design Document

App name: WingmanAI
AI persona name: Goose
Version: 1.0
Stack: Flutter macOS + thin Swift method channel
Philosophy: Ambient, proactive, thermally respectful, 100% local by default


What WingmanAI Is

WingmanAI is a macOS desktop overlay app powered entirely by local AI inference. Its AI persona β€” Goose β€” watches your screen, understands what you are doing in any app, and surfaces proactive advice without you having to ask. When Goose wants to act on your behalf, it proposes an action and waits for your approval. You can talk to Goose directly by voice or text at any time.

Named after Goose from Top Gun β€” always watching your back, speaking up when it matters, executing when asked.

Nothing leaves your Mac. Ever.


Core Design Principles

  1. Ambient over reactive β€” Goose watches and speaks up. You don't have to go to it.
  2. Thermally respectful β€” inference only fires when the screen meaningfully changes. The GPU rests between captures.
  3. Human in control β€” every action Goose wants to take requires explicit approval. No surprises.
  4. Local first β€” bundled Ollama, bundled models, zero cloud dependency by default. Frontier models are an optional opt-in.
  5. Hookable β€” every major subsystem is behind an interface. Swap LLaVA for a better vision model, serial inference for parallel inference, stub features for real ones β€” without touching the rest of the codebase.

The Overlay

Goose lives in a compact always-on-top floating panel in your chosen screen corner (default: upper-right). It is always visible β€” on top of every other window, translucent by default, small enough to be unobtrusive.

Two States

Compact card β€” always visible, ~300px wide:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ πŸͺΏ WingmanAI    β–Ά ⏸ ⏹   πŸ‘οΈ  πŸ”•  βš™οΈ  β”‚
β”‚ ─────────────────────────────────────── β”‚
β”‚ Looks like you're writing an email.     β”‚
β”‚ The subject line could be sharper.      β”‚
β”‚ [✏️ Fix it]  [πŸ’‘ Explain]  [Dismiss]   β”‚
β”‚ ─────────────────────────────────────── β”‚
β”‚ 🧠 14K/128K β–ˆβ–ˆβ–ˆβ–ˆβ–‘  RAM 38G  CPU 12%    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Expanded chat β€” full interactive panel, tap anywhere to open:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ πŸͺΏ WingmanAI    β–Ά ⏸ ⏹   πŸ‘οΈ  πŸ”•  βš™οΈ βœ•β”‚
β”‚ ─────────────────────────────────────── β”‚
β”‚ [scrollable conversation history]       β”‚
β”‚                                         β”‚
β”‚ πŸͺΏ Goose: The subject line...           β”‚
β”‚ πŸ‘€ You: Rewrite it                      β”‚
β”‚ 🌩️ Claude: Here's a sharper version... β”‚
β”‚                                         β”‚
β”‚ ─────────────────────────────────────── β”‚
β”‚ [────── say anything ──────] 🎀 Send   β”‚
β”‚ ─────────────────────────────────────── β”‚
β”‚ 🧠 14K/128K  RAM 38G  CPU 12%  GPU 48% β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Transport Controls β€” Play / Pause / Stop

Three always-visible buttons in the compact card header. These are the most important controls in the app β€” they let the user manage Goose's resource consumption at any moment.

Button Color State What happens
β–Ά Play Green Active Screen watching runs, inference enabled, models loaded in GPU RAM
⏸ Pause Amber Paused Capture stops, inference queue freezes, models stay loaded β€” instant resume
⏹ Stop Red Stopped Everything halts, models explicitly unloaded from VRAM β€” full resource release

Pause vs Stop is the critical distinction:

  • Pause keeps models warm in GPU RAM. Resuming takes milliseconds. Use it for a quick break.
  • Stop evicts models from memory entirely via OllamaClient.unloadModel(). Resuming takes several seconds while models reload. Use it when you need GPU RAM for something else β€” video editing, gaming, a heavy build.

State persists across app restarts. If Goose was paused when you quit, it opens paused.


Focus Awareness

The two highest-leverage features in WingmanAI β€” telling Goose exactly where your attention is.

Mouse Position

Goose tracks NSEvent.mouseLocation continuously. When it analyzes a screenshot, it knows where your cursor is and treats that screen region as the highest-priority area. A terminal pane you're hovering over matters more than the browser window behind it.

Text Selection β€” The Key Feature

When you highlight text anywhere on screen, Goose immediately:

  1. Reads the exact selected text via AXSelectedText (Accessibility API β€” no OCR, exact characters)
  2. Understands the context β€” which app, what type of content, your conversation history, your active project, your memory
  3. Reasons about what you most likely want β€” generates contextually intelligent suggestions using Granite
  4. Surfaces a selection action card in the overlay

The suggestions are not hardcoded buttons β€” Granite generates them based on everything it knows about what you've been doing. The same text highlighted in different contexts produces completely different suggestions:

  • Highlighted in Mail while discussing a client proposal β†’ "Rewrite formally", "Convert to action item", "Flag as blocker"
  • Highlighted in Xcode while debugging β†’ "Explain this code", "Find the bug", "Write a unit test"
  • Highlighted in Terminal β†’ "Explain this error", "Suggest a fix", "Search for this"
  • Highlighted in Safari β†’ "Summarize this", "Fact-check this", "Save to memory"

A free-text input is always present so you can ask anything beyond what Goose suggested.

When you approve an action, Goose rewrites the text and injects it back in-place β€” the selection is replaced in whatever app you're in, without you leaving it. The diff view shows old vs new before injection is confirmed.

Text injection methods:

  • Primary: app-specific AppleScript (tell application "Mail" to set selected text...)
  • Universal fallback: keyboard simulation via CGEventPost (type over active selection)

This feature requires Accessibility permission β€” requested and explained at first launch.


AI Models

Default Configuration

Role Model RAM Context
Vision (screen reading) llava:7b ~4.7GB β€”
Reasoning (chat, advice, tools) granite3.1-dense:8b ~5GB 128K tokens

Both models are downloaded at first launch. Both are user-configurable. Both ship via the bundled Ollama runtime β€” no external installation required.

VisionProvider β€” Swappable by Design

The vision layer sits behind a VisionProvider abstract interface. Swapping LLaVA for a better model requires implementing one class. No other code changes.

VisionProvider (abstract)
    OllamaVisionProvider    ← default, llava:7b
    MoondreamProvider       ← hook: ~1.7GB, faster for screen reading
    Qwen2VLProvider         ← hook: better quality
    FrontierVisionProvider  ← hook: GPT-4o Vision or Claude Vision

Near-term swap candidate: moondream2 β€” already on Ollama, significantly faster than LLaVA for screen reading specifically.

Frontier Model Escalation (Off by Default)

When local Granite isn't getting the job done, Goose can optionally escalate to a cloud frontier model. The user configures which providers to use, in what priority order, and how many times per minute escalation is allowed.

Providers: ChatGPT (GPT-4o), Claude (claude-opus-4), Grok (grok-3)
Failback chain: Provider 1 β†’ Provider 2 β†’ Provider 3 β†’ Granite silently
Attribution: "🌩️ Claude says:" vs "πŸͺΏ Goose says:" β€” always visible
API keys: Stored locally in AppSettings, never transmitted except to the provider


Screen Watching

Goose captures a screenshot every N seconds (configurable: 3/5/10/30s, default 5s). Before sending it to the vision model, a perceptual hash diff checks whether the screen has meaningfully changed. If not β€” no inference. The GPU stays cold.

Capture scope options:

  • Full screen
  • Active window only
  • User-defined region (draw a rectangle once, Goose watches only that area)

Privacy exclusions: User can list apps Goose never watches (e.g. 1Password, banking apps). If the frontmost app is on the exclusion list, capture is skipped entirely.

Vision transparency log: The last 20 captures are stored with Goose's conclusions. The user can open this log at any time to understand why Goose said what it said.


Session Continuity

Token Counter

Always visible in the performance strip:

🧠 14,203 / 128,000  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘  11%

Color shifts from green β†’ amber at 70% β†’ red at 90%.

Session Summary Files

When the context window fills (at 90% threshold), Goose:

  1. Writes a concise summary of the current session β€” not a transcript, a "state of the world" document similar to Bob's DESIGN.md and plan.md
  2. Starts a fresh context window
  3. Loads the most recent session files that fit within the token budget (most recent first)

One file per context window: gooseSession1-2025-07-14.md
Location: ~/Library/Application Support/WingmanAI/sessions/

The session file contains: what the user is working on, key context, what Goose has done, open threads, things Goose has learned. The user can read and edit these files directly.


Task Queue

v1 β€” Parallel I/O, Sequential Inference

Multiple tasks run simultaneously. All I/O (web searches, file reads, shell commands) executes in parallel. Inference is serialized β€” one at a time, queued. This gives the feel of concurrent work with zero thermal penalty.

Future β€” Parallel Inference (Hook)

ParallelTaskScheduler is built in v1 but hidden behind a settings flag. When the user enables frontier cloud models (no thermal concern) or on more powerful future hardware, they unlock it in Advanced Settings. No code changes β€” one configuration flag.


Performance Monitor

Always visible in the compact overlay. Single line in compact mode, full panel in expanded mode.

Compact:

🧠 14K/128K  RAM 38G  CPU 12%  GPU 48%

Expanded: Progress bars for context, RAM, CPU, GPU + Ollama status + which models are loaded.

Auto-throttle: When CPU or GPU hits the red threshold, Goose automatically increases the capture interval. The user sees a small warning and can override.


Web Search

Goose can search the web and fetch URLs as part of its reasoning β€” reused directly from deepThinkER.

  • [SEARCH: query] β†’ DuckDuckGo HTML endpoint
  • [FETCH: url] β†’ direct URL fetch
  • Rate limited (configurable, default 10/min)
  • Results injected into Granite's context automatically
  • Shown as collapsible "πŸ” Searched:" cards in the chat

Proactive research mode: Tell Goose to research something while you keep working. It runs background searches via the deepThinkER ResearchEngine pattern and surfaces a result card when done.


Action Execution

Goose can execute shell commands and control other apps via AppleScript β€” with your approval on every action.

Approval gate: Every proposed action appears as an approval card in the overlay before executing. You tap Approve or Deny. Approved actions are logged to the audit log.

Shell execution: Process.run β€” proven pattern from deepThinkER
AppleScript: Process.run('osascript', ['-e', script]) β€” controls any AppleScript-aware app
Keyboard simulation: CGEventPost β€” universal fallback for apps without AppleScript support

Requires Accessibility permission β€” requested at first launch with guided setup.


Memory and Profiles

Persistent memory: Goose remembers facts across sessions β€” your preferences, your projects, things you've told it. Reused from deepThinkER's MemoryStore.

Project profiles: Save a named context bundle β€” project folder + pinned files + persona prompt + model overrides. Switch profiles with one tap in the compact overlay.

Auto-learn: Dismissals and thumbs-down are stored in memory and adjust future advice. Consistent thumbs-down on a category can trigger automatic frontier escalation for that category.


Voice

Full two-way voice β€” Goose speaks and listens.

  • Speech β†’ Text: macOS SFSpeechRecognizer β€” 50+ languages, offline-capable
  • Text β†’ Speech: macOS AVSpeechSynthesizer β€” neural voices, user picks in Settings
  • Global hotkey: Press βŒ˜β‡§Space (configurable) to activate voice input from anywhere
  • Wake word: "Hey Goose" β€” on/off toggle
  • Both directions independently toggleable in Settings

First Launch Flow

1. Splash screen β€” bundled Ollama starts, live status
2. Hardware detection β€” RAM tier, GPU backend
3. Model download β€” llava:7b + granite3.1-dense:8b with progress bars
4. Permissions β€” Screen Recording + Accessibility guided setup with System Settings deep links
5. Corner picker β€” choose where Goose lives
6. Persona picker β€” Developer / Writer / Executive / Default presets
7. Interactive tutorial β€” how to summon, approve actions, use voice
8. Goose activates β€” introduces itself by voice and text

Settings Overview

Category Settings
Window Corner (4 options), opacity, free drag
Models Reasoning model, vision model, model management
Screen Capture interval, capture scope, region selector, privacy exclusions
Voice Input on/off, output on/off, language, voice, hotkey, wake word
Search On/off, rate cap
Frontier On/off, API keys, priority order, throttle, auto-escalate triggers
Context Pinned files, folder, RAG folder
Session Quiet hours, DND, Focus mode
Persona Prompt editor, preset picker
Advanced Task concurrency (hidden v1), thermal override, update check
Accessibility Font size, sound cues

Reliability

  • LaunchAgent: WingmanAI auto-restarts on crash β€” installed at first launch
  • Crash recovery: State snapshot written before each inference β€” resumable on next launch
  • Audit log: Every tool execution logged with timestamp, tool, argument, result, approval status
  • Local-only badge: Visible indicator in the overlay confirming nothing has left your Mac
  • Update check: Version check on launch, notification + GitHub link if newer version available

Competitive Position

WingmanAI occupies a position no other tool currently holds:

Tool What it is Screen watching Proactive Local
Ollama Inference runtime ❌ ❌ βœ…
Jan.ai Local chat UI ❌ ❌ βœ…
LM Studio Local model runner + dev API ❌ ❌ βœ…
Unsloth Model training platform ❌ ❌ βœ…
OpenClaw Messaging gateway ❌ ❌ ❌ needs API keys
WingmanAI Ambient desktop AI βœ… βœ… βœ…

Every other tool is reactive β€” you go to them. WingmanAI comes to you. That is the moat.

For a full competitive analysis including OpenClaw deep-dive, see PLAN.md Section 3.


Technical Stack

WingmanAI.app
β”œβ”€β”€ Swift (~200 lines)
β”‚   β”œβ”€β”€ NSWindow floating + corner snap + opacity
β”‚   β”œβ”€β”€ SFSpeechRecognizer + AVSpeechSynthesizer
β”‚   β”œβ”€β”€ NSWorkspace active app detection
β”‚   β”œβ”€β”€ NSEvent mouse location stream
β”‚   β”œβ”€β”€ AXSelectedText accessibility polling
β”‚   β”œβ”€β”€ CGEventPost text injection
β”‚   └── FlutterMethodChannel bridge
β”‚
└── Dart / Flutter (all business logic)
    β”œβ”€β”€ Bundled Ollama runtime
    β”œβ”€β”€ VisionProvider (abstract, LLaVA default)
    β”œβ”€β”€ ReasoningEngine (Granite + tools)
    β”œβ”€β”€ ScreenWatcher + PerceptualHasher
    β”œβ”€β”€ FocusChannel (mouse + selection)
    β”œβ”€β”€ SelectionDetector + SelectionActionCard
    β”œβ”€β”€ GooseStateManager (Play/Pause/Stop)
    β”œβ”€β”€ TaskScheduler (serial v1, parallel hook)
    β”œβ”€β”€ FrontierClient (OpenAI + Anthropic + xAI)
    β”œβ”€β”€ NetworkFetcher + ResearchEngine (reused)
    β”œβ”€β”€ MemoryStore + ProjectProfiles (reused)
    β”œβ”€β”€ SessionSummaryWriter + SessionLoader
    β”œβ”€β”€ ResourceMonitor + ThermalGuard (reused)
    └── AuditLog (reused)

Reused directly from deepThinkER/deepThink: OllamaClient, OllamaLauncher, ModelManager, HardwareDetector, ResourceMonitor, NetworkFetcher, NetworkSearchTool, NetworkFetchTool, AgentTool framework, ToolRegistry, ToolCallInterceptor, FileReadTool, FileWriteTool, MemoryStore, AuditLog, ContextManager, ResearchEngine, AppSettings pattern, AppPaths pattern, entitlements, AppDelegate lifecycle.


Design document written by Bob. See PLAN.md for full implementation sub-tasks.