Perch — Server Intelligence Skill
Perch is a self-hosted intelligence layer that watches, diagnoses, and (within strict bounds) heals Linux servers managed by RunCloud — or any plain Ubuntu/Debian/AlmaLinux box. It runs as an MCP server, an HTTP API, and a Telegram bot. The brain (SQLite) accumulates per-server, per-webapp knowledge over time.
This skill teaches Claude how to use Perch correctly and safely.
Identity
- What it is: Server intelligence layer. Reads everything, learns over time, talks to you in plain English.
- What it isn't: SaaS, monitoring dashboard, or runtime dependency. No vendor lock-in. Free forever.
- How it talks: Telegram, Slack, Claude Code MCP, HTTP API, CLI — same intelligence, multiple surfaces.
- Where data lives:
~/.perch/brain.db (SQLite, on the user's server) and ~/.perch/vault.json (AES-256-GCM encrypted credentials). Nothing leaves the box unless the user explicitly configures a webhook.
Architecture
You (Claude Code / Telegram / Slack / HTTP)
↓
PERCH CORE
├── brain.ts SQLite KB (servers, webapps, problems, plugins, knowledge, actions_log)
├── gateway.ts Friendly alert formatter (multi-channel)
├── ssh-enhanced.ts SSH with TOFU host verification + WP-CLI helper
├── vault.ts AES-256-GCM credential vault
└── redact.ts Centralized privacy redactor (16 patterns)
↓
MODULES
├── wordpress/ db, plugins, security, backup, images, perf, errors
├── api/server.ts HTTP wrapper for external integration
└── monitor.sh 14-rule cron automation engine
/perch_* MCP Tool Catalog
Server (RunCloud API)
list_servers, get_server, get_server_stats, get_server_health
control_service, clean_server_disk, get_server_logs
update_ssh_settings, update_server_autoupdate
- 130+ more — see
src/index.ts
Server (SSH)
ssh_run_command — arbitrary SSH (validate inputs)
ssh_server_status, ssh_smart_fix, ssh_restart_service
ssh_kill_orphans, ssh_disk_cleanup, ssh_check_ports
ssh_wp_cli, ssh_artisan, ssh_tail_log
WordPress
perch_wp_db_audit — autoload, transients, orphans, fragmentation
perch_wp_db_clean — drop expired transients/sessions (idempotent)
perch_wp_plugins — list + Wordfence Intelligence vulnerability scan
perch_wp_plugin_update, perch_wp_plugin_deactivate (logs to undo)
perch_wp_security — 12-check hardening audit
perch_wp_backup — backup health
perch_wp_images_scan, perch_wp_images_optimize
perch_wp_perf — performance snapshot
perch_wp_errors — diagnose PHP fatals + white screens
Vault
perch_vault_put, perch_vault_get, perch_vault_list, perch_vault_delete
Brain & Intelligence
perch_brain — KB summary
perch_webapp_history — per-webapp problem history
perch_brain_search — FTS5 search across all problems
perch_actions_log — recent destructive actions
perch_undo — reverse the last destructive action
perch_multi_server_dashboard — one-shot all-server status
perch_self_update — pull latest, rebuild, restart
RunCloud Gotchas (CRITICAL — get these right)
| Wrong |
Right (RunCloud) |
nginx |
nginx-rc |
nginx.service |
nginx-rc.service |
/etc/nginx/ |
/etc/nginx-rc/ |
php8.x-fpm |
php8x-fpm-rc |
/etc/nginx/conf.d/ (overwritten) |
/etc/nginx-rc/extra.d/ (custom-safe) |
/var/log/nginx/error.log |
/var/log/nginx-rc/error.log |
/var/www/ |
/home/{appuser}/webapps/{appname}/ |
www-data |
each webapp's own system user |
Never edit /etc/nginx-rc/conf.d/ — RunCloud regenerates these and your changes vanish. Use /etc/nginx-rc/extra.d/ for custom blocks.
PHP-FPM logs: /home/{user}/logs/php_error.log per webapp.
Safety Policy (READ THIS BEFORE EVERY DESTRUCTIVE TOOL CALL)
Auto-allowed (no confirm needed)
- Restart crashed
nginx-rc, php*-fpm-rc, MySQL/MariaDB
- Kill orphan processes (PPID=1)
- Truncate (not delete) log files >50MB
- SSL renewal when <7 days remain
- Clear expired WordPress transients (WP-CLI built-in safe op)
- Clear
/tmp PHP sessions older than 24h
Confirm-required (always ask first)
- Plugin deactivation (
perch_wp_plugin_deactivate)
- Plugin updates
- WP core update
- Database table changes (OPTIMIZE/REPAIR)
- File deletions
- Nginx config edits beyond reload
- Service stops without restart
- Reboot
Never auto, ever
- Backup restoration
- DELETE/UPDATE on user data tables
rm outside /tmp
- User account changes
- Hetzner-level shutdown / rebuild
Master Key Handling
PERCH_MASTER_KEY (env var) is the only thing protecting the credential vault. Rules:
- Never echo the key in MCP responses, logs, or alerts.
- Never save the key to brain.db or any file Perch creates (it lives only in
~/.perch/.env mode 0600, sourced by systemd EnvironmentFile).
- If the user asks "what's my master key?" — refuse and direct them to their password manager /
~/.perch/.env.
- Vault rotation requires the OLD key as input — see
npm run vault rotate -- --old-key=....
Common Workflows
"Why is mysite.com white-screening?"
perch_wp_errors with domain → returns root cause + suggested fix
- If
fixableByPerch: true and user confirms → perch_wp_plugin_deactivate
perch_wp_errors again to verify the fatal cleared
- Tell user what was disabled and why
"Audit all my WP sites"
list_servers → for each server, list_webapps
- For each WP webapp:
perch_wp_db_audit, perch_wp_security, perch_wp_plugins
- Summarize per-site, surface critical issues first
"Rotate my RunCloud API key"
perch_vault_get with runcloud:apikey (current value, redact in summary)
- User generates new key in RunCloud panel
perch_vault_put with the new value
- Verify with
ping tool (returns pong if auth works)
"Update Perch and tell me what changed"
perch_self_update with dryRun: true first (returns commit count + changelog)
- Show user the changelog, ask to proceed
perch_self_update (real) if confirmed
"What do you know about disk-full incidents?"
perch_brain_search with query "disk full"
- Group by server / by month
- If patterns emerge ("happens after weekly backup"), surface that
Anti-Patterns (Claude must NEVER)
- ❌ Echo
PERCH_MASTER_KEY, vault values, or wp-config DB_PASSWORD into chat output
- ❌ Modify
/etc/nginx-rc/conf.d/ files
- ❌ Run
perch_wp_plugin_deactivate without explicit user confirmation
- ❌ Run any
*delete* tool without dry-run first
- ❌ Hard-code RunCloud paths assuming Ubuntu nginx defaults — always use the RunCloud variants
- ❌ Tell the user "I'll just restart nginx" without first checking
nginx -t config validity
- ❌ Stuff entire DB query results into chat — use
perch_brain_search summaries
- ❌ Ignore the safety whitelist/blacklist — defer to docs/safety.md when uncertain
When to Trigger This Skill
Auto-load when the user mentions any of:
- "perch", "/perch_X", "the perch tool"
- "runcloud", "nginx-rc", "RunCloud server"
- "site is down", "white screen", "500 error" (and they own the server)
- "audit my WordPress site", "check plugin vulnerabilities", "wp_options bloat"
- "ssh into [host I own]", "restart nginx-rc / php-fpm"
- "perch.adityaarsharma.com" or "github.com/adityaarsharma/perch"
Source of Truth
The repo at https://github.com/adityaarsharma/perch is canonical. When this skill conflicts with the repo, the repo wins. Specifically read:
README.md — vision + comparison + connectors
docs/install.md — install paths
docs/automation.md — 14 cron rules + thresholds
docs/safety.md — auto/confirm/never policy (verbatim authority)
docs/master-key.md — encryption key lifecycle
docs/runcloud.md — RunCloud-specific operational reference
src/index.ts — authoritative tool list (tools array)
Installation
# Drop this skill where Claude Code looks for skills
mkdir -p ~/.claude/skills/perch
cp /path/to/perch/skills/perch/SKILL.md ~/.claude/skills/perch/SKILL.md
# Restart Claude Code
Skill version 1.0 — generated April 2026 from the live Perch codebase.
1---2name: perch3description: Server intelligence layer for RunCloud-managed Linux servers. Use when the user mentions Perch, /perch_*, RunCloud, nginx-rc, server intelligence, server diagnosis, WordPress site auditing, plugin vulnerability scanning, or any time they want to investigate, monitor, or heal a server they own.4---5
6# Perch — Server Intelligence Skill
7
8Perch is a self-hosted intelligence layer that watches, diagnoses, and (within strict bounds) heals Linux servers managed by RunCloud — or any plain Ubuntu/Debian/AlmaLinux box. It runs as an MCP server, an HTTP API, and a Telegram bot. The brain (SQLite) accumulates per-server, per-webapp knowledge over time.
9
10This skill teaches Claude how to use Perch correctly and safely.
11
12## Identity
13
14- **What it is**: Server intelligence layer. Reads everything, learns over time, talks to you in plain English.
15- **What it isn't**: SaaS, monitoring dashboard, or runtime dependency. No vendor lock-in. Free forever.
16- **How it talks**: Telegram, Slack, Claude Code MCP, HTTP API, CLI — same intelligence, multiple surfaces.
17- **Where data lives**: `~/.perch/brain.db` (SQLite, on the user's server) and `~/.perch/vault.json` (AES-256-GCM encrypted credentials). Nothing leaves the box unless the user explicitly configures a webhook.
18
19## Architecture
20
21```
22You (Claude Code / Telegram / Slack / HTTP)
23 ↓
24PERCH CORE
25 ├── brain.ts SQLite KB (servers, webapps, problems, plugins, knowledge, actions_log)
26 ├── gateway.ts Friendly alert formatter (multi-channel)
27 ├── ssh-enhanced.ts SSH with TOFU host verification + WP-CLI helper
28 ├── vault.ts AES-256-GCM credential vault
29 └── redact.ts Centralized privacy redactor (16 patterns)
30 ↓
31MODULES
32 ├── wordpress/ db, plugins, security, backup, images, perf, errors
33 ├── api/server.ts HTTP wrapper for external integration
34 └── monitor.sh 14-rule cron automation engine
35```
36
37## /perch_* MCP Tool Catalog
38
39### Server (RunCloud API)
40- `list_servers`, `get_server`, `get_server_stats`, `get_server_health`
41- `control_service`, `clean_server_disk`, `get_server_logs`
42- `update_ssh_settings`, `update_server_autoupdate`
43- 130+ more — see `src/index.ts`
44
45### Server (SSH)
46- `ssh_run_command` — arbitrary SSH (validate inputs)
47- `ssh_server_status`, `ssh_smart_fix`, `ssh_restart_service`
48- `ssh_kill_orphans`, `ssh_disk_cleanup`, `ssh_check_ports`
49- `ssh_wp_cli`, `ssh_artisan`, `ssh_tail_log`
50
51### WordPress
52- `perch_wp_db_audit` — autoload, transients, orphans, fragmentation
53- `perch_wp_db_clean` — drop expired transients/sessions (idempotent)
54- `perch_wp_plugins` — list + Wordfence Intelligence vulnerability scan
55- `perch_wp_plugin_update`, `perch_wp_plugin_deactivate` (logs to undo)
56- `perch_wp_security` — 12-check hardening audit
57- `perch_wp_backup` — backup health
58- `perch_wp_images_scan`, `perch_wp_images_optimize`
59- `perch_wp_perf` — performance snapshot
60- `perch_wp_errors` — diagnose PHP fatals + white screens
61
62### Vault
63- `perch_vault_put`, `perch_vault_get`, `perch_vault_list`, `perch_vault_delete`
64
65### Brain & Intelligence
66- `perch_brain` — KB summary
67- `perch_webapp_history` — per-webapp problem history
68- `perch_brain_search` — FTS5 search across all problems
69- `perch_actions_log` — recent destructive actions
70- `perch_undo` — reverse the last destructive action
71- `perch_multi_server_dashboard` — one-shot all-server status
72- `perch_self_update` — pull latest, rebuild, restart
73
74## RunCloud Gotchas (CRITICAL — get these right)
75
76| Wrong | Right (RunCloud) |
77|---|---|
78| `nginx` | `nginx-rc` |
79| `nginx.service` | `nginx-rc.service` |
80| `/etc/nginx/` | `/etc/nginx-rc/` |
81| `php8.x-fpm` | `php8x-fpm-rc` |
82| `/etc/nginx/conf.d/` (overwritten) | `/etc/nginx-rc/extra.d/` (custom-safe) |
83| `/var/log/nginx/error.log` | `/var/log/nginx-rc/error.log` |
84| `/var/www/` | `/home/{appuser}/webapps/{appname}/` |
85| `www-data` | each webapp's own system user |
86
87**Never** edit `/etc/nginx-rc/conf.d/` — RunCloud regenerates these and your changes vanish. Use `/etc/nginx-rc/extra.d/` for custom blocks.
88
89PHP-FPM logs: `/home/{user}/logs/php_error.log` per webapp.
90
91## Safety Policy (READ THIS BEFORE EVERY DESTRUCTIVE TOOL CALL)
92
93### Auto-allowed (no confirm needed)
94- Restart crashed `nginx-rc`, `php*-fpm-rc`, MySQL/MariaDB
95- Kill orphan processes (PPID=1)
96- Truncate (not delete) log files >50MB
97- SSL renewal when <7 days remain
98- Clear expired WordPress transients (WP-CLI built-in safe op)
99- Clear `/tmp` PHP sessions older than 24h
100
101### Confirm-required (always ask first)
102- Plugin deactivation (`perch_wp_plugin_deactivate`)
103- Plugin updates
104- WP core update
105- Database table changes (OPTIMIZE/REPAIR)
106- File deletions
107- Nginx config edits beyond reload
108- Service stops without restart
109- Reboot
110
111### Never auto, ever
112- Backup restoration
113- DELETE/UPDATE on user data tables
114- `rm` outside `/tmp`
115- User account changes
116- Hetzner-level shutdown / rebuild
117
118## Master Key Handling
119
120`PERCH_MASTER_KEY` (env var) is the only thing protecting the credential vault. Rules:
121
122- **Never** echo the key in MCP responses, logs, or alerts.
123- **Never** save the key to brain.db or any file Perch creates (it lives only in `~/.perch/.env` mode 0600, sourced by systemd EnvironmentFile).
124- If the user asks "what's my master key?" — refuse and direct them to their password manager / `~/.perch/.env`.
125- Vault rotation requires the OLD key as input — see `npm run vault rotate -- --old-key=...`.
126
127## Common Workflows
128
129### "Why is mysite.com white-screening?"
1301. `perch_wp_errors` with domain → returns root cause + suggested fix
1312. If `fixableByPerch: true` and user confirms → `perch_wp_plugin_deactivate`
1323. `perch_wp_errors` again to verify the fatal cleared
1334. Tell user what was disabled and why
134
135### "Audit all my WP sites"
1361. `list_servers` → for each server, `list_webapps`
1372. For each WP webapp: `perch_wp_db_audit`, `perch_wp_security`, `perch_wp_plugins`
1383. Summarize per-site, surface critical issues first
139
140### "Rotate my RunCloud API key"
1411. `perch_vault_get` with `runcloud:apikey` (current value, redact in summary)
1422. User generates new key in RunCloud panel
1433. `perch_vault_put` with the new value
1444. Verify with `ping` tool (returns pong if auth works)
145
146### "Update Perch and tell me what changed"
1471. `perch_self_update` with `dryRun: true` first (returns commit count + changelog)
1482. Show user the changelog, ask to proceed
1493. `perch_self_update` (real) if confirmed
150
151### "What do you know about disk-full incidents?"
1521. `perch_brain_search` with query "disk full"
1532. Group by server / by month
1543. If patterns emerge ("happens after weekly backup"), surface that
155
156## Anti-Patterns (Claude must NEVER)
157
158- ❌ Echo `PERCH_MASTER_KEY`, vault values, or wp-config DB_PASSWORD into chat output
159- ❌ Modify `/etc/nginx-rc/conf.d/` files
160- ❌ Run `perch_wp_plugin_deactivate` without explicit user confirmation
161- ❌ Run any `*delete*` tool without dry-run first
162- ❌ Hard-code RunCloud paths assuming Ubuntu nginx defaults — always use the RunCloud variants
163- ❌ Tell the user "I'll just restart nginx" without first checking `nginx -t` config validity
164- ❌ Stuff entire DB query results into chat — use `perch_brain_search` summaries
165- ❌ Ignore the safety whitelist/blacklist — defer to docs/safety.md when uncertain
166
167## When to Trigger This Skill
168
169Auto-load when the user mentions any of:
170- "perch", "/perch_X", "the perch tool"
171- "runcloud", "nginx-rc", "RunCloud server"
172- "site is down", "white screen", "500 error" (and they own the server)
173- "audit my WordPress site", "check plugin vulnerabilities", "wp_options bloat"
174- "ssh into [host I own]", "restart nginx-rc / php-fpm"
175- "perch.adityaarsharma.com" or "github.com/adityaarsharma/perch"
176
177## Source of Truth
178
179The repo at `https://github.com/adityaarsharma/perch` is canonical. When this skill conflicts with the repo, the repo wins. Specifically read:
180
181- `README.md` — vision + comparison + connectors
182- `docs/install.md` — install paths
183- `docs/automation.md` — 14 cron rules + thresholds
184- `docs/safety.md` — auto/confirm/never policy (verbatim authority)
185- `docs/master-key.md` — encryption key lifecycle
186- `docs/runcloud.md` — RunCloud-specific operational reference
187- `src/index.ts` — authoritative tool list (`tools` array)
188
189## Installation
190
191```bash
192# Drop this skill where Claude Code looks for skills
193mkdir -p ~/.claude/skills/perch
194cp /path/to/perch/skills/perch/SKILL.md ~/.claude/skills/perch/SKILL.md
195# Restart Claude Code
196```
197
198---
199
200*Skill version 1.0 — generated April 2026 from the live Perch codebase.*