aiwg
Version:
Cognitive architecture for AI-augmented software development with structured memory, ensemble validation, and closed-loop correction. FAIR-aligned artifacts, 84% cost reduction via human-in-the-loop, standards adopted by 100+ organizations.
798 lines (606 loc) • 20 kB
Markdown
# Daemon Mode Guide
AIWG daemon mode runs a persistent background process that monitors your project, executes automated tasks, and bridges messaging platforms. It extends the Ralph loop pattern into always-on project supervision.
## Overview
The daemon provides:
- **File watching** — Trigger actions when project files change
- **Scheduled tasks** — Cron-like scheduling for health checks and audits
- **Agent supervision** — Spawn and manage `claude -p` subprocesses
- **Task queue** — Persistent task management with priority support
- **Automation rules** — Event-driven trigger→condition→action workflows
- **IPC communication** — CLI↔daemon communication via Unix domain socket
- **Messaging integration** — Slack, Discord, and Telegram notifications and commands
- **2-way AI chat** — Ask questions from messaging platforms
## Quick Start
### Start the daemon
```bash
aiwg daemon start
```
The daemon detaches from the terminal and runs in the background. State is stored in `.aiwg/daemon/`.
### Check status
```bash
aiwg daemon status
```
Output shows PID, uptime, active subsystems, and connected adapters.
### Submit a task
```bash
aiwg task submit "Fix the failing tests in auth module"
```
This queues a task for the agent supervisor, which spawns a `claude -p` process to execute it.
### Stop the daemon
```bash
aiwg daemon stop
```
Sends SIGTERM for graceful shutdown. Running tasks are given 15 seconds to complete.
## Configuration
Configuration is stored in `.aiwg/daemon.json`. Create this file in your project root:
```json
{
"daemon": {
"heartbeat_interval_seconds": 30,
"max_parallel_actions": 3,
"action_timeout_minutes": 120,
"log": {
"max_size_mb": 50,
"max_files": 5
}
},
"watch": {
"enabled": true,
"paths": ["src/", "test/", ".aiwg/"],
"ignore": ["node_modules/", ".git/", "*.log"],
"debounce_ms": 1000
},
"schedule": {
"enabled": true,
"jobs": [
{
"name": "health-check",
"cron": "*/30 * * * *",
"action": "health-check"
},
{
"name": "daily-audit",
"cron": "0 9 * * *",
"action": "security-audit"
}
]
},
"rules": [
{
"id": "auto-test-on-change",
"trigger": {
"type": "file_change",
"pattern": "src/**/*.ts"
},
"condition": {
"type": "debounce",
"interval_ms": 5000
},
"action": {
"type": "submit_task",
"prompt": "Run tests for the changed files"
}
}
]
}
```
### Configuration Reference
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `daemon.heartbeat_interval_seconds` | number | 30 | Heartbeat write interval |
| `daemon.max_parallel_actions` | number | 3 | Maximum concurrent agent tasks |
| `daemon.action_timeout_minutes` | number | 120 | Task timeout before kill |
| `daemon.log.max_size_mb` | number | 50 | Log file rotation size |
| `daemon.log.max_files` | number | 5 | Number of rotated log files to keep |
| `watch.enabled` | boolean | false | Enable file system monitoring |
| `watch.paths` | string[] | — | Directories to watch |
| `watch.ignore` | string[] | — | Glob patterns to ignore |
| `watch.debounce_ms` | number | 1000 | Debounce interval for rapid changes |
| `schedule.enabled` | boolean | false | Enable cron scheduling |
| `schedule.jobs` | object[] | — | Cron job definitions |
| `rules` | object[] | — | Automation rules |
## IPC Commands
The daemon communicates via a Unix domain socket at `.aiwg/daemon/daemon.sock` using JSON-RPC 2.0.
### Daemon Management
```bash
# Full daemon status with all subsystems
aiwg daemon status
# Health check (quick ping)
aiwg daemon ping
```
### Task Management
```bash
# Submit a task
aiwg task submit "Refactor the user module to use dependency injection"
# Submit with priority (higher = sooner, default 0)
aiwg task submit "Fix critical security bug" --priority 10
# List tasks
aiwg task list
aiwg task list --state running
aiwg task list --state queued
aiwg task list --state completed
# Get task details
aiwg task get <task-id>
# Cancel a task
aiwg task cancel <task-id>
# Task statistics
aiwg task stats
```
### Automation Management
```bash
# View automation status and rules
aiwg automation status
# Enable/disable all automation
aiwg automation enable
aiwg automation disable
# Enable/disable specific rule
aiwg automation enable --rule auto-test-on-change
aiwg automation disable --rule auto-test-on-change
```
### Chat via IPC
```bash
# Send a chat message through the daemon (submitted as a task)
aiwg chat send "What is our current test coverage?"
```
## Agent Tasks
The daemon's agent supervisor manages `claude -p` subprocesses:
### How Tasks Work
1. A task is submitted (via CLI, automation rule, or messaging command)
2. The task enters the queue with its priority
3. When a slot is available (under `max_parallel_actions`), the supervisor spawns a `claude -p` process
4. The process runs in the project directory with full CLAUDE.md context
5. On completion, the result is stored in the task store
6. Events are emitted: `task:started`, `task:completed`, `task:failed`, `task:timeout`
### Task States
| State | Description |
|-------|-------------|
| `queued` | Waiting for an available slot |
| `running` | `claude -p` process is active |
| `completed` | Process exited successfully |
| `failed` | Process exited with error |
| `cancelled` | Cancelled by user or system |
| `timeout` | Exceeded `action_timeout_minutes` |
### Concurrency
The `max_parallel_actions` setting controls how many tasks run simultaneously. Default is 3. Each running task is a separate Node.js child process running `claude -p`.
## Automation Rules
Automation rules define event-driven workflows that respond to file changes, scheduled events, or other daemon events.
### Rule Structure
```json
{
"id": "unique-rule-id",
"trigger": {
"type": "file_change",
"pattern": "src/**/*.ts"
},
"condition": {
"type": "debounce",
"interval_ms": 5000
},
"action": {
"type": "submit_task",
"prompt": "Run linting on the changed TypeScript files"
}
}
```
### Trigger Types
| Type | Description | Parameters |
|------|-------------|------------|
| `file_change` | File created, modified, or deleted | `pattern` (glob) |
| `schedule` | Cron schedule fires | `cron` (cron expression) |
| `event` | Internal daemon event | `topic` (event topic string) |
### Condition Types
| Type | Description | Parameters |
|------|-------------|------------|
| `debounce` | Wait for activity to settle | `interval_ms` |
| `always` | Always proceed | — |
### Action Types
| Type | Description | Parameters |
|------|-------------|------------|
| `submit_task` | Submit to agent supervisor | `prompt`, `priority?` |
### Example Rules
**Run tests when source changes**:
```json
{
"id": "auto-test",
"trigger": {"type": "file_change", "pattern": "src/**/*.{ts,js}"},
"condition": {"type": "debounce", "interval_ms": 5000},
"action": {"type": "submit_task", "prompt": "Run the test suite and report results"}
}
```
**Security scan on config changes**:
```json
{
"id": "security-scan",
"trigger": {"type": "file_change", "pattern": "**/.env*"},
"condition": {"type": "always"},
"action": {"type": "submit_task", "prompt": "Scan for accidentally committed secrets", "priority": 10}
}
```
## REPL Chat
The daemon includes an interactive REPL for terminal-based chat:
```bash
aiwg daemon chat
```
This connects to the running daemon via IPC and provides an interactive prompt for sending messages. Messages are submitted as high-priority tasks to the agent supervisor.
## Tmux Integration
For projects using tmux, the daemon can manage sessions:
```bash
# Start daemon with tmux session
aiwg daemon start --tmux
# Attach to daemon's tmux session
aiwg daemon attach
```
The tmux manager creates a session named `aiwg-daemon` with panes for:
- Daemon logs
- Task output
- Interactive chat
## Health Monitoring
### Heartbeat
The daemon writes a heartbeat file every `heartbeat_interval_seconds` (default 30s):
```
.aiwg/daemon/heartbeat
```
Contains PID, timestamp, and uptime. External monitoring tools can check this file for daemon health.
### State File
Complete daemon state is written alongside the heartbeat:
```
.aiwg/daemon/state.json
```
Contains:
- PID and start time
- Uptime
- IPC socket path and connected clients
- Agent supervisor status (running/queued tasks)
- Task statistics
- File watcher and scheduler status
- Automation engine state
- Health assessment
### Log Rotation
Daemon logs are written to `.aiwg/daemon/daemon.log` with automatic rotation:
- Rotates when file exceeds `log.max_size_mb` (default 50 MB)
- Keeps `log.max_files` rotated copies (default 5)
- Rotated files named: `daemon.log.1`, `daemon.log.2`, etc.
## Docker and CI Usage
The daemon works in Docker containers and CI environments:
```dockerfile
# Dockerfile
FROM node:20
RUN npm install -g aiwg
WORKDIR /app
COPY . .
RUN aiwg daemon start
```
Key considerations:
- No systemd or launchd required — pure Node.js process management
- PID file at `.aiwg/daemon.pid` for lifecycle tracking
- Lock file at `.aiwg/daemon/.lock` prevents duplicate daemons
- Unix socket at `.aiwg/daemon/daemon.sock` for IPC
- All paths are project-relative (no system-level dependencies)
### Running as a Service
For long-lived deployments, use your system's service manager:
**systemd (Linux)**:
```ini
[Unit]
Description=AIWG Daemon
After=network.target
[Service]
Type=forking
PIDFile=/path/to/project/.aiwg/daemon.pid
ExecStart=/usr/bin/node /path/to/project/tools/daemon/daemon-main.mjs
ExecStop=/bin/kill -TERM $MAINPID
WorkingDirectory=/path/to/project
User=developer
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
```
**launchd (macOS)**:
```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>io.aiwg.daemon</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/node</string>
<string>/path/to/project/tools/daemon/daemon-main.mjs</string>
</array>
<key>WorkingDirectory</key>
<string>/path/to/project</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/path/to/project/.aiwg/daemon/stdout.log</string>
<key>StandardErrorPath</key>
<string>/path/to/project/.aiwg/daemon/stderr.log</string>
</dict>
</plist>
```
## File Structure
```
.aiwg/
├── daemon.pid # Daemon process ID
└── daemon/
├── .lock # Single-instance lock file
├── heartbeat # Health check file (JSON)
├── state.json # Full daemon state
├── daemon.log # Log output
├── daemon.log.1 # Rotated logs
├── daemon.sock # Unix domain socket for IPC
├── tasks.json # Persistent task queue
├── actions/ # Action output directory
└── events/ # Event log directory
```
## Troubleshooting
### Daemon won't start
```bash
# Check if already running
aiwg daemon status
# Check for stale lock file
ls -la .aiwg/daemon/.lock
# Remove stale lock and PID (if daemon is confirmed not running)
rm .aiwg/daemon/.lock .aiwg/daemon.pid
aiwg daemon start
```
### Can't connect to daemon
```bash
# Verify socket exists
ls -la .aiwg/daemon/daemon.sock
# Check socket permissions
stat .aiwg/daemon/daemon.sock
# Verify daemon PID is running
cat .aiwg/daemon.pid
ps -p $(cat .aiwg/daemon.pid)
```
### Tasks stuck in queue
```bash
# Check supervisor status
aiwg daemon status
# Check if max_parallel_actions limit is reached
aiwg task list --state running
# Cancel a stuck task
aiwg task cancel <task-id>
```
### High memory usage
The daemon accumulates conversation history for AI chat sessions. Clear old conversations by restarting the daemon:
```bash
aiwg daemon stop && aiwg daemon start
```
### Log file too large
Check log rotation settings in `.aiwg/daemon.json`:
```json
{
"daemon": {
"log": {
"max_size_mb": 50,
"max_files": 5
}
}
}
```
## Advanced Configuration
### Custom Event Handlers
Automation rules can respond to custom daemon events:
```json
{
"id": "on-deployment-complete",
"trigger": {
"type": "event",
"topic": "deployment:complete"
},
"condition": {"type": "always"},
"action": {
"type": "submit_task",
"prompt": "Run post-deployment smoke tests"
}
}
```
Emit custom events from your own scripts using the IPC protocol:
```javascript
import { DaemonClient } from 'aiwg/daemon/ipc-client';
const client = new DaemonClient();
await client.connect();
await client.emit('deployment:complete', { version: '1.2.3' });
await client.disconnect();
```
### Multiple Automation Profiles
Create environment-specific configuration:
```bash
# Development profile with aggressive automation
aiwg daemon start --config .aiwg/daemon.dev.json
# Production profile with conservative automation
aiwg daemon start --config .aiwg/daemon.prod.json
```
### Task Priority Strategies
Tasks are executed in priority order (higher priority first):
| Priority | Use Case | Example |
|----------|----------|---------|
| 10 | Critical security issues | Secret scanning |
| 5 | Important but not urgent | Nightly backups |
| 0 (default) | Normal development tasks | Test runs |
| -5 | Low priority background tasks | Documentation updates |
When multiple tasks have the same priority, they execute in submission order (FIFO).
## Performance Tuning
### File Watching at Scale
For large projects, optimize file watching:
```json
{
"watch": {
"enabled": true,
"paths": ["src/", "test/"],
"ignore": [
"node_modules/",
".git/",
"*.log",
"dist/",
"build/",
"coverage/"
],
"debounce_ms": 3000,
"use_polling": false
}
}
```
- Increase `debounce_ms` to reduce noise from rapid file changes
- Set `use_polling: true` only if native file watching fails (slower but more compatible)
- Exclude large directories like `node_modules/` and build artifacts
### Concurrency Limits
Adjust `max_parallel_actions` based on system resources:
```json
{
"daemon": {
"max_parallel_actions": 5
}
}
```
Each agent task spawns a separate `claude -p` process. Monitor resource usage:
```bash
# Check daemon and subprocess resource usage
ps aux | grep -E '(daemon|claude)'
```
Recommended limits:
- Development machine: 3-5 concurrent tasks
- CI server: 5-10 concurrent tasks
- Production server: 1-3 concurrent tasks
### Task Timeout Tuning
Set appropriate timeouts for different task types:
```json
{
"daemon": {
"action_timeout_minutes": 120
}
}
```
For specific tasks requiring longer execution:
```bash
# Override timeout for long-running task
aiwg task submit "Comprehensive security audit" --timeout 240
```
## Security Considerations
### Access Control
The daemon runs with the permissions of the user who started it. IPC socket permissions are set to 0600 (owner read/write only).
For multi-user environments, consider:
- Running daemon as dedicated service user
- Setting appropriate file permissions on `.aiwg/daemon/`
- Using OS-level access controls for socket file
### Secrets in Automation
Avoid embedding secrets in automation rules. Use environment variables:
```json
{
"id": "notify-on-error",
"trigger": {"type": "event", "topic": "task:failed"},
"action": {
"type": "submit_task",
"prompt": "Send failure notification",
"env": {
"SLACK_WEBHOOK_URL": "${SLACK_WEBHOOK_URL}"
}
}
}
```
### Network Exposure
The daemon uses local Unix domain sockets by default (no network exposure). For remote access, use SSH tunneling:
```bash
# From remote machine
ssh -L /tmp/aiwg.sock:/path/to/project/.aiwg/daemon/daemon.sock user@host
# Use forwarded socket
export AIWG_DAEMON_SOCKET=/tmp/aiwg.sock
aiwg daemon status
```
## Cross-References
- [Messaging Guide](messaging-guide.md) — Platform integration
- [Ralph Guide](ralph-guide.md) — Iterative task loops via daemon
- `.aiwg/architecture/adrs/ADR-daemon-mode.md` — Architecture decision
- `.aiwg/architecture/adrs/ADR-ipc-protocol.md` — IPC protocol specification
- `tools/daemon/README.md` — Developer documentation
- `tools/daemon/daemon-main.mjs` — Daemon entry point source
- `tools/daemon/agent-supervisor.mjs` — Agent task execution
- `tools/daemon/automation-engine.mjs` — Rule processing
- `tools/daemon/ipc-server.mjs` — IPC server implementation
- `tools/daemon/ipc-client.mjs` — IPC client implementation
## Migration from Manual Workflows
### Before: Manual Testing
```bash
# Developer manually runs tests after changes
npm test
```
### After: Automated Testing
```json
{
"rules": [
{
"id": "auto-test",
"trigger": {"type": "file_change", "pattern": "src/**/*.ts"},
"condition": {"type": "debounce", "interval_ms": 5000},
"action": {"type": "submit_task", "prompt": "Run tests for changed files"}
}
]
}
```
Now tests run automatically after code changes stabilize.
### Before: Scheduled Tasks via Cron
```cron
0 9 * * * cd /path/to/project && npm run audit
```
### After: Daemon Scheduling
```json
{
"schedule": {
"enabled": true,
"jobs": [
{
"name": "daily-audit",
"cron": "0 9 * * *",
"action": "security-audit"
}
]
}
}
```
Scheduling is now project-aware and integrated with task management.
## Best Practices
1. **Start small** — Begin with file watching or scheduling, add automation rules incrementally
2. **Use meaningful rule IDs** — Makes debugging and logs clearer
3. **Set appropriate debounce intervals** — Balance responsiveness with noise reduction
4. **Monitor task queue depth** — Adjust `max_parallel_actions` if queue grows
5. **Review logs regularly** — Check `.aiwg/daemon/daemon.log` for issues
6. **Test automation rules** — Manually trigger events to verify behavior
7. **Document custom rules** — Add comments explaining business logic
8. **Version control daemon config** — Track `.aiwg/daemon.json` in git
9. **Set up log rotation** — Prevent disk space issues
10. **Use priorities wisely** — Reserve high priorities for truly urgent tasks
## FAQ
**Q: Can I run multiple daemons in different projects?**
Yes. Each project has its own daemon instance with separate state in `.aiwg/daemon/`.
**Q: Does the daemon survive system reboots?**
No. Use your OS service manager (systemd/launchd) to start the daemon automatically.
**Q: Can I submit tasks while the daemon is stopped?**
No. The daemon must be running to accept tasks. Start it with `aiwg daemon start`.
**Q: How do I upgrade the daemon after updating AIWG?**
Stop the daemon, update AIWG, restart the daemon:
```bash
aiwg daemon stop
npm update -g aiwg
aiwg daemon start
```
**Q: Can automation rules spawn other automation rules?**
Not directly, but tasks submitted by automation can emit events that trigger other rules.
**Q: What happens to running tasks when I stop the daemon?**
Running tasks receive SIGTERM and have 15 seconds to complete. After that, they're killed.
**Q: Can I pause the daemon without stopping it?**
Use automation disable to stop rule processing while keeping the daemon running:
```bash
aiwg automation disable
```
**Q: How do I debug automation rules?**
Check the daemon log for trigger/action events:
```bash
tail -f .aiwg/daemon/daemon.log | grep automation
```
**Q: Can I use the daemon without messaging platforms?**
Yes. Messaging integration is optional. The daemon provides file watching, scheduling, and task management independently.