Files
ironclaw/docs/drafts/platforms/macos.mdx
2026-04-09 14:18:30 +02:00

280 lines
6.7 KiB
Plaintext

---
title: macOS
sidebarTitle: macOS
description: Running IronClaw on macOS with Homebrew, Keychain, and launchd
---
IronClaw supports macOS natively with Homebrew installation, macOS Keychain for secure key storage, and launchd for background service management.
---
## Installation
### Homebrew (Recommended)
```bash
# Add the IronClaw tap
brew tap ironclaw-ai/tap
# Install IronClaw
brew install ironclaw
```
### Shell Script
```bash
curl -fsSL https://install.ironclaw.ai | bash
```
Installs to `~/.local/bin/ironclaw`. Add to PATH:
```bash
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
```
### Cargo (Build from Source)
```bash
# Install Rust if needed
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Build and install
cargo install ironclaw
```
### Verify Installation
```bash
ironclaw --version
ironclaw doctor
```
---
## First Launch: Gatekeeper
macOS Gatekeeper may block the binary on first launch if it was downloaded directly rather than installed through Homebrew.
**To allow it:**
1. Right-click `ironclaw` in Finder and choose **Open**
2. Click **Open** in the security dialog
Or via the terminal:
```bash
xattr -d com.apple.quarantine ~/.local/bin/ironclaw
```
<Note>
Binaries installed via `brew install ironclaw` are automatically notarized and will not trigger the Gatekeeper warning.
</Note>
---
## macOS Keychain Integration
IronClaw stores its encryption master key in the macOS Keychain. This keeps the key off disk and protected by your login password and Touch ID.
### First Run Dialogs
On first run you will see two system dialogs:
1. **"Enter your password to unlock the login keychain"** — Unlock the keychain to read/write items. Enter your macOS login password.
2. **"ironclaw wants to use your confidential information stored in 'IronClaw Master Key' in your keychain"** — Click **Always Allow** to prevent repeated prompts on future launches.
<Warning>
Clicking **Allow** instead of **Always Allow** causes this dialog to appear on every launch. Choose **Always Allow** the first time to avoid repeated interruptions.
</Warning>
### Managing the Keychain Entry
View the entry in Keychain Access (open via Spotlight: `keychain access`):
- Category: **Passwords**
- Name: `IronClaw Master Key`
- Account: `ironclaw`
To delete and regenerate the master key (this invalidates all stored secrets):
```bash
security delete-generic-password -a ironclaw -s "IronClaw Master Key"
ironclaw onboard # Re-run wizard to generate a new key
```
### Headless / CI Environments
For non-interactive macOS environments (CI, build machines), use the environment variable fallback:
```bash
export IRONCLAW_MASTER_KEY=$(openssl rand -base64 32)
```
---
## launchd Service
launchd is the macOS equivalent of systemd. It manages background services and can restart IronClaw automatically on failure or system reboot.
### User-Level Service (Recommended)
Create `~/Library/LaunchAgents/ai.ironclaw.plist`:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>ai.ironclaw</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/ironclaw</string>
<string>run</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>DATABASE_BACKEND</key>
<string>libsql</string>
<key>LLM_BACKEND</key>
<string>nearai</string>
<key>GATEWAY_ENABLED</key>
<string>true</string>
<key>GATEWAY_HOST</key>
<string>127.0.0.1</string>
<key>GATEWAY_PORT</key>
<string>3000</string>
<key>RUST_LOG</key>
<string>ironclaw=info</string>
</dict>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<dict>
<key>Crashed</key>
<true/>
<key>SuccessfulExit</key>
<false/>
</dict>
<key>StandardOutPath</key>
<string>/tmp/ironclaw.stdout.log</string>
<key>StandardErrorPath</key>
<string>/tmp/ironclaw.stderr.log</string>
<key>WorkingDirectory</key>
<string>/Users/YOUR_USERNAME</string>
</dict>
</plist>
```
Replace `YOUR_USERNAME` with your actual macOS username (`whoami`).
<Note>
Sensitive values (API keys, auth tokens) should not be placed in the plist directly since it is a plain text file. Store them in the Keychain and have IronClaw read them at startup, or use `launchctl setenv` to inject them at runtime.
</Note>
### Load and Manage the Service
```bash
# Load the service (starts immediately due to RunAtLoad)
launchctl load ~/Library/LaunchAgents/ai.ironclaw.plist
# Unload (stop and disable)
launchctl unload ~/Library/LaunchAgents/ai.ironclaw.plist
# Reload after editing the plist
launchctl unload ~/Library/LaunchAgents/ai.ironclaw.plist
launchctl load ~/Library/LaunchAgents/ai.ironclaw.plist
# Check status
launchctl list | grep ironclaw
# Start / stop manually
launchctl start ai.ironclaw
launchctl stop ai.ironclaw
```
### Homebrew Services (Alternative)
If installed via Homebrew:
```bash
# Start now and on login
brew services start ironclaw
# Stop
brew services stop ironclaw
# Restart
brew services restart ironclaw
# View status
brew services list | grep ironclaw
```
---
## Docker Desktop for macOS
The Docker sandbox requires Docker. On macOS, use [Docker Desktop](https://www.docker.com/products/docker-desktop/).
### Install Docker Desktop
1. Download from [docker.com/products/docker-desktop](https://www.docker.com/products/docker-desktop/)
2. Drag to Applications and open
3. Complete the setup wizard
4. Verify: `docker run --rm hello-world`
### Resource Limits
Docker Desktop runs inside a Linux VM on macOS. Configure the VM resource allocation in **Docker Desktop → Settings → Resources**:
| Setting | Minimum | Recommended |
|---------|---------|-------------|
| CPUs | 2 | 4 |
| Memory | 4 GB | 8 GB |
| Disk | 20 GB | 40 GB |
<Note>
Docker on macOS has more overhead than native Linux due to the VM layer. Sandbox container startup is typically 1-3 seconds slower than on Linux. This is expected behavior.
</Note>
---
## Viewing Logs
```bash
# Stream logs in real time (unified log)
log stream --predicate 'process == "ironclaw"' --level info
# Show recent messages
log show --predicate 'process == "ironclaw"' --last 1h
# View launchd stdout/stderr files
tail -f /tmp/ironclaw.stdout.log
tail -f /tmp/ironclaw.stderr.log
```
---
## Next Steps
<CardGroup cols={3}>
<Card title="VPS Hardening" icon="shield" href="/platforms/vps">
Securing IronClaw on a public-facing server
</Card>
<Card title="Docker Compose" icon="layers" href="/platforms/docker-compose">
Production Docker Compose with PostgreSQL
</Card>
<Card title="Logging" icon="file-text" href="/ops/logging">
RUST_LOG levels and log streaming
</Card>
</CardGroup>