Native macOS cockpit for AI agents
Features • Installation • Architecture • Contributing • License
Early Alpha — Sable is under active development. Core features work but expect rough edges, UI bugs, and breaking changes. If you're okay with that, contributions are very welcome — there's plenty to fix and improve.
Sable is a native macOS desktop application that serves as a unified cockpit for interacting with AI agents through the OpenClaw framework. Built entirely with SwiftUI and SwiftData — zero external dependencies.
Think of it as a local-first, privacy-respecting alternative to web-based AI chat interfaces, with deep integration into agent workflows, tool execution, and multi-provider support.
- Real-time SSE streaming with typewriter rendering — not fake delays, actual server-sent events
- Tool call visibility — see what the agent is doing (searching, reading, executing) in real time
- Reasoning blocks — collapsible thinking process display for reasoning models
- Auto-retry — transient failures (timeouts, 502/503) retry automatically with exponential backoff, like Claude and ChatGPT
- Rich content — Markdown rendering, code blocks with syntax differentiation, image attachments, file uploads
- Message actions — copy, regenerate, delete via hover overlay (no clutter)
- OpenClaw Gateway — primary channel via
/v1/responsesAPI (SSE streaming) - Direct API — Anthropic, OpenAI, Google Gemini, Moonshot Kimi, Ollama
- Model discovery — auto-detect available models from each provider
- API keys — stored in macOS Keychain, never in config files
- Browse, configure, and edit OpenClaw agents
- Skill browser with one-click installation
- Real-time gateway health monitoring
- Monochrome design system — zero accent colors, hierarchy through opacity and weight
- Dark & Light mode — full support with semantic color tokens
- Localization — English and Chinese
- Menu bar extra — quick access from the system tray
- macOS 14.0 (Sonoma) or later
- XcodeGen (
brew install xcodegen) - Xcode 16+
- OpenClaw (for gateway features)
# Clone
git clone https://github.com/Dglsel/Sable.git
cd Sable
# Generate Xcode project
xcodegen generate
# Open in Xcode and build (⌘B), or:
xcodebuild -project Sable.xcodeproj -scheme Sable -destination 'platform=macOS' buildIf you want to use the OpenClaw gateway for agent features:
# Install OpenClaw
curl -fsSL https://openclaw.ai/install.sh | bash
# Start the gateway
openclaw gateway startSable reads gateway configuration from ~/.openclaw/openclaw.json automatically.
You can also use Sable as a standalone chat client by configuring provider API keys directly in Settings.
Sable/
├── App/ # Entry point, DI container, window management
├── Features/ # Feature modules
│ ├── Chat/ # Message list, composer, streaming, typewriter
│ ├── Dashboard/ # Gateway status, health monitoring
│ ├── Agents/ # Agent browser & editor
│ ├── Skills/ # Skill browser & installer
│ ├── Settings/ # Provider config, appearance, data management
│ ├── Sidebar/ # Navigation, conversation history
│ └── MenuBar/ # System tray panel
├── Core/ # Shared infrastructure
│ ├── DesignSystem/ # Tokens: theme, typography, spacing, animation
│ ├── Models/ # SwiftData entities (Conversation, Message)
│ ├── Types/ # Value types, enums, configuration
│ └── Utilities/ # Helpers
├── Services/ # Service layer
│ ├── OpenClaw/ # Gateway client, ACP protocol, SSE streaming
│ ├── Providers/ # Multi-provider abstraction (Anthropic, OpenAI, etc.)
│ ├── Security/ # Keychain integration
│ └── Persistence/ # SwiftData container management
└── Resources/ # Assets, localization strings
| Decision | Rationale |
|---|---|
| Zero dependencies | No SPM packages — ships with only Apple frameworks |
| SwiftData over Core Data | Type-safe, modern persistence with @Model macro |
| SSE over WebSocket | Simpler protocol, better compatibility with HTTP infrastructure |
| Monochrome UI | Intentional differentiation — content takes center stage |
| XcodeGen | Reproducible project generation, no .xcodeproj conflicts in git |
| Keychain for secrets | OS-level encryption, never stored in files or UserDefaults |
User Input
→ URLContentFetcher (extract web content from URLs in prompt)
→ OpenResponsesService (POST /v1/responses, SSE stream)
→ StreamEvent enum (.delta, .toolCall, .reasoningDelta, .completed, .retrying)
→ ChatHomeView (state management, message accumulation)
→ TypewriterState (character-by-character rendering at 60fps)
→ MessageListView (LazyVStack + auto-scroll)
Contributions are welcome. Here's how to get started:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run
xcodegen generateif you added/removed files - Build and test (
⌘Bin Xcode) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This is an early alpha. Known bugs and rough edges include:
- Scroll behavior — auto-scroll can be unreliable in long conversations; scroll-to-bottom button may not appear consistently
- Streaming edge cases — typewriter animation occasionally fails to render, showing content all at once
- Conversation switching — switching between conversations can sometimes cause blank content or stale state
- ThinkingIndicator — may not display correctly after certain tool call sequences
- Settings UI — some pickers don't refresh immediately after language switch
- Code blocks — syntax highlighting is minimal (monochrome only, no language detection yet)
- Bug fixes — see Known Issues above, all of these are open for PRs
- Unit tests — test coverage is minimal, especially for services and parsing logic
- Accessibility — VoiceOver support, keyboard navigation
- Performance — LazyVStack optimization for very long conversations (1000+ messages)
- Localization — additional language support beyond English and Chinese
- Code syntax highlighting — monochrome weight/opacity-based differentiation
- Swift 6 strict concurrency — all
@MainActorannotations are intentional - Design tokens are defined in
Core/DesignSystem/— never hardcode colors, fonts, or spacing - Read
DESIGN.mdbefore making visual changes
MIT — use it however you want.