# TOOLS.md - Local Notes

Skills define _how_ tools work. This file is for _your_ specifics — the stuff that's unique to your setup.

## Why Separate?

Skills are shared. Your setup is yours. Keeping them apart means you can update skills without losing your notes, and share skills without leaking your infrastructure.

---
## Gitea (Git Server - DO NOT INSTALL LOCALLY)

**⚠️ CRITICAL:** Gitea runs on a SEPARATE MACHINE (192.168.1.128). Do NOT install it on Matt's Mac.

**Server Location:** http://192.168.1.128:3000 (NOT localhost:3000)
- **Login:** ai-agent / !7883Gitea
- **Organization:** TopDogLabs
- **All repos go under:** http://192.168.1.128:3000/TopDogLabs/

### Backup Rule - MANDATORY

**ALWAYS push to Gitea after significant changes:**
```bash
cd /Users/mattbruce/.openclaw/workspace
git add -A
git commit -m "Description of changes"
git push origin master
```

**Push after:**
- New skills or agent profiles created
- TOOLS.md, SOUL.md, AGENTS.md updates
- New cron jobs or automation
- Significant memory/documentation changes
- New project scaffolding

**Why:** Ensures continuity if local workspace is lost/corrupted.

### Using Gitea

**Clone existing repo:**
```bash
git clone http://192.168.1.128:3000/TopDogLabs/repo-name.git
```

**Push to Gitea:**
```bash
git push origin main
# Enter username: ai-agent
# Enter password: !7883Gitea
```

**Create new repo via web:**
1. Go to http://192.168.1.128:3000
2. Login as ai-agent
3. Click + → New Repository
4. Owner: TopDogLabs
5. Name: [project-name]

**NEVER do this:**
- ❌ `brew install gitea` on Matt's Mac
- ❌ Run `gitea web` locally
- ❌ Use port 3000 for anything (it's for Next.js dev)

## Folders for All Content/Projects
- **Location:** /Users/mattbruce/Documents/Projects/OpenClaw
- **Documents:** /Users/mattbruce/Documents/Projects/OpenClaw/Documents
- **iOS:** /Users/mattbruce/Documents/Projects/OpenClaw/iOS
- **Web:** /Users/mattbruce/Documents/Projects/OpenClaw/Web

## Blog Backup
- **Location:** /Users/mattbruce/Documents/Projects/OpenClaw/Web/blog-backup
- **Live URL:** https://blog.twisteddevices.com
- **API:** https://blog.twisteddevices.com/api
- **Local Dev:** http://localhost:3002
- **Stack:** Next.js + Supabase + Vercel
- **Deploy:** `npm run build && vercel --prod` (no GitHub, CLI only)
- **Features:** Daily digest blog with tag filtering, search, responsive design

### API Key
- **Cron Job:** `daily-digest-2026-secure-key`
- **Usage:** Set in Vercel environment as `CRON_API_KEY`
- **In Skill:** `export BLOG_MACHINE_TOKEN="daily-digest-2026-secure-key"`
- **Skill Location:** `~/.agents/skills/blog-backup/`

### CLI Access

**Location:** `/Users/mattbruce/Documents/Projects/OpenClaw/Web/blog-backup/scripts/`

**Script:** `blog.sh` - Digest management (create, list, get, delete, search, status)

**Quick Examples:**
```bash
cd /Users/mattbruce/Documents/Projects/OpenClaw/Web/blog-backup

# Create a digest
./scripts/blog.sh post \
    --date 2026-02-26 \
    --content "# Daily Digest" \
    --tags '["AI", "iOS"]'

# List recent digests
./scripts/blog.sh list --limit 10 --json

# Get specific digest
./scripts/blog.sh get 1234567890

# Search digests
./scripts/blog.sh search "OpenClaw"

# Check if digest exists for date
./scripts/blog.sh status 2026-02-26

# Check API health
./scripts/blog.sh health
```

### Skill Usage
```bash
source ~/.agents/skills/blog-backup/lib/blog.sh
export BLOG_MACHINE_TOKEN="daily-digest-2026-secure-key"
export BLOG_API_URL="https://blog.twisteddevices.com/api"

# Create a digest
DIGEST_ID=$(blog_post_create \
    --date "2026-02-26" \
    --content "# Daily Digest" \
    --tags '["AI", "iOS"]')

# List digests
blog_post_list --limit 10 --json

# Get specific digest
blog_post_get "1234567890"

# Search digests
blog_post_search "OpenClaw"
```

## Mission Control
- **Location:** /Users/mattbruce/Documents/Projects/OpenClaw/Web/mission-control
- **Live URL:** https://mission-control.twisteddevices.com/
- **API:** https://mission-control.twisteddevices.com/api
- **Local Dev:** http://localhost:3001
- **Stack:** Next.js + Vercel
- **Deploy:** `npm run build && vercel --prod` (no GitHub, CLI only)

## Gantt Board
- **Location:** /Users/mattbruce/Documents/Projects/OpenClaw/Web/gantt-board
- **Live URL:** https://gantt-board.twisteddevices.com
- **API:** https://gantt-board.twisteddevices.com/api
- **Login:** mbruce+max@topdoglabs.com / !7883Gantt
- **Local Dev:** http://localhost:3000
- **Stack:** Next.js + Supabase + Vercel
- **Deploy:** `npm run build && vercel --prod` (no GitHub, CLI only)

### CLI Access (Full CRUD)

**Location:** `/Users/mattbruce/Documents/Projects/OpenClaw/Web/gantt-board/scripts/`

**Scripts:**
- `task.sh` - Task management (create, list, get, update, delete, bulk-create)
- `project.sh` - Project management (create, list, get, update, delete)
- `sprint.sh` - Sprint management (create, list, get, close)

**Quick Examples:**
```bash
cd /Users/mattbruce/Documents/Projects/OpenClaw/Web/gantt-board/scripts

# Create task with all fields
./task.sh create --title "Fix bug" --description "Details" --type bug \
  --priority high --project "Gantt Board" --sprint "current" --assignee "Max" \
  --due-date "2026-03-01" --tags "urgent,backend"

# List tasks with filters
./task.sh list --status todo --priority high --project "Gantt Board"

# Update task
./task.sh update <task-id> --status in-progress --add-comment "Starting work"

# Create project
./project.sh create --name "New Project" --description "Project details"

# Create sprint
./sprint.sh create --name "Sprint 1" --project "Gantt Board" \
  --start-date 2026-02-24 --end-date 2026-03-07

# Bulk create from JSON
./task.sh bulk-create tasks.json --auto-create
```

**Features:**
- Auto-resolves names to IDs ("Gantt Board" → project UUID, "Max" → user UUID)
- Use "current" for the most recent active sprint
- JSON file input with `--file` and `--auto-create` for projects
- Interactive mode with `--interactive`

**Full Documentation:** See `scripts/README.md` in the gantt-board directory.

## Supabase for Gantt Board

- **URL:** https://qnatchrjlpehiijwtreh.supabase.co
- **Project ID:** qnatchrjlpehiijwtreh

## User IDs for Gantt Board

- **Matt:** 0a3e400c-3932-48ae-9b65-f3f9c6f26fe9
- **Max:** 9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa

---

## 🔄 Automated Task Worker (24/7)

**CRITICAL:** This is the PRIMARY workflow for all task work. Read this every session.

### Cron Job
- **Job ID:** `b9f3bbe6-bcb5-4483-8816-d044fd91c58a`
- **Schedule:** Every hour (24/7)
- **Scope:** Current sprint ONLY (ignores backlog/future sprints)
- **Statuses:** `open`, `todo`, `in-progress`
- **Assignee:** Max (9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa)

### Authentication
The Gantt Board API uses cookie-based auth. For server-to-server calls from this cron job, use the service role token:

```bash
# Set the token (already configured in environment)
export GANTT_MACHINE_TOKEN="50cd5e8fe3f895353f97c9ee64052c0b689b4eedf79259746413734d0a163cf8"
```

**Always use API endpoints via CLI tools or direct curl with the token. NEVER use direct Supabase REST calls.**

### When User Says "Create a Task"
1. Immediately add to Gantt Board via CLI: `./scripts/gantt-task-crud.sh create "Title" todo high ...`
2. Assign to current sprint
3. Do NOT create separate files (unless specifically asked)

### Reading Full Task Details (REQUIRED)
**CRITICAL: Use API endpoints, NOT direct Supabase.**

**Get current sprint via API:**
```bash
# Get current sprint ID (today's date)
TODAY=$(date +%Y-%m-%d)
curl -s "http://localhost:3000/api/sprints" \
  -H "Authorization: Bearer ${GANTT_MACHINE_TOKEN}" \
  -H "Content-Type: application/json" | jq '.sprints[] | select(.startDate <= '"$TODAY"' and .endDate >= '"$TODAY"')'
```

**Fetch tasks for current sprint via API:**
```bash
curl -s "http://localhost:3000/api/tasks?sprintId={current_sprint_id}&status=open,todo,in-progress" \
  -H "Authorization: Bearer ${GANTT_MACHINE_TOKEN}" \
  -H "Content-Type: application/json"
```

**Use CLI tools (API passthrough):**
```bash
cd /Users/mattbruce/Documents/Projects/OpenClaw/Web/gantt-board

# Get current sprint
./scripts/sprint.sh list --active --json

# List tasks in current sprint
./scripts/task.sh list --sprint current --status open,todo,in-progress --json

# Get full task details including comments
./scripts/task.sh get {task_id} --json
```

**READ in this order:**
1. **Title** - High-level goal
2. **Description** - Implementation details, steps
3. **Comments** (ALL of them) - What's done? What's next? What's left?

### Task Comment Format (APPEND to existing)
```json
{
  "id": "{timestamp}-{random}",
  "text": "[YYYY-MM-DD HH:MM] 🔄 In Progress\n\n**What was just done:**\n- Step completed\n\n**What is next:**\n- Next action\n\n**What is left to do:**\n- Remaining work",
  "replies": [],
  "createdAt": "YYYY-MM-DDTHH:MM:SSZ",
  "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa"
}
```

### Status Flow
```
open/todo → in-progress → review → (user validates) → done
    ↑
Add progress comment at EACH step
```

### Updating Tasks via CLI (API passthrough)
```bash
cd /Users/mattbruce/Documents/Projects/OpenClaw/Web/gantt-board

./scripts/task.sh update {task_id} --status in-progress --comment "[YYYY-MM-DD HH:MM] 🔄 In Progress

**What was just done:**
- Step completed

**What is next:**
- Next action

**What is left to do:**
- Remaining work"
```

**Direct API (if needed):**
```bash
curl -s -X PATCH "http://localhost:3000/api/tasks/{task_id}" \
  -H "Authorization: Bearer ${GANTT_MACHINE_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "in-progress",
    "comments": [EXISTING_COMMENTS_PLUS_NEW_ONE]
  }'
```

### Subagent Coordination
- Spawn subagents for parallel work
- Subagents READ same full task details
- Subagents REPORT back with progress
- YOU update task comments with their work

### User Workflow
- User creates task in Gantt Board
- Cron/auto picks it up hourly
- I work on it, log everything in comments
- Move to `review` when complete
- User validates, moves to `done`

## 👥 Subagent Team (Alice, Bob, Charlie)

**Location:** `/Users/mattbruce/.openclaw/workspace/agents/`

**Full Registry:** `agents/TEAM-REGISTRY.md`

### Team Members

| Name | Role | When to Spawn |
|------|------|---------------|
| **Alice-Researcher** | Research & tech evaluation | Need to choose technology, compare options, assess risks |
| **Bob-Implementer** | Code implementation | Requirements clear, ready to build |
| **Charlie-Tester** | Testing & code review | Implementation done, need quality gate |

### Standard Workflow

```
Complex Task:  Alice → Bob → Charlie → Done
               15m    30m     10m

Simple Task:   Bob → Charlie → Done
               20m    10m

Research Only: Alice → Report
               15m
```

### How to Spawn

**Alice (Research):**
```javascript
sessions_spawn({
  task: `Research: [question]\n\nContext: [background]\n\nRead your SOUL.md at: /Users/mattbruce/.openclaw/workspace/agents/alice-researcher/SOUL.md`,
  label: "Alice-Researcher",
  agentId: "main"
})
```

**Bob (Implement):**
```javascript
sessions_spawn({
  task: `Implement: [feature]\n\nBased on: [research/spec]\n\nRead your SOUL.md at: /Users/mattbruce/.openclaw/workspace/agents/bob-implementer/SOUL.md`,
  label: "Bob-Implementer",
  agentId: "main"
})
```

**Charlie (Test):**
```javascript
sessions_spawn({
  task: `Test: [feature]\n\nCode: [files]\n\nRead your SOUL.md at: /Users/mattbruce/.openclaw/workspace/agents/charlie-tester/SOUL.md`,
  label: "Charlie-Tester",
  agentId: "main"
})
```

### Each Agent Has
- **SOUL.md** - Personality, rules, boundaries
- **AGENTS.md** - Role definition, skills, typical tasks

### Announcement Format
- **Alice:** "Alice-Researcher ✅ 5 options evaluated – Recommended: X – Ready for Bob"
- **Bob:** "Bob-Implementer ✅ [feature] implemented – Ready for Charlie"
- **Charlie:** "Charlie-Tester ✅ 12 tests passed – 2 bugs found – Recommendation"

---

## Tavily AI Search (Configured)

**API Key:** Stored in `.env.tavily` (auto-loaded)

**Quick Commands:**
```bash
# Search
cd ~/.openclaw/workspace && ./tavily-search.sh "query" -n 5

# Extract URL content
cd ~/.openclaw/workspace && ./tavily-extract.sh "https://example.com"

# Deep research
cd ~/.openclaw/workspace && ./tavily-search.sh "query" --deep
```

**Note:** API key is automatically loaded from `.env.tavily`. No need to export manually.

---

## Daily Digest

**Schedule:** Every day at 7am CST (America/Chicago)  
**Posted to:** https://blog.twisteddevices.com  
**API Key:** `daily-digest-2026-secure-key`

---

Add whatever helps you do your job. This is your cheat sheet.
