docs: harden homelab skill pack

This commit is contained in:
Affaan Mustafa 2026-05-12 21:14:52 -04:00
parent 13f4b2ce7f
commit 5a7b774197
9 changed files with 61 additions and 38 deletions

View File

@ -11,7 +11,7 @@
{ {
"name": "ecc", "name": "ecc",
"source": "./", "source": "./",
"description": "The most comprehensive Claude Code plugin — 60 agents, 225 skills, 75 legacy command shims, selective install profiles, and production-ready hooks for TDD, security scanning, code review, and continuous learning", "description": "The most comprehensive Claude Code plugin — 60 agents, 228 skills, 75 legacy command shims, selective install profiles, and production-ready hooks for TDD, security scanning, code review, and continuous learning",
"version": "2.0.0-rc.1", "version": "2.0.0-rc.1",
"author": { "author": {
"name": "Affaan Mustafa", "name": "Affaan Mustafa",

View File

@ -1,7 +1,7 @@
{ {
"name": "ecc", "name": "ecc",
"version": "2.0.0-rc.1", "version": "2.0.0-rc.1",
"description": "Battle-tested Claude Code plugin for engineering teams — 60 agents, 225 skills, 75 legacy command shims, production-ready hooks, and selective install workflows evolved through continuous real-world use", "description": "Battle-tested Claude Code plugin for engineering teams — 60 agents, 228 skills, 75 legacy command shims, production-ready hooks, and selective install workflows evolved through continuous real-world use",
"author": { "author": {
"name": "Affaan Mustafa", "name": "Affaan Mustafa",
"url": "https://x.com/affaanmustafa" "url": "https://x.com/affaanmustafa"

View File

@ -1,6 +1,6 @@
# Everything Claude Code (ECC) — Agent Instructions # Everything Claude Code (ECC) — Agent Instructions
This is a **production-ready AI coding plugin** providing 60 specialized agents, 225 skills, 75 commands, and automated hook workflows for software development. This is a **production-ready AI coding plugin** providing 60 specialized agents, 228 skills, 75 commands, and automated hook workflows for software development.
**Version:** 2.0.0-rc.1 **Version:** 2.0.0-rc.1
@ -150,7 +150,7 @@ Troubleshoot failures: check test isolation → verify mocks → fix implementat
``` ```
agents/ — 60 specialized subagents agents/ — 60 specialized subagents
skills/ — 225 workflow skills and domain knowledge skills/ — 228 workflow skills and domain knowledge
commands/ — 75 slash commands commands/ — 75 slash commands
hooks/ — Trigger-based automations hooks/ — Trigger-based automations
rules/ — Always-follow guidelines (common + per-language) rules/ — Always-follow guidelines (common + per-language)

View File

@ -358,7 +358,7 @@ If you stacked methods, clean up in this order:
/plugin list ecc@ecc /plugin list ecc@ecc
``` ```
**That's it!** You now have access to 60 agents, 225 skills, and 75 legacy command shims. **That's it!** You now have access to 60 agents, 228 skills, and 75 legacy command shims.
### Dashboard GUI ### Dashboard GUI
@ -1362,7 +1362,7 @@ The configuration is automatically detected from `.opencode/opencode.json`.
|---------|-------------|----------|--------| |---------|-------------|----------|--------|
| Agents | PASS: 60 agents | PASS: 12 agents | **Claude Code leads** | | Agents | PASS: 60 agents | PASS: 12 agents | **Claude Code leads** |
| Commands | PASS: 75 commands | PASS: 35 commands | **Claude Code leads** | | Commands | PASS: 75 commands | PASS: 35 commands | **Claude Code leads** |
| Skills | PASS: 225 skills | PASS: 37 skills | **Claude Code leads** | | Skills | PASS: 228 skills | PASS: 37 skills | **Claude Code leads** |
| Hooks | PASS: 8 event types | PASS: 11 events | **OpenCode has more!** | | Hooks | PASS: 8 event types | PASS: 11 events | **OpenCode has more!** |
| Rules | PASS: 29 rules | PASS: 13 instructions | **Claude Code leads** | | Rules | PASS: 29 rules | PASS: 13 instructions | **Claude Code leads** |
| MCP Servers | PASS: 14 servers | PASS: Full | **Full parity** | | MCP Servers | PASS: 14 servers | PASS: Full | **Full parity** |
@ -1467,7 +1467,7 @@ ECC is the **first plugin to maximize every major AI coding tool**. Here's how e
|---------|------------|------------|-----------|----------| |---------|------------|------------|-----------|----------|
| **Agents** | 60 | Shared (AGENTS.md) | Shared (AGENTS.md) | 12 | | **Agents** | 60 | Shared (AGENTS.md) | Shared (AGENTS.md) | 12 |
| **Commands** | 75 | Shared | Instruction-based | 35 | | **Commands** | 75 | Shared | Instruction-based | 35 |
| **Skills** | 225 | Shared | 10 (native format) | 37 | | **Skills** | 228 | Shared | 10 (native format) | 37 |
| **Hook Events** | 8 types | 15 types | None yet | 11 types | | **Hook Events** | 8 types | 15 types | None yet | 11 types |
| **Hook Scripts** | 20+ scripts | 16 scripts (DRY adapter) | N/A | Plugin hooks | | **Hook Scripts** | 20+ scripts | 16 scripts (DRY adapter) | N/A | Plugin hooks |
| **Rules** | 34 (common + lang) | 34 (YAML frontmatter) | Instruction-based | 13 instructions | | **Rules** | 34 (common + lang) | 34 (YAML frontmatter) | Instruction-based | 13 instructions |

View File

@ -160,7 +160,7 @@ Copy-Item -Recurse rules/typescript "$HOME/.claude/rules/"
/plugin list ecc@ecc /plugin list ecc@ecc
``` ```
**完成!** 你现在可以使用 60 个代理、225 个技能和 75 个命令。 **完成!** 你现在可以使用 60 个代理、228 个技能和 75 个命令。
### multi-* 命令需要额外配置 ### multi-* 命令需要额外配置

View File

@ -1,6 +1,6 @@
# Everything Claude Code (ECC) — 智能体指令 # Everything Claude Code (ECC) — 智能体指令
这是一个**生产就绪的 AI 编码插件**,提供 60 个专业代理、225 项技能、75 条命令以及自动化钩子工作流,用于软件开发。 这是一个**生产就绪的 AI 编码插件**,提供 60 个专业代理、228 项技能、75 条命令以及自动化钩子工作流,用于软件开发。
**版本:** 2.0.0-rc.1 **版本:** 2.0.0-rc.1
@ -147,7 +147,7 @@
``` ```
agents/ — 60 个专业子代理 agents/ — 60 个专业子代理
skills/ — 225 个工作流技能和领域知识 skills/ — 228 个工作流技能和领域知识
commands/ — 75 个斜杠命令 commands/ — 75 个斜杠命令
hooks/ — 基于触发的自动化 hooks/ — 基于触发的自动化
rules/ — 始终遵循的指导方针(通用 + 每种语言) rules/ — 始终遵循的指导方针(通用 + 每种语言)

View File

@ -224,7 +224,7 @@ Copy-Item -Recurse rules/typescript "$HOME/.claude/rules/"
/plugin list ecc@ecc /plugin list ecc@ecc
``` ```
**搞定!** 你现在可以使用 60 个智能体、225 项技能和 75 个命令了。 **搞定!** 你现在可以使用 60 个智能体、228 项技能和 75 个命令了。
*** ***
@ -1138,7 +1138,7 @@ opencode
|---------|-------------|----------|--------| |---------|-------------|----------|--------|
| 智能体 | PASS: 60 个 | PASS: 12 个 | **Claude Code 领先** | | 智能体 | PASS: 60 个 | PASS: 12 个 | **Claude Code 领先** |
| 命令 | PASS: 75 个 | PASS: 35 个 | **Claude Code 领先** | | 命令 | PASS: 75 个 | PASS: 35 个 | **Claude Code 领先** |
| 技能 | PASS: 225 项 | PASS: 37 项 | **Claude Code 领先** | | 技能 | PASS: 228 项 | PASS: 37 项 | **Claude Code 领先** |
| 钩子 | PASS: 8 种事件类型 | PASS: 11 种事件 | **OpenCode 更多!** | | 钩子 | PASS: 8 种事件类型 | PASS: 11 种事件 | **OpenCode 更多!** |
| 规则 | PASS: 29 条 | PASS: 13 条指令 | **Claude Code 领先** | | 规则 | PASS: 29 条 | PASS: 13 条指令 | **Claude Code 领先** |
| MCP 服务器 | PASS: 14 个 | PASS: 完整 | **完全对等** | | MCP 服务器 | PASS: 14 个 | PASS: 完整 | **完全对等** |
@ -1246,7 +1246,7 @@ ECC 是**第一个最大化利用每个主要 AI 编码工具的插件**。以
|---------|------------|------------|-----------|----------| |---------|------------|------------|-----------|----------|
| **智能体** | 60 | 共享 (AGENTS.md) | 共享 (AGENTS.md) | 12 | | **智能体** | 60 | 共享 (AGENTS.md) | 共享 (AGENTS.md) | 12 |
| **命令** | 75 | 共享 | 基于指令 | 35 | | **命令** | 75 | 共享 | 基于指令 | 35 |
| **技能** | 225 | 共享 | 10 (原生格式) | 37 | | **技能** | 228 | 共享 | 10 (原生格式) | 37 |
| **钩子事件** | 8 种类型 | 15 种类型 | 暂无 | 11 种类型 | | **钩子事件** | 8 种类型 | 15 种类型 | 暂无 | 11 种类型 |
| **钩子脚本** | 20+ 个脚本 | 16 个脚本 (DRY 适配器) | N/A | 插件钩子 | | **钩子脚本** | 20+ 个脚本 | 16 个脚本 (DRY 适配器) | N/A | 插件钩子 |
| **规则** | 34 (通用 + 语言) | 34 (YAML 前页) | 基于指令 | 13 条指令 | | **规则** | 34 (通用 + 语言) | 34 (YAML 前页) | 基于指令 | 13 条指令 |

View File

@ -46,7 +46,7 @@ straightforward.
# docker-compose.yml # docker-compose.yml
services: services:
pihole: pihole:
image: pihole/pihole:latest image: pihole/pihole:<pinned-release-tag>
container_name: pihole container_name: pihole
ports: ports:
- "53:53/tcp" - "53:53/tcp"
@ -62,11 +62,15 @@ services:
- "./etc-dnsmasq.d:/etc/dnsmasq.d" - "./etc-dnsmasq.d:/etc/dnsmasq.d"
restart: unless-stopped restart: unless-stopped
cap_add: cap_add:
- NET_ADMIN - NET_ADMIN # only needed if Pi-hole will serve DHCP
``` ```
Set `PIHOLE_WEBPASSWORD` in a `.env` file next to `docker-compose.yml` — do not put Replace `<pinned-release-tag>` with a current Pi-hole release tag before deploying.
the password directly in the compose file. Avoid `latest` for long-lived DNS infrastructure so upgrades are deliberate and
reviewable.
Set `PIHOLE_WEBPASSWORD` in a `.env` file next to `docker-compose.yml`, chmod it to
`600`, and keep it out of git — do not put the password directly in the compose file.
Access web admin at: `http://<pi-ip>/admin` Access web admin at: `http://<pi-ip>/admin`
@ -83,7 +87,8 @@ static ip_address=192.168.3.2/24
static routers=192.168.3.1 static routers=192.168.3.1
static domain_name_servers=192.168.3.1 static domain_name_servers=192.168.3.1
# Step 2: Download and inspect the installer before running it # Step 2: Download and inspect the installer before running it.
# Prefer the package or installer path documented by Pi-hole for your OS/version.
curl -sSL https://install.pi-hole.net -o pi-hole-install.sh curl -sSL https://install.pi-hole.net -o pi-hole-install.sh
less pi-hole-install.sh # review before proceeding less pi-hole-install.sh # review before proceeding
@ -104,8 +109,9 @@ bash pi-hole-install.sh
# Method 1: Change DNS in your router DHCP settings (recommended) # Method 1: Change DNS in your router DHCP settings (recommended)
Router admin UI → DHCP Settings → DNS Server Router admin UI → DHCP Settings → DNS Server
Primary DNS: 192.168.3.2 (Pi-hole IP) Primary DNS: 192.168.3.2 (Pi-hole IP)
Secondary DNS: 1.1.1.1 (fallback — prevents outage if Pi-hole is down, Secondary DNS: leave blank for strict blocking, or use a second Pi-hole.
but bypasses blocking for any query that reaches it) A public fallback such as 1.1.1.1 improves availability during
rollout but can bypass blocking because clients may query it.
All devices get Pi-hole as DNS automatically on next DHCP renewal. All devices get Pi-hole as DNS automatically on next DHCP renewal.
Force renewal: reconnect Wi-Fi or run 'sudo dhclient -r && sudo dhclient' on Linux Force renewal: reconnect Wi-Fi or run 'sudo dhclient -r && sudo dhclient' on Linux
@ -152,9 +158,12 @@ bash pi-hole-install.sh
DNS-over-HTTPS encrypts your DNS queries so your ISP cannot see what sites you resolve. DNS-over-HTTPS encrypts your DNS queries so your ISP cannot see what sites you resolve.
```bash ```bash
# Install cloudflared (Cloudflare's DoH proxy) # Install cloudflared (Cloudflare's DoH proxy).
# On Raspberry Pi (ARM64): # Prefer Cloudflare's package repository for automatic signed package verification.
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64 # If you download a binary directly, pin a release version and verify its checksum.
CLOUDFLARED_VERSION="<pinned-version>"
curl -LO "https://github.com/cloudflare/cloudflared/releases/download/${CLOUDFLARED_VERSION}/cloudflared-linux-arm64"
# Verify the checksum/signature from Cloudflare's release notes before installing.
sudo mv cloudflared-linux-arm64 /usr/local/bin/cloudflared sudo mv cloudflared-linux-arm64 /usr/local/bin/cloudflared
sudo chmod +x /usr/local/bin/cloudflared sudo chmod +x /usr/local/bin/cloudflared
@ -231,10 +240,10 @@ pihole -g
## Anti-Patterns ## Anti-Patterns
``` ```
# BAD: Setting Pi-hole as DNS with no fallback # BAD: Depending on one Pi-hole without a recovery path
# If Pi-hole crashes or the Pi loses power, all DNS stops working # If Pi-hole crashes or the Pi loses power, DNS can stop working
# GOOD: Set Pi-hole as primary DNS, a public resolver as secondary # GOOD: Keep a documented router fallback for rollback during setup
# BETTER: Run two Pi-hole instances for redundancy # BETTER: Run two Pi-hole instances for redundancy; avoid public fallback DNS for strict blocking
# BAD: Installing Pi-hole without a static IP # BAD: Installing Pi-hole without a static IP
# If the Pi gets a new DHCP IP, all devices lose DNS # If the Pi gets a new DHCP IP, all devices lose DNS
@ -252,7 +261,8 @@ pihole -g
## Best Practices ## Best Practices
- Give the Pi a static IP or DHCP reservation before installing Pi-hole - Give the Pi a static IP or DHCP reservation before installing Pi-hole
- Use Pi-hole as primary DNS, add a public resolver as secondary - Use Pi-hole as primary DNS; for redundancy, add a second Pi-hole instead of a
public resolver if you need strict blocking
- Enable DoH (DNS-over-HTTPS) with cloudflared for encrypted upstream queries - Enable DoH (DNS-over-HTTPS) with cloudflared for encrypted upstream queries
- Set `home.lan` as your local domain and create DNS records for all your services - Set `home.lan` as your local domain and create DNS records for all your services
- Review the Query Log occasionally — blocked queries show you what devices are doing - Review the Query Log occasionally — blocked queries show you what devices are doing

View File

@ -45,10 +45,10 @@ Traffic is encrypted end-to-end with no central server or certificate authority.
# Install WireGuard # Install WireGuard
sudo apt update && sudo apt install wireguard -y sudo apt update && sudo apt install wireguard -y
# Generate server keypair — store in a root-owned, mode-600 directory # Generate server keypair — create files with private permissions from the start
sudo mkdir -p /etc/wireguard sudo mkdir -p /etc/wireguard
wg genkey | sudo tee /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key sudo sh -c 'umask 077; wg genkey > /etc/wireguard/server_private.key'
sudo chmod 600 /etc/wireguard/server_private.key sudo sh -c 'wg pubkey < /etc/wireguard/server_private.key > /etc/wireguard/server_public.key'
# Write server config — substitute the actual private key value # Write server config — substitute the actual private key value
# Do not store private keys in version control or share them # Do not store private keys in version control or share them
@ -60,10 +60,10 @@ PrivateKey = <paste_server_private_key_here>
# Scoped forwarding rules: allow VPN traffic in/out, not a blanket FORWARD ACCEPT # Scoped forwarding rules: allow VPN traffic in/out, not a blanket FORWARD ACCEPT
PostUp = iptables -A FORWARD -i wg0 -o eth0 -j ACCEPT PostUp = iptables -A FORWARD -i wg0 -o eth0 -j ACCEPT
PostUp = iptables -A FORWARD -i eth0 -o wg0 -m state --state RELATED,ESTABLISHED -j ACCEPT PostUp = iptables -A FORWARD -i eth0 -o wg0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -o eth0 -j ACCEPT PostDown = iptables -D FORWARD -i wg0 -o eth0 -j ACCEPT
PostDown = iptables -D FORWARD -i eth0 -o wg0 -m state --state RELATED,ESTABLISHED -j ACCEPT PostDown = iptables -D FORWARD -i eth0 -o wg0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer] [Peer]
@ -76,13 +76,14 @@ AllowedIPs = 10.8.0.2/32
PublicKey = <laptop_public_key> PublicKey = <laptop_public_key>
AllowedIPs = 10.8.0.3/32 AllowedIPs = 10.8.0.3/32
EOF EOF
sudo chmod 600 /etc/wireguard/wg0.conf
# Replace eth0 with your actual outbound interface name # Replace eth0 with your actual outbound interface name
# Check with: ip route show default # Check with: ip route show default
# Enable IP forwarding (required for routing traffic through the server) # Enable IP forwarding (required for routing traffic through the server)
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl -p sudo sysctl --system
# Start WireGuard and enable on boot # Start WireGuard and enable on boot
sudo wg-quick up wg0 sudo wg-quick up wg0
@ -94,8 +95,8 @@ sudo systemctl enable wg-quick@wg0
```bash ```bash
# Generate a unique keypair for each client device # Generate a unique keypair for each client device
# Run on the client, or on the server and transfer the private key securely — never in plaintext # Run on the client, or on the server and transfer the private key securely — never in plaintext
umask 077
wg genkey | tee phone_private.key | wg pubkey > phone_public.key wg genkey | tee phone_private.key | wg pubkey > phone_public.key
chmod 600 phone_private.key
# Client config file (phone_wg0.conf): # Client config file (phone_wg0.conf):
[Interface] [Interface]
@ -222,8 +223,20 @@ stays reachable after an IP change.
# Option 2: DuckDNS (free, simple) # Option 2: DuckDNS (free, simple)
Sign up at duckdns.org → get a token and subdomain (myhome.duckdns.org) Sign up at duckdns.org → get a token and subdomain (myhome.duckdns.org)
Cron job (store token in an env file or a secrets manager, not inline): Store token in /etc/ddns.env (mode 600), then use a small root-owned script:
*/5 * * * * source /etc/ddns.env && curl "https://www.duckdns.org/update?domains=myhome&token=${DUCKDNS_TOKEN}&ip="
# /usr/local/bin/update-duckdns
#!/bin/sh
set -eu
. /etc/ddns.env
curl --fail --silent --show-error --max-time 10 \
--get "https://www.duckdns.org/update" \
--data-urlencode "domains=myhome" \
--data-urlencode "token=${DUCKDNS_TOKEN}" \
--data-urlencode "ip="
# Cron job:
*/5 * * * * /usr/local/bin/update-duckdns >/dev/null 2>&1
``` ```
## Troubleshooting ## Troubleshooting