# TOOLS.md - Local Notes

Skills define _how_ tools work. This file is for _your_ specifics — setup-specific stuff.

## Browser Tool (IMPORTANT)

**Always use `profile="openclaw"`** — not chrome (requires manually attached tab).

```bash
openclaw browser start --browser-profile openclaw
```

If "device token mismatch" or "no tab connected" → switch to openclaw profile.

---

## API Keys (XDG-compliant)

| Service | Location |
|---------|----------|
| OpenAI | `~/.config/openai/api-key` |
| PostHog | `~/.config/posthog/api-key` |
| ClickUp | `~/.config/clickup/finspend.json` |

**DO NOT use `.env` files in `.openclaw/`** — all credentials go in `~/.config/<service>/`.

---

## Context7 (Live Documentation)

- **Purpose:** Real-time library/framework docs
- **API Key:** `ctx7sk-13f7b82d-aadf-41e3-989a-08ac3283a95d`
- **Config:** `~/.claude.json` (user-level, all Claude Code sessions)
- **Tools:** `resolve_library_id`, `get_library_docs`

---

## Symphony Suite Landing Pages (Cloud Run)

- **GCP Project:** `theagency-ai` ← ALL Symphony Suite deployments
- **Region:** us-central1 (except theagency-landing: asia-southeast1)

| Domain | Service |
|--------|---------|
| alignlyhq.com | alignly |
| clocklane.com | clocklane |
| encoreclients.com | encore |
| getworklane.com | worklane |
| overtureinsights.com | overture |
| vectorpm.io | vector |
| agency.symph.ai / theagency.symph.ai / agency.symph.co | theagency-landing (asia-southeast1) |

```bash
export PATH="/home/aria/google-cloud-sdk/bin:$PATH"
cd /home/aria/projects/<service>
gcloud run deploy <service> --source . --region=<region> --project=theagency-ai --allow-unauthenticated
```

---

## Cloud DNS

- **GCP Project:** `symph-dns` | **Zone:** `symph-dot-co` | **DNSSEC:** On

---

## GitHub

| Org | Use |
|-----|-----|
| **SymphonyAgents** | ALL new repos (Feb 2026+) |
| **symphco** | Legacy only |

- **Service Account:** symphdevtools (dev.tools@symph.co) | **Auth:** PAT | **Protocol:** SSH

**New repos:**
```bash
gh repo create SymphonyAgents/<name> --private
gh api -X PUT "/orgs/SymphonyAgents/teams/symphony-devs/repos/SymphonyAgents/<name>" -f permission=push
```

**New members:** `gh api -X PUT "/orgs/SymphonyAgents/teams/symphony-devs/memberships/<username>" -f role=member`

**Access policy (Raven 2026-02-10):** NEVER add individual collaborators unless Raven requests it. Always add symphony-devs team. Auto-add `codewithbjim` (standing instruction).

---

## Agency App Starter Template

- **Repo:** `git@github.com:symphco/agency-app-starter.git`
- **Stack:** Next.js 15, Tailwind v4, shadcn/ui, Firebase (Firestore + Auth)
- **Clone:** `git clone git@github.com:symphco/agency-app-starter.git {slug} && cd {slug} && rm -rf .git && git init`

---

## Firebase

- **GCP Folder:** `436092539710` (Symph Products) | **Naming:** `symph-{slug}`

**Central SA (ALWAYS use for infra):**
```
~/.config/gcloud/aria-firebase-admin.json
aria-firebase-admin@the-agency-symph.iam.gserviceaccount.com
```

**I can do myself (don't ask users):**
```bash
# Link billing
gcloud billing projects link <project-id> --billing-account=01F3D7-6E8F01-1E2163

# Custom GCS bucket (use instead of .appspot.com default)
gsutil mb -p <project-id> -l us-central1 gs://<bucket-name>

# Create project
export GOOGLE_APPLICATION_CREDENTIALS="$HOME/.config/gcloud/aria-firebase-admin.json"
firebase projects:create symph-{slug} --display-name "Name" --folder 436092539710

# Deploy rules
firebase deploy --only firestore:rules --project symph-{slug}
```

**Firestore namespaces:** `dev_*`, `staging_*`, `prod_*`
**DEV deploy:** Caddy (`{slug}.dev.apps.symph.co`) | **PROD:** Cloud Run (NOT Firebase App Hosting)

---

## Product Context & Assets Hub

- **All products:** <https://assets.landing.symph.co/>
- **Logos only:** <https://logos.landing.symph.co/>

---

## Caddy (Dev Web Apps)

- **Domain:** `*.dev.apps.symph.co` | **Ports:** 3001-3100
- **Landing pages:** `*.landing.symph.co` | **Ports:** 3100-3199
- **Skill:** `caddy-manager` (add / remove / list / ports)

### External State Files

| File | Purpose |
|------|---------|
| `agency/infra/caddy-ports.json` | Port allocation (git-backed, source of truth) |
| `agency/products-registry.yaml` | Master manifest |
| `agency/infra/bootstrap.sh` | Full VPS recovery |
| `/home/aria/projects/.aria-logs/` | App stdout/stderr logs |

### App Process Management

Pure port-based — no PID files:
```bash
lsof -ti :<port>                         # Check if running
lsof -ti :<port> | xargs kill -TERM      # Stop
cd /home/aria/products/<slug>/apps/main && npm run start -- -p <port>  # Start
```

---

## Symphony (Agency UI)

- **Location:** `/home/aria/projects/symph-agency/`
- **App URL:** `symphony.symph.co` | **Dashboard:** `symphony.symph.co/dashboard`
- **Landing:** `theagency.symph.ai` (public marketing, NOT the app)
- **Port:** 4000 | **Process:** PM2

**Deploy (ALWAYS use deploy.sh):**
```bash
cd /home/aria/projects/symph-agency && ./deploy.sh
```
Direct `npm run build` → 502s. Always use `deploy.sh`.

**If down:** `pm2 start npm --name "symph-agency" -- start -- -p 4000`

---

## Discord Channels

| Channel | ID | Purpose |
|---------|-----|---------|
| #aria | 1467744183803580548 | Conversations, requests |
| #aria-status | 1471453583890448553 | Read-only status feed |
| #suggestions | 1469210442009153679 | Skills + improvements |

**New member greeting:** "Welcome to Symph Agency! 👋 Essential reading: <https://discord.com/channels/1467742341111611610/1467742347000418458/1469208335470428354>"

---

## External State Files

| Path | Purpose |
|------|---------|
| `/home/aria/products/<slug>/` | Product repos |
| `/home/aria/products/<slug>/apps/main/` | App codebases |
| `/home/aria/agency-jobs/` | Ephemeral job files (symlinked from `agency/jobs/`) |
| `/home/aria/projects/` | Platform infra ONLY |

---

## Google Drive (Marketing Assets)

- **Shared Drive:** "Symph Agency" (`0APueXYbYyRzNUk9PVA`)
- **Credentials:** `/home/aria/.config/gcloud/aria-drive-sync.json`
- **rclone remote:** `gdrive:` (`~/.config/rclone/rclone.conf`)
- **Local uploads:** `/home/aria/marketing-assets/uploads/`
- **Sync:** every 30 min via crontab (`sync-to-drive.sh`)
- **Metadata:** `agency/marketing/assets.yaml` (git-tracked, no binaries)

---

## Workspace Organization (Raven 2026-02-17)

| Content | Location |
|---------|----------|
| Product assets | `/home/aria/products/<slug>/assets/` or `marketing/` |
| Non-product marketing | `/home/aria/marketing-assets/uploads/` |
| Agency config/skills/memory | `/home/aria/.openclaw/workspace/` |
| Platform infra | `/home/aria/projects/` |

**NEVER save in workspace root:** PNG, JPG, MP4, MP3, TTF, or any generated content.

---

## Issue Tracking

**Location:** `agency/issues/` | **Index:** `agency/issues/INDEX.md`
**Prefixes:** `ARIA-###` (agent tasks) | `AGY-###` (agency platform) | `INFRA-###` (infrastructure)
**Priorities:** P0 critical → P3 low. P0/P1 auto-post to #aria-status.

---

## Git Worktrees

**Skill:** `worktree-manager` | **Scripts:** `skills/worktree-manager/scripts/`

```bash
SKILL_DIR="/home/aria/.openclaw/workspace/skills/worktree-manager/scripts"
$SKILL_DIR/create-worktree.sh <slug> <task-id> <requester> <requester-id> "description"
$SKILL_DIR/merge-worktree.sh <slug> <task-id>
$SKILL_DIR/cleanup-worktree.sh <slug> <task-id>
$SKILL_DIR/check-stale.sh
```

---

## Image Generation (CRITICAL — Gemini only, NO DALL-E)

**⛔ NEVER use DALL-E or OpenAI for image generation.**
**✅ ALWAYS use nano-banana-pro (Gemini 3 Pro Image)**

```bash
uv run /home/linuxbrew/.linuxbrew/lib/node_modules/openclaw/skills/nano-banana-pro/scripts/generate_image.py \
  --prompt "your prompt here" --filename "output.png" --resolution 1K
```

Resolutions: `1K` (default), `2K`, `4K`. Edit mode: add `-i /path/to/input.png`.
**Text/caption generation can still use OpenAI.** Only image gen uses nano-banana-pro.

---

## PDF Reading

```bash
python3 scripts/read-pdf.py /path/to/file.pdf        # Full text
python3 scripts/read-pdf.py /path/to/file.pdf --pages 5   # First N pages
python3 scripts/read-pdf.py /path/to/file.pdf --summary   # Preview
```

PDFs from attachments land in `/home/aria/.openclaw/media/inbound/`.

---

## SymphPay (Quick Reference)

| Env | Base URL | Admin Key |
|-----|----------|-----------|
| Staging | `https://symph-pay-test.df.r.appspot.com/` | `INTERNAL_ADMIN` |
| Production | `https://symph-pay.df.r.appspot.com/` | `R227Nnt5U` |

**Wiki:** https://github.com/symphco/symph-pay/wiki | **Full docs:** `symph-pay` skill

---

## ReadStreak QA Protocol (Nick's Rule — 2026-02-12)

**Before saying ANY fix is done:**
1. Build completes without errors
2. Kill old server: `fuser -k PORT/tcp`
3. Start new server
4. Verify BUILD_ID served matches `.next/BUILD_ID`
5. 5 rounds of testing — different flows/states
6. Hard refresh / incognito test
7. Check server logs for errors

**NEVER tell user to hard refresh** — stale cache = my deployment failure.

---

## PostHog Analytics

- **Project ID:** 316683 | **Host:** us.posthog.com
- **Personal API Key:** `~/.config/posthog/api-key`

| Dashboard | ID |
|-----------|-----|
| Product Lifecycle | 1287840 |
| Build & Design | 1287841 |
| Sales Pipeline | 1287842 |
| User Engagement | 1287843 |

**Key:** Dashboard queries MUST use `InsightVizNode` wrapper, not raw `TrendsQuery`.
**Skill:** `posthog` (scripts for check/fix/create insights)

---

## ClickUp (FinSpend)

- **Config:** `~/.config/clickup/finspend.json`
- **Team:** Symph (`7533817`) | **List:** `901815112591`
- **API:** `curl -H "Authorization: $(jq -r .api_key ~/.config/clickup/finspend.json)" "https://api.clickup.com/api/v2/list/901815112591/task"`

---

## SymphOs (Internal HR System)

- **Repo:** `git@github.com:symphco/symphos-v2.git` | **Location:** `/home/aria/projects/symphos-v2/`
- **Node:** v20.11.1 (use `nvm use 20.11.1`)
- **Web:** https://symphos.dev.apps.symph.co | **API:** https://symphos-api.dev.apps.symph.co/api

**⚠️ CRITICAL WORKFLOW:** Always branch from `main`, create PRs to `main`, no direct pushes, DO NOT use worktrees, DO NOT follow agency product pipeline.

```bash
cd /home/aria/projects/symphos-v2 && source ~/.nvm/nvm.sh && nvm use 20.11.1
NODE_ENV=local nohup npx nx serve api > /tmp/symphos-api.log 2>&1 &   # port 3333
nohup npx nx serve web --port=4200 > /tmp/symphos-web.log 2>&1 &       # port 4200
```

---

## Receiving Credentials from Users

Ask users to share via **Bitwarden Send** (Text Send, no password). Get the link in chat.

---

## Leonardo AI

- **API Key:** `~/.env` as `LEONARDO_API_KEY`
- **Docs:** <https://docs.leonardo.ai/>

---

## Git Access Priority (Raven 2026-02-19)

Default to git SSH operations first. Use `gh` CLI only for GitHub-specific features (PRs, issues, API).

---

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