docs: ultra-detailed README with icon, badges, screenshots; MIT LICENSE; hardened .gitignore
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Showing 8 changed files with +644 and −38
modified
.gitignore
+68 −1
@@ -1,6 +1,73 @@ | ||
| 1 | +# | |
| 2 | +# .gitignore | |
| 3 | +# Zyquo Agent | |
| 4 | +# | |
| 5 | +# Author: Simon-Pierre Boucher | |
| 6 | +# Mail: contact@spboucher.ai | |
| 7 | +# | |
| 8 | + | |
| 9 | +# ---- Secrets (NEVER commit) ------------------------------------------------- | |
| 1 | 10 | .secrets/ |
| 11 | +*.env.keys | |
| 12 | +.env | |
| 13 | +.env.local | |
| 14 | +*.p12 | |
| 15 | +*.mobileprovision | |
| 16 | +AuthKey_*.p8 | |
| 17 | + | |
| 18 | +# ---- Swift Package Manager -------------------------------------------------- | |
| 2 | 19 | .build/ |
| 20 | +.swiftpm/ | |
| 21 | +*.xcframework | |
| 22 | + | |
| 23 | +# ---- Build products / distribution ----------------------------------------- | |
| 24 | +build/ | |
| 3 | 25 | dist/ |
| 26 | +DerivedData/ | |
| 27 | +*.dmg | |
| 28 | +*.o | |
| 29 | +*.dSYM/ | |
| 4 | 30 | *.icns.tmp |
| 5 | −.DS_Store | |
| 31 | + | |
| 32 | +# ---- Xcode (not used to build, but keep clones clean) ---------------------- | |
| 33 | +*.xcodeproj/xcuserdata/ | |
| 34 | +*.xcworkspace/xcuserdata/ | |
| 35 | +*.xcuserstate | |
| 36 | +*.xcuserdatad/ | |
| 37 | +xcuserdata/ | |
| 38 | +*.xcscmblueprint | |
| 39 | +*.xccheckout | |
| 40 | +*.moved-aside | |
| 41 | +*.hmap | |
| 42 | +*.ipa | |
| 43 | +timeline.xctimeline | |
| 44 | +playground.xcworkspace | |
| 45 | + | |
| 46 | +# ---- Dependency managers --------------------------------------------------- | |
| 47 | +Pods/ | |
| 48 | +Carthage/Build/ | |
| 49 | +.netrc | |
| 50 | + | |
| 51 | +# ---- Tooling / caches ------------------------------------------------------ | |
| 6 | 52 | scripts/__pycache__/ |
| 53 | +__pycache__/ | |
| 54 | +*.pyc | |
| 55 | +.mypy_cache/ | |
| 56 | + | |
| 57 | +# ---- macOS ----------------------------------------------------------------- | |
| 58 | +.DS_Store | |
| 59 | +.DS_Store? | |
| 60 | +._* | |
| 61 | +.Spotlight-V100 | |
| 62 | +.Trashes | |
| 63 | +.AppleDouble | |
| 64 | +.LSOverride | |
| 65 | +Icon? | |
| 66 | +ehthumbs.db | |
| 67 | +Thumbs.db | |
| 68 | + | |
| 69 | +# ---- Editors --------------------------------------------------------------- | |
| 70 | +.idea/ | |
| 71 | +.vscode/ | |
| 72 | +*.swp | |
| 73 | +*~ | |
added
LICENSE
+21 −0
@@ -0,0 +1,21 @@ | ||
| 1 | +MIT License | |
| 2 | + | |
| 3 | +Copyright (c) 2026 Simon-Pierre Boucher | |
| 4 | + | |
| 5 | +Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 6 | +of this software and associated documentation files (the "Software"), to deal | |
| 7 | +in the Software without restriction, including without limitation the rights | |
| 8 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 9 | +copies of the Software, and to permit persons to whom the Software is | |
| 10 | +furnished to do so, subject to the following conditions: | |
| 11 | + | |
| 12 | +The above copyright notice and this permission notice shall be included in all | |
| 13 | +copies or substantial portions of the Software. | |
| 14 | + | |
| 15 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 18 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 19 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 20 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 21 | +SOFTWARE. | |
modified
README.md
+555 −37
@@ -1,61 +1,579 @@ | ||
| 1 | +<div align="center"> | |
| 2 | + | |
| 3 | +<img src="assets/icon.png" alt="Zyquo Agent" width="180" height="180"> | |
| 4 | + | |
| 1 | 5 | # Zyquo Agent |
| 2 | 6 | |
| 3 | −**Zyquo Agent** is the autonomous-agent member of the Zyquo family — a native macOS app | |
| 4 | −(Swift + SwiftUI, built with the Swift Package Manager, no Xcode IDE) that turns the same | |
| 5 | −cloud models as **Zyquo Cloud** into a deeply agentic assistant that can operate your Mac: | |
| 6 | −running `bash` commands and AppleScript, reading and writing files in per-task workspaces, | |
| 7 | −and iterating in a real plan→act→observe→reflect loop until the task is done — with | |
| 8 | −approvals, a risk-classifying policy gate, and a full audit log in front of every action. | |
| 7 | +### **The autonomous agent that actually operates your Mac.** | |
| 8 | + | |
| 9 | +*Plans. Runs real commands. Verifies its own work. Asks before anything risky.* | |
| 10 | + | |
| 11 | +<br> | |
| 12 | + | |
| 13 | +[](https://github.com/spboucher-ai/zyquo-agent/releases/latest) | |
| 14 | +[](https://www.apple.com/macos/) | |
| 15 | +[](https://swift.org) | |
| 16 | +[](LICENSE) | |
| 17 | + | |
| 18 | +[](https://github.com/spboucher-ai/zyquo-agent/releases) | |
| 19 | +[](#-installation) | |
| 20 | +[-7A5AF0?style=flat-square&labelColor=2E2A3A)](#-building-from-source) | |
| 21 | +[](#-providers--models) | |
| 22 | +[-9B82F6?style=flat-square&labelColor=2E2A3A)](docs/VERIFICATION.md) | |
| 23 | +[](docs/VERIFICATION.md) | |
| 24 | +[](docs/EVALUATION.md) | |
| 25 | +[](#-building-from-source) | |
| 26 | + | |
| 27 | +<br> | |
| 28 | + | |
| 29 | +**[⬇️ Download the DMG](https://github.com/spboucher-ai/zyquo-agent/releases/latest)** · **[📖 Docs](docs/)** · **[🔬 Verification report](docs/VERIFICATION.md)** · **[🧪 Evaluation report](docs/EVALUATION.md)** | |
| 30 | + | |
| 31 | +</div> | |
| 32 | + | |
| 33 | +<br> | |
| 34 | + | |
| 35 | +--- | |
| 36 | + | |
| 37 | +<br> | |
| 38 | + | |
| 39 | +## 📋 Table of Contents | |
| 40 | + | |
| 41 | +- [✨ What is Zyquo Agent?](#-what-is-zyquo-agent) | |
| 42 | +- [🖼️ Screenshots](#️-screenshots) | |
| 43 | +- [🚀 Features](#-features) | |
| 44 | + - [The agent engine](#the-agent-engine) | |
| 45 | + - [The tools it can actually use](#the-tools-it-can-actually-use) | |
| 46 | + - [Safety: the headline feature](#-safety-the-headline-feature) | |
| 47 | + - [Workspaces](#-workspaces) | |
| 48 | + - [Memory & context compaction](#-memory--context-compaction) | |
| 49 | + - [The command-center interface](#-the-command-center-interface) | |
| 50 | + - [Productivity](#-productivity) | |
| 51 | +- [🤖 Providers & Models](#-providers--models) | |
| 52 | +- [💾 Installation](#-installation) | |
| 53 | +- [⚙️ Requirements](#️-requirements) | |
| 54 | +- [📖 Usage](#-usage) | |
| 55 | + - [Your first task](#your-first-task) | |
| 56 | + - [Choosing a safety mode](#choosing-a-safety-mode) | |
| 57 | + - [Keyboard shortcuts](#keyboard-shortcuts) | |
| 58 | + - [The command-line interface](#the-command-line-interface) | |
| 59 | +- [🔨 Building from Source](#-building-from-source) | |
| 60 | +- [🏗️ Architecture](#️-architecture) | |
| 61 | +- [🔬 Verification & Evaluation](#-verification--evaluation) | |
| 62 | +- [🗺️ Roadmap](#️-roadmap) | |
| 63 | +- [🤝 Contributing](#-contributing) | |
| 64 | +- [📄 License](#-license) | |
| 65 | +- [👤 Author](#-author) | |
| 66 | + | |
| 67 | +<br> | |
| 68 | + | |
| 69 | +--- | |
| 70 | + | |
| 71 | +<br> | |
| 72 | + | |
| 73 | +## ✨ What is Zyquo Agent? | |
| 74 | + | |
| 75 | +**Zyquo Agent** is a native macOS app that turns cloud LLMs into an agent that *does things on your Mac* — it runs `bash` commands, drives other apps with AppleScript, reads and writes files, and keeps iterating until the task is genuinely done. | |
| 76 | + | |
| 77 | +It is not a chat window with a shell attached. It is a real **plan → act → observe → reflect** loop: | |
| 78 | + | |
| 79 | +``` | |
| 80 | +you describe a task | |
| 81 | + ↓ | |
| 82 | +the agent drafts a checklist → shown live in the Plan panel | |
| 83 | + ↓ | |
| 84 | +it calls a tool (bash / osascript / file ops) | |
| 85 | + ↓ | |
| 86 | +◆ every action passes a policy gate → risky ones stop and ask YOU | |
| 87 | + ↓ | |
| 88 | +it reads the actual result, revises the plan, and continues | |
| 89 | + ↓ | |
| 90 | +it verifies its own work with tools before declaring "done" | |
| 91 | +``` | |
| 92 | + | |
| 93 | +Everything is visible while it happens: streamed thinking, the exact command about to run, live `stdout`/`stderr`, exit codes, plan check-offs, token/time budgets — and an **append-only audit log** of every single action it took. | |
| 94 | + | |
| 95 | +Zyquo Agent is the agentic member of the **Zyquo** family (**Zyquo Cloud** — chat client · **Zyquo Local** — on-device models · **Zyquo Agent** — this). It reuses Cloud's provider layer and encrypted key vault, so your keys and model list feel identical across the family. | |
| 96 | + | |
| 97 | +> **Built entirely without the Xcode IDE** — Swift Package Manager and the command-line toolchain only. | |
| 98 | + | |
| 99 | +<br> | |
| 100 | + | |
| 101 | +--- | |
| 102 | + | |
| 103 | +<br> | |
| 104 | + | |
| 105 | +## 🖼️ Screenshots | |
| 106 | + | |
| 107 | +<div align="center"> | |
| 108 | + | |
| 109 | +### The command center at rest | |
| 110 | + | |
| 111 | +<img src="assets/screenshots/empty-state.png" alt="Zyquo Agent empty state" width="90%"> | |
| 112 | + | |
| 113 | +<br><br> | |
| 114 | + | |
| 115 | +### A real run: step cards, live terminal feed, budget meters | |
| 116 | + | |
| 117 | +<img src="assets/screenshots/live-run.png" alt="Zyquo Agent live run" width="90%"> | |
| 118 | + | |
| 119 | +*The agent wrote a file, then verified it with `list_dir` and `read_file` before answering. The drawer streams every action as it happens; the right panel tracks steps, tokens, and time against your budgets.* | |
| 120 | + | |
| 121 | +<br><br> | |
| 122 | + | |
| 123 | +### Safety settings: modes, boundaries, and your own allow/deny rules | |
| 124 | + | |
| 125 | +<img src="assets/screenshots/settings-safety.png" alt="Zyquo Agent safety settings" width="90%"> | |
| 126 | + | |
| 127 | +</div> | |
| 128 | + | |
| 129 | +<br> | |
| 130 | + | |
| 131 | +--- | |
| 132 | + | |
| 133 | +<br> | |
| 134 | + | |
| 135 | +## 🚀 Features | |
| 136 | + | |
| 137 | +### The agent engine | |
| 138 | + | |
| 139 | +| | | | |
| 140 | +|---|---| | |
| 141 | +| 🔄 **True agentic loop** | A `stop_reason`-keyed while-loop (`AgentLoop`, a Swift actor): stream a model turn → execute its tool calls → thread the results back → repeat until the model answers without calling tools. Handles truncation, refusals, and transient provider errors (one automatic retry with backoff). | | |
| 142 | +| 🧠 **Reasoning-model aware** | Thinking/reasoning tokens stream into a collapsible section, separate from the answer. | | |
| 143 | +| 📋 **Live editable plan** | The agent maintains a real checklist through an internal `update_plan` tool — items go pending → active → done/failed, persisted to `.zyquo/plan.json`, rendered in the Plan panel, and **editable by you** mid-run. | | |
| 144 | +| ♻️ **Re-planning on failure** | A failed step doesn't derail the run: the agent self-critiques, revises the plan, and continues. (Verified end-to-end: [scenario s6](docs/EVALUATION.md).) | | |
| 145 | +| 🛑 **LoopGuard** | Step / token / wall-clock budgets plus **repetition** detection (same failing call 3×) and **stall** detection (6 steps with no progress). On a trip it **pauses and asks you** — never silently spins or aborts. | | |
| 146 | +| ⚡ **Streaming everything** | Text, thinking, and even partial tool-call *arguments* stream live, so you watch the command being composed before it runs. | | |
| 147 | +| ⏹️ **Real cancellation** | ⌘. (or SIGINT on the CLI) cancels the model stream **and kills the running child process** (SIGTERM → SIGKILL), recording a `cancelled` outcome. Verified by test. | | |
| 9 | 148 | |
| 10 | −Sibling apps: **Zyquo Cloud** (chat client) · **Zyquo Local** (on-device models) · **Zyquo Agent** (this). | |
| 149 | +### The tools it can actually use | |
| 11 | 150 | |
| 12 | −## Requirements | |
| 151 | +| Tool | What it does | | |
| 152 | +|---|---| | |
| 153 | +| `bash` | Runs commands via `/bin/bash -lc` with the workspace as cwd. Line-by-line `stdout`/`stderr` streaming, per-command timeout, exit code capture, 200 KB output cap with truncation notice, fully cancellable. | | |
| 154 | +| `osascript` | Executes AppleScript to automate macOS apps (Finder, Notes, Mail, Calendar, System Events…). Detects TCC denials and explains how to grant Automation access. | | |
| 155 | +| `read_file` | Reads a file with offset/limit paging (50 KB per call cap). | | |
| 156 | +| `write_file` | Creates or overwrites a file, tracked in the workspace. | | |
| 157 | +| `edit_file` | Exact-unique string replacement — **fails loudly** if the target text matches zero or multiple times, so edits can't silently hit the wrong line. | | |
| 158 | +| `list_dir` | Directory listing with optional depth. | | |
| 159 | +| `search_files` | Grep-like content search returning `file:line` matches, capped. | | |
| 160 | +| `update_plan` | Internal (never touches the policy gate) — how the agent maintains its checklist. | | |
| 13 | 161 | |
| 14 | −- macOS 13.0+ (Apple Silicon or Intel) | |
| 15 | −- Swift 6 command-line toolchain (Command Line Tools — the Xcode IDE is not used) | |
| 16 | −- The build pins `SDKROOT` to the MacOSX26 SDK (SDK 27's SwiftUI macros require Xcode); the | |
| 17 | − Makefile handles this automatically. | |
| 162 | +Adding a tool is deliberately trivial: conform to the `Tool` protocol (name, description, JSON-Schema parameters, `execute`) and register it in `ToolRegistry`. | |
| 163 | + | |
| 164 | +### 🛡️ Safety: the headline feature | |
| 165 | + | |
| 166 | +This is the part most agent tools treat as an afterthought. | |
| 167 | + | |
| 168 | +**Three modes, switchable per task, always visible in the header:** | |
| 169 | + | |
| 170 | +| Mode | Behavior | | |
| 171 | +|---|---| | |
| 172 | +| **Manual** | Every gated action asks first. | | |
| 173 | +| **Guarded** *(default)* | Curated read-only commands and in-workspace file writes run automatically; anything mutating asks. | | |
| 174 | +| **Autonomous** | Runs freely within budget — **except** the always-ask class, which still asks. | | |
| 175 | + | |
| 176 | +**The gate itself** (`PolicyEngine`, a Swift actor) evaluates `deny → ask → allow`, **per subcommand**: | |
| 177 | + | |
| 178 | +- 🔍 **Commands are parsed, not pattern-matched.** Compound lines split on `&&`, `||`, `;`, `|` and newlines (quote-aware); `$(…)`/backtick substitutions are extracted and classified too; wrappers (`env`, `nohup`, `time`, `xargs`, `nice`) are stripped first. The verdict is the **most severe** across all subcommands — `ls && rm -rf ~/x` asks, because the second half asks. | |
| 179 | +- ⛔ **Hard denies** that no approval can unlock: `rm -rf /` and equivalents, fork bombs, `mkfs`, `diskutil eraseDisk`, writes to `/System`. | |
| 180 | +- ⚠️ **Always-ask circuit breakers, in *every* mode including Autonomous:** any `sudo`, `rm -rf` outside the workspace, `curl … | sh`, overwrites outside the workspace, `kill`/`pkill`, `defaults write`, `launchctl`, `csrutil`, `chmod -R` outside the workspace, writes to `/Library` `/usr` `/etc`, `git push --force`, `shutdown`, `security`, and AppleScript containing `with administrator privileges`. | |
| 181 | +- 🚫 **`sudo` is never run silently.** Ever. Proven by a test that *forces* a `sudo` tool call and confirms denial in all three modes. | |
| 182 | +- ✅ **Inline approval cards** show the exact payload, the risk level and reason, the cwd, and the agent's stated intent — with **Approve**, **Approve & Remember**, **Edit** (re-classified after your edit), and **Deny**. | |
| 183 | +- 📝 **"Approve & remember"** stores the *narrowest* token-prefix rule (`brew list` matches `brew list --versions`, never `brew install`) — and a remembered rule can **never** override a circuit breaker. | |
| 184 | +- 📜 **Append-only audit log** (`.zyquo/audit.jsonl`) records every executed action: timestamp, kind, exact payload, cwd, ruling, exit code, truncated output. Viewable in-app, exportable. | |
| 185 | + | |
| 186 | +Pattern matching is treated as UX, not a security boundary — it's paired with workspace scoping, human approval, and a complete audit trail. | |
| 187 | + | |
| 188 | +### 📁 Workspaces | |
| 189 | + | |
| 190 | +Every task gets its own directory under `~/Library/Application Support/ZyquoAgent/Workspaces/`. `bash` runs there; file tools are scoped there by default and **escaping requires explicit approval**. Created and modified files are tracked with badges, checkpoints can snapshot the agent's work, and reopening an old task restores its workspace and full step history. | |
| 191 | + | |
| 192 | +### 🗜️ Memory & context compaction | |
| 193 | + | |
| 194 | +Long autonomous runs don't fall off the context window: | |
| 195 | + | |
| 196 | +- Live token accounting, calibrated by the provider's own usage numbers. | |
| 197 | +- At **85%** of the model's context, older completed steps are summarized into one compact record by the *same* model (with a mechanical fallback) — while the task, the plan, `MEMORY.md`, and the **most recent 6 steps stay verbatim**. A thrash guard enforces a minimum gap between compactions. | |
| 198 | +- 📤 **Output offloading:** any tool result over 8 KB is written to `.zyquo/outputs/` and replaced in-context by its first ~40 lines plus a path the agent can re-read on demand. | |
| 199 | +- 📌 **`MEMORY.md`** lives in the workspace root and is owned by the agent — it records durable facts that survive compaction *and* whole sessions. | |
| 200 | + | |
| 201 | +*Verified live: a task that triggered **4 compactions** still produced a fully correct result.* | |
| 202 | + | |
| 203 | +### 🖥️ The command-center interface | |
| 204 | + | |
| 205 | +- **Sidebar** — tasks grouped Pinned / Today / Yesterday / Previous 7 Days / Older, each with an animated status pill (Planning · Running · Awaiting approval · Done · Failed), model badge, and a live activity indicator. | |
| 206 | +- **Conversation column** — your prompts as bubbles; the agent's work as **step cards**: thought line, tool chips, the exact command in monospace, color-coded streaming output, exit codes, expandable truncation, collapsible thinking, and inline approval / guard-trip / compaction cards. Final answers render as full Markdown with syntax-highlighted code. | |
| 207 | +- **Plan panel** — the live checklist with animated check-offs, a progress bar, and step/token/time meters against your budgets. | |
| 208 | +- **Activity drawer** — three tabs: **Live** (raw streaming terminal feed with cwd), **Audit Log** (every executed action), **Files** (workspace tree with created/modified badges, preview, reveal in Finder). | |
| 209 | +- **Header** — editable title, model picker (all 170 models, agent-capable ones emphasized), the safety-mode segmented control, workspace chip, export, and an info popover showing the actual system prompt and budgets. | |
| 210 | +- Light theme is the flagship; a deep plum-charcoal dark theme is derived from the same tokens. Five accent colors. | |
| 211 | + | |
| 212 | +### 🎯 Productivity | |
| 213 | + | |
| 214 | +- 📚 **29 built-in task templates** across 6 categories — Files & Folders (6), Development (6), Automation/AppleScript (5), Data (4), System Info (4), Writing (4) — with `{{variable}}` fill-in. Plus your own. | |
| 215 | +- 🎭 **Personas** — a system-prompt addendum, preferred model, and default safety mode, applied per task. | |
| 216 | +- ⚡ **Quick Task panel** (⌥Space) — a Spotlight-style floating panel that runs a one-off task and can be promoted to a full task. | |
| 217 | +- 🔍 **⌘K command palette** — fuzzy search over tasks, templates, and actions. | |
| 218 | +- 📤 **Export** transcripts to Markdown or PDF · 🔎 full-text search across all tasks · 🏷️ auto-generated task titles · 🔔 menu bar extra showing running-task status. | |
| 219 | +- 🔐 **Encrypted key vault** — AES-256-GCM, HKDF-derived and machine-bound, stored at `~/Library/Application Support/ZyquoAgent/vault.zq`. **Deliberately not the Keychain**, matching the rest of the Zyquo family. Environment variables take precedence at run time. | |
| 220 | + | |
| 221 | +<br> | |
| 222 | + | |
| 223 | +--- | |
| 224 | + | |
| 225 | +<br> | |
| 226 | + | |
| 227 | +## 🤖 Providers & Models | |
| 228 | + | |
| 229 | +Zyquo Agent ships the same **170-model catalog** as Zyquo Cloud across **12 providers**, and marks the ~80-model subset that's genuinely suited to multi-step agentic work (strong reasoning + reliable native function calling + adequate context). | |
| 230 | + | |
| 231 | +| Provider | Provider | Provider | | |
| 232 | +|---|---|---| | |
| 233 | +| 🟢 OpenAI | 🟣 Anthropic | ⚫ xAI | | |
| 234 | +| 🟠 Mistral | 🔵 Google Gemini | 🟡 Alibaba Qwen | | |
| 235 | +| 🐋 DeepSeek | 🌙 Kimi (Moonshot) | 🔍 Perplexity | | |
| 236 | +| 🤝 Together AI | ☁️ DeepInfra | ⚡ Cerebras | | |
| 237 | + | |
| 238 | +Plus **custom OpenAI-compatible endpoints**. Two clients cover everything: a native `AnthropicClient` (`/v1/messages`, `tool_use`/`tool_result` blocks, `input_json_delta` streaming) and one `OpenAICompatibleClient` (index-keyed `tool_calls` deltas, `role:"tool"` messages) — normalized behind a single `ProviderClient` protocol so the agent loop never sees a wire format. | |
| 239 | + | |
| 240 | +**Every agent-capable model was verified live**, not assumed: **77 of 80 pass** the full battery — receives the schema, emits a valid *streamed* tool call, consumes a threaded `tool_result`, and produces a correct final answer. Full per-model table with latencies: **[docs/VERIFICATION.md](docs/VERIFICATION.md)**. | |
| 241 | + | |
| 242 | +Two real provider quirks were found and fixed in the process: | |
| 243 | +- **Gemini 3+ thought signatures** — Gemini rejects a threaded tool result if the originating call's opaque `thought_signature` isn't echoed back verbatim; it's now captured and round-tripped. | |
| 244 | +- **OpenAI GPT-5.4+** — `/chat/completions` refuses function tools unless `reasoning_effort` is `none`; the client now downgrades it automatically when tools are attached. | |
| 245 | + | |
| 246 | +The 3 remaining failures are external and documented: DeepInfra's two Gemini re-hosts strip Google's required signature (the same models work via the native Gemini provider), and `kimi-k3` is capacity-throttled upstream. | |
| 247 | + | |
| 248 | +Default agent model: **`claude-sonnet-5`**. | |
| 249 | + | |
| 250 | +> 🔑 **Bring your own keys.** Zyquo Agent ships with none and talks only to the providers you configure. | |
| 251 | + | |
| 252 | +<br> | |
| 253 | + | |
| 254 | +--- | |
| 255 | + | |
| 256 | +<br> | |
| 257 | + | |
| 258 | +## 💾 Installation | |
| 259 | + | |
| 260 | +### Option 1 — Download the DMG *(recommended)* | |
| 261 | + | |
| 262 | +<div align="center"> | |
| 263 | + | |
| 264 | +### **[⬇️ Download Zyquo Agent 1.0.0](https://github.com/spboucher-ai/zyquo-agent/releases/latest/download/ZyquoAgent.dmg)** | |
| 265 | + | |
| 266 | +</div> | |
| 267 | + | |
| 268 | +1. Download `ZyquoAgent.dmg` from the [latest release](https://github.com/spboucher-ai/zyquo-agent/releases/latest). | |
| 269 | +2. Open it and drag **Zyquo Agent** to your **Applications** folder. | |
| 270 | +3. Launch it. **No Gatekeeper warning, no right-click-to-open workaround** — the app is signed with a Developer ID, notarized by Apple, and stapled: | |
| 271 | + | |
| 272 | +```console | |
| 273 | +$ spctl -a -vv "/Applications/Zyquo Agent.app" | |
| 274 | +/Applications/Zyquo Agent.app: accepted | |
| 275 | +source=Notarized Developer ID | |
| 276 | +origin=Developer ID Application: Simon-Pierre Boucher (3YM54G49SN) | |
| 277 | +``` | |
| 278 | + | |
| 279 | +4. Open **Settings → Providers & Keys** (⌘,) and paste at least one API key. | |
| 280 | + | |
| 281 | +### Option 2 — Build from source | |
| 282 | + | |
| 283 | +See [Building from Source](#-building-from-source). | |
| 284 | + | |
| 285 | +### First-run permissions | |
| 286 | + | |
| 287 | +The first time the agent runs AppleScript against another app, macOS asks for **Automation** permission. If you deny it, grant it later in **System Settings → Privacy & Security → Automation**; the app explains this inline when it hits a TCC denial. | |
| 288 | + | |
| 289 | +<br> | |
| 290 | + | |
| 291 | +--- | |
| 18 | 292 | |
| 19 | −## Build | |
| 293 | +<br> | |
| 294 | + | |
| 295 | +## ⚙️ Requirements | |
| 296 | + | |
| 297 | +| | | | |
| 298 | +|---|---| | |
| 299 | +| **macOS** | 13.0 Ventura or later | | |
| 300 | +| **Architecture** | Apple Silicon *or* Intel — the release is a Universal binary (`arm64` + `x86_64`) | | |
| 301 | +| **Disk** | ~15 MB for the app, plus whatever your task workspaces use | | |
| 302 | +| **API key** | At least one from a supported provider (BYOK — none included) | | |
| 303 | +| **Network** | Only to the providers you configure | | |
| 304 | +| **To build** | Swift 6 command-line toolchain. The **Xcode IDE is not required**; `rsvg-convert` (Homebrew) only if you regenerate the icon. | | |
| 305 | + | |
| 306 | +Runtime dependency: exactly one — [`swift-markdown`](https://github.com/swiftlang/swift-markdown) for rendering. Everything else is Foundation, SwiftUI, AppKit, and CryptoKit. | |
| 307 | + | |
| 308 | +<br> | |
| 309 | + | |
| 310 | +--- | |
| 311 | + | |
| 312 | +<br> | |
| 313 | + | |
| 314 | +## 📖 Usage | |
| 315 | + | |
| 316 | +### Your first task | |
| 317 | + | |
| 318 | +1. Press **⌘N** (or click **New Task**). | |
| 319 | +2. Pick a model, and a safety mode — **Guarded** is a sensible default. | |
| 320 | +3. Describe the outcome you want, not the commands. Press **⌘↩**. | |
| 321 | +4. Watch it work. When an approval card appears, read the command, then **Approve**, **Edit**, or **Deny**. | |
| 322 | + | |
| 323 | +Good first tasks (all shipped as templates): | |
| 324 | + | |
| 325 | +``` | |
| 326 | +Organize my Downloads folder by file type into subfolders | |
| 327 | +Set up a Python project with a venv, add pytest, and run the tests | |
| 328 | +Find every file over 100 MB in this folder and summarize what's using space | |
| 329 | +Batch-rename these screenshots to a YYYY-MM-DD-description pattern | |
| 330 | +Read this CSV and give me totals per category | |
| 331 | +Export my Notes to Markdown files | |
| 332 | +``` | |
| 333 | + | |
| 334 | +### Choosing a safety mode | |
| 335 | + | |
| 336 | +| If you… | Use | | |
| 337 | +|---|---| | |
| 338 | +| are trying it out, or the task touches anything you care about | **Manual** | | |
| 339 | +| want it to move but keep your hand on anything mutating | **Guarded** ✅ | | |
| 340 | +| have a long, well-understood, low-stakes task | **Autonomous** | | |
| 341 | + | |
| 342 | +In all three, destructive and elevated actions **still** require your approval. | |
| 343 | + | |
| 344 | +### Keyboard shortcuts | |
| 345 | + | |
| 346 | +| Shortcut | Action | | Shortcut | Action | | |
| 347 | +|---|---|---|---|---| | |
| 348 | +| `⌘N` | New task | | `⌘K` | Command palette | | |
| 349 | +| `⌘↩` | Run | | `⌘F` | Search tasks | | |
| 350 | +| `⌘.` | Stop | | `⌘⇧A` | Open audit log | | |
| 351 | +| `⌥Space` | Quick Task panel | | `⌘⇧E` | Export transcript | | |
| 352 | +| `⌘,` | Settings | | | | | |
| 353 | + | |
| 354 | +### The command-line interface | |
| 355 | + | |
| 356 | +The app binary doubles as a headless CLI — useful for scripting and CI: | |
| 357 | + | |
| 358 | +```bash | |
| 359 | +BIN="/Applications/Zyquo Agent.app/Contents/MacOS/ZyquoAgent" | |
| 360 | + | |
| 361 | +# Run a task headlessly, with live rendering and stdin approval prompts | |
| 362 | +"$BIN" --run "summarize the largest files in this folder" \ | |
| 363 | + --model claude-sonnet-5 --mode guarded --workspace ~/scratch --max-steps 20 | |
| 364 | + | |
| 365 | +# Scripted runs: auto-approve mode-driven prompts. | |
| 366 | +# NOTE: --yes never auto-approves the always-ask class — those are auto-DENIED | |
| 367 | +# unless you additionally pass --allow-destructive. | |
| 368 | +"$BIN" --run "…" --yes | |
| 369 | + | |
| 370 | +"$BIN" --load-vault # import provider keys from environment variables | |
| 371 | +"$BIN" --verify # live tool-calling verification across the catalog | |
| 372 | +"$BIN" --verify-policy # PolicyEngine safety self-check (38 assertions) | |
| 373 | +"$BIN" --run-mock # offline engine smoke test, no keys or network | |
| 374 | +``` | |
| 375 | + | |
| 376 | +Keys resolve from the environment first (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY`, …), then the encrypted vault. | |
| 377 | + | |
| 378 | +<br> | |
| 379 | + | |
| 380 | +--- | |
| 381 | + | |
| 382 | +<br> | |
| 383 | + | |
| 384 | +## 🔨 Building from Source | |
| 20 | 385 | |
| 21 | 386 | ```bash |
| 22 | −make dev # release build → dist/Zyquo Agent.app (ad-hoc signed, fast iteration) | |
| 23 | −make run # make dev + open the app | |
| 24 | −make release # universal binary, Developer ID sign, notarize, staple (Phase 8) | |
| 25 | −make icon # regenerate AppIcon.icns from assets/icon/zyquo-agent.svg | |
| 26 | −make test # swift test (requires an XCTest-capable toolchain) | |
| 387 | +git clone https://github.com/spboucher-ai/zyquo-agent.git | |
| 388 | +cd zyquo-agent | |
| 389 | + | |
| 390 | +make dev # release build → dist/Zyquo Agent.app (ad-hoc signed) — fast iteration | |
| 391 | +make run # build, bundle, and launch | |
| 392 | +make icon # regenerate AppIcon.icns from assets/icon/zyquo-agent.svg | |
| 27 | 393 | make clean |
| 28 | 394 | ``` |
| 29 | 395 | |
| 30 | −Plain SPM also works: `swift build -c release` (export | |
| 31 | −`SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX26.sdk` first). | |
| 396 | +Plain SwiftPM works too: | |
| 397 | + | |
| 398 | +```bash | |
| 399 | +export SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX26.sdk | |
| 400 | +swift build -c release | |
| 401 | +``` | |
| 402 | + | |
| 403 | +<details> | |
| 404 | +<summary><b>Why <code>SDKROOT</code> is pinned</b></summary> | |
| 405 | + | |
| 406 | +<br> | |
| 407 | + | |
| 408 | +SDK 27 declares SwiftUI's `@State` and friends as *macros*, and the macro plugin (`libSwiftUIMacros.dylib`) ships only with the full Xcode install. SDK 26 keeps the property-wrapper forms, so a Command-Line-Tools-only toolchain can build the whole app. The `Makefile` sets this for you. | |
| 409 | + | |
| 410 | +</details> | |
| 411 | + | |
| 412 | +<details> | |
| 413 | +<summary><b>Producing a signed, notarized release</b></summary> | |
| 414 | + | |
| 415 | +<br> | |
| 416 | + | |
| 417 | +`make release` builds a Universal binary (`arm64` + `x86_64` via `lipo`), assembles the bundle, then signs, notarizes, staples, and verifies it. It requires your own Developer ID certificate and a `notarytool` keychain profile — edit `IDENTITY` and `NOTARY_PROFILE` in the `Makefile`. | |
| 418 | + | |
| 419 | +```bash | |
| 420 | +make release # app: sign → notarize → staple → spctl | |
| 421 | +scripts/notarize.sh "dist/Zyquo Agent.app" "<identity>" "<profile>" \ | |
| 422 | + Resources/ZyquoAgent.entitlements dmg # …and a notarized DMG | |
| 423 | +``` | |
| 424 | + | |
| 425 | +The script **fails loudly** unless `spctl` reports `source=Notarized Developer ID`. | |
| 426 | + | |
| 427 | +> ⚠️ Keep `Resources/ZyquoAgent.entitlements` pure ASCII with no XML comments — the AMFI parser `codesign` uses rejects both. | |
| 428 | + | |
| 429 | +</details> | |
| 32 | 430 | |
| 33 | −## CLI modes | |
| 431 | +<details> | |
| 432 | +<summary><b>Running the checks</b></summary> | |
| 34 | 433 | |
| 35 | −The app binary doubles as a headless CLI: | |
| 434 | +<br> | |
| 36 | 435 | |
| 37 | 436 | ```bash |
| 38 | −ZyquoAgent --run "create a folder ~/zqtest with a hello.txt, then list it" # agent loop POC | |
| 39 | −ZyquoAgent --verify # Phase 7 provider tool-calling harness (needs API keys) | |
| 40 | −ZyquoAgent --verify-policy # PolicyEngine safety self-checks | |
| 41 | −ZyquoAgent --load-vault # seed the encrypted key vault from environment variables | |
| 437 | +.build/release/ZyquoAgent --verify-policy # 38 safety assertions | |
| 438 | +.build/release/ZyquoAgent --run-mock # offline end-to-end engine test | |
| 439 | +.build/release/ZyquoAgent --run-ui-smoke # UI state-machine test | |
| 440 | +scripts/agent-eval.sh all # full live scenario + safety suite (needs keys) | |
| 42 | 441 | ``` |
| 43 | 442 | |
| 44 | −## Data locations | |
| 443 | +`swift test` requires an XCTest-capable toolchain; the XCTest files are there for Xcode/CI, and the executable checks above are the equivalents that run anywhere. | |
| 45 | 444 | |
| 46 | −- App data: `~/Library/Application Support/ZyquoAgent/` | |
| 47 | −- Per-task workspaces: `~/Library/Application Support/ZyquoAgent/Workspaces/` | |
| 48 | −- Encrypted key vault (AES-256-GCM, no Keychain — same design as Zyquo Cloud): `…/ZyquoAgent/vault.zq` | |
| 445 | +</details> | |
| 49 | 446 | |
| 50 | −## Documentation | |
| 447 | +<br> | |
| 51 | 448 | |
| 52 | −- `docs/PLAN.md` — phase-by-phase build plan and checkpoints | |
| 53 | −- `docs/AGENT-RESEARCH.md` — the agent-design research the architecture traces back to | |
| 54 | −- `docs/PROVIDER-REUSE.md` — the Zyquo Cloud provider study and porting contract | |
| 449 | +--- | |
| 450 | + | |
| 451 | +<br> | |
| 452 | + | |
| 453 | +## 🏗️ Architecture | |
| 454 | + | |
| 455 | +**82 Swift files, ~19,000 lines**, no Xcode project file. | |
| 456 | + | |
| 457 | +``` | |
| 458 | +Sources/ZyquoAgent/ | |
| 459 | +├── App/ @main, CLI modes, SwiftUI shell, menu bar (5 files) | |
| 460 | +├── Agent/ AgentLoop · Planner · MemoryManager · LoopGuard | |
| 461 | +│ Transcript · AgentStep · AgentEvent · prompt (8 files) | |
| 462 | +├── Tools/ Tool protocol · ToolRegistry · ShellTool | |
| 463 | +│ AppleScriptTool · FileTools (5 files) | |
| 464 | +├── Execution/ ExecutionService · PolicyEngine · AuditLog (4 files) | |
| 465 | +├── Workspace/ WorkspaceManager (1 file) | |
| 466 | +├── Providers/ ProviderClient · Anthropic · OpenAI-compatible (4 files) | |
| 467 | +├── Models/ ToolSpec/ToolCall/ToolResult · AgentTask | |
| 468 | +│ catalog types · templates (9 files) | |
| 469 | +├── Services/ ModelCatalog · SecureKeyStore · Streaming (6 files) | |
| 470 | +├── ViewModels/ TaskStore · RunController · approval bridge (8 files) | |
| 471 | +├── Views/ Command center, settings, palette, Markdown (25 files) | |
| 472 | +├── DesignSystem/ ZyquoTheme tokens, components, glyph (4 files) | |
| 473 | +└── Verify/ Live provider verification harness (1 file) | |
| 474 | +``` | |
| 475 | + | |
| 476 | +**Design rules that hold throughout:** | |
| 477 | + | |
| 478 | +- `AgentLoop`, `ExecutionService`, `PolicyEngine`, `AuditLog`, and `WorkspaceManager` are **actors**; structured concurrency everywhere; every long operation is cancellable. | |
| 479 | +- Shell execution **never** leaks into views or view models — it lives behind `ExecutionService`, and everything passes `PolicyEngine` first. | |
| 480 | +- The UI renders exclusively from an `AgentEvent` stream and the persisted `Transcript`. | |
| 481 | +- Every color, font, spacing, and radius comes from `ZyquoTheme` tokens — no raw hex in views. | |
| 482 | + | |
| 483 | +The architecture traces directly back to research documented in **[docs/AGENT-RESEARCH.md](docs/AGENT-RESEARCH.md)** (413 lines, 79 cited sources), and the provider layer to **[docs/PROVIDER-REUSE.md](docs/PROVIDER-REUSE.md)**. | |
| 484 | + | |
| 485 | +<br> | |
| 486 | + | |
| 487 | +--- | |
| 488 | + | |
| 489 | +<br> | |
| 490 | + | |
| 491 | +## 🔬 Verification & Evaluation | |
| 492 | + | |
| 493 | +Nothing here is claimed on vibes — it was measured, and the failures are documented too. | |
| 494 | + | |
| 495 | +| Suite | Result | Report | | |
| 496 | +|---|---|---| | |
| 497 | +| **Provider tool-calling** (live, every agent-capable model) | **77 / 80** green | [docs/VERIFICATION.md](docs/VERIFICATION.md) | | |
| 498 | +| **End-to-end scenarios** (live, real workspaces) | **11 / 11** pass | [docs/EVALUATION.md](docs/EVALUATION.md) | | |
| 499 | +| **Safety tests** (live) | **8 / 8** pass | [docs/EVALUATION.md](docs/EVALUATION.md) | | |
| 500 | +| **PolicyEngine self-check** | **38 / 38** | `--verify-policy` | | |
| 501 | + | |
| 502 | +Scenarios cover: nested file structures, batch renaming, writing *and running* a Python script, CSV analysis checked against ground truth, largest-file discovery, **re-planning after a deliberate failure**, **forced memory compaction**, AppleScript automation, multi-tool log analysis, and cross-provider parity on a second provider. | |
| 503 | + | |
| 504 | +Safety tests confirm: `sudo` never executes in any mode (including a test that *forces* a sudo tool call), out-of-workspace deletes are auto-denied, cancellation kills the child process, `rm -rf /` is hard-denied, and no key material reaches any transcript, log, or workspace file. | |
| 505 | + | |
| 506 | +<br> | |
| 507 | + | |
| 508 | +--- | |
| 509 | + | |
| 510 | +<br> | |
| 511 | + | |
| 512 | +## 🗺️ Roadmap | |
| 513 | + | |
| 514 | +- [ ] Enforce the two settings that are currently persisted-but-advisory: `requireApprovalForAppleScript` in Autonomous mode, and `workspaceEscapePolicy = deny` *(the engine already asks for AppleScript in Manual/Guarded and always asks on workspace escape — these would add stricter hooks)* | |
| 515 | +- [ ] Optional **Seatbelt sandbox profile** for Autonomous runs, on top of the policy gate | |
| 516 | +- [ ] Read-only **explorer sub-agent** that returns summaries without mutating state | |
| 517 | +- [ ] **HTTP fetch tool** (the `Tool` protocol is built for this) | |
| 518 | +- [ ] Improve auto-generated task titles — short prompts can produce clipped titles | |
| 519 | +- [ ] Workspace **checkpoint restore** exposed in the UI | |
| 520 | +- [ ] Structured exit codes and policy rulings surfaced per step card (currently in the audit log) | |
| 521 | +- [ ] Re-verify `kimi-k3` when Moonshot's capacity recovers | |
| 55 | 522 | |
| 56 | −API keys are **never** committed, logged, or embedded; they live only in the encrypted | |
| 57 | −vault (or env vars during testing). | |
| 523 | +<br> | |
| 58 | 524 | |
| 59 | 525 | --- |
| 60 | 526 | |
| 61 | −Author: Simon-Pierre Boucher · contact@spboucher.ai | |
| 527 | +<br> | |
| 528 | + | |
| 529 | +## 🤝 Contributing | |
| 530 | + | |
| 531 | +Issues and pull requests are welcome. | |
| 532 | + | |
| 533 | +If you contribute code, please keep the project's conventions: | |
| 534 | + | |
| 535 | +1. **Every code file starts with the standard header** (name, `Zyquo Agent`, author, mail) — there's a sweep that checks. | |
| 536 | +2. **Zero build warnings.** | |
| 537 | +3. **Design tokens only** — no raw hex values or magic numbers in views; add a token to `ZyquoTheme` if one is genuinely missing. | |
| 538 | +4. **Never bypass the safety gate.** There must be no code path that executes a shell command or AppleScript without going through `PolicyEngine`, and no action that isn't audited. | |
| 539 | +5. **Never commit secrets.** API keys belong in the vault or the environment. `.secrets/` is gitignored. | |
| 540 | +6. Before opening a PR, run: `swift build -c release`, `--verify-policy`, `--run-mock`, and `--run-ui-smoke`. | |
| 541 | + | |
| 542 | +<br> | |
| 543 | + | |
| 544 | +--- | |
| 545 | + | |
| 546 | +<br> | |
| 547 | + | |
| 548 | +## 📄 License | |
| 549 | + | |
| 550 | +Released under the **MIT License** — see [LICENSE](LICENSE). | |
| 551 | + | |
| 552 | +<br> | |
| 553 | + | |
| 554 | +--- | |
| 555 | + | |
| 556 | +<br> | |
| 557 | + | |
| 558 | +## 👤 Author | |
| 559 | + | |
| 560 | +<div align="center"> | |
| 561 | + | |
| 562 | +**Simon-Pierre Boucher** | |
| 563 | + | |
| 564 | +[](mailto:contact@spboucher.ai) | |
| 565 | + | |
| 566 | +<br> | |
| 567 | + | |
| 568 | +**The Zyquo family** — one design language, three characters | |
| 569 | +☁️ Zyquo Cloud *(chat)* · 💠 Zyquo Local *(on-device)* · ⚡ **Zyquo Agent** *(autonomous)* | |
| 570 | + | |
| 571 | +<br> | |
| 572 | + | |
| 573 | +<sub>Built on macOS with Swift, SwiftUI, and the command line — no Xcode IDE.</sub> | |
| 574 | + | |
| 575 | +<br> | |
| 576 | + | |
| 577 | +⭐ **If Zyquo Agent is useful to you, a star is genuinely appreciated.** | |
| 578 | + | |
| 579 | +</div> | |
added
assets/icon-512.png
+0 −0
Binary file not shown.
added
assets/icon.png
+0 −0
Binary file not shown.
added
assets/screenshots/empty-state.png
+0 −0
Binary file not shown.
added
assets/screenshots/live-run.png
+0 −0
Binary file not shown.
added
assets/screenshots/settings-safety.png
+0 −0
Binary file not shown.