Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ systemctl start kimaki # or: systemctl start cc-connect
| `--chat <bridge>` | Chat bridge: `kimaki` (Discord, default for OpenCode), `cc-connect` (default for Claude Code and Studio Code), `telegram` |
| `--multisite` | Convert to WordPress Multisite (subdirectory by default) |
| `--subdomain` | Subdomain multisite (use with `--multisite`, requires wildcard DNS) |
| `--no-skills` | Skip WordPress agent skills |
| `--no-skills` | Skip wp-coding-agents skills |
| `--skip-deps` | Skip apt packages |
| `--skip-ssl` | Skip SSL/HTTPS |
| `--root` | Run agent as root (default on VPS) |
Expand Down Expand Up @@ -184,7 +184,7 @@ SITE_DOMAIN=example.com ./setup.sh --dry-run
| **[Homeboy](https://github.com/Extra-Chill/homeboy)** | Optional developer power layer for project status, component-aware checks, review loops, and WordPress extension verification | `--with-homeboy` |
| **[Kimaki](https://kimaki.xyz)**, **[cc-connect](https://github.com/nichochar/cc-connect)**, or **[opencode-telegram](https://github.com/grinev/opencode-telegram-bot)** | Chat bridge (Discord, multi-platform, or Telegram) | `--no-chat` |
| **SessionStart hook** | Syncs Data Machine agents into CLAUDE.md on every session (Claude Code and Studio Code) | Always installed |
| **[WordPress agent skills](https://github.com/WordPress/agent-skills)** | WP development patterns (cloned at install) | `--no-skills` |
| **wp-coding-agents skills** | Setup and upgrade runbooks shipped with this repo. The composed `AGENTS.md` provides the site-specific WordPress, Data Machine, and Homeboy operating context, so setup does not install redundant external skills. | `--no-skills` |

## VPS vs. Local

Expand Down
16 changes: 16 additions & 0 deletions bridges/kimaki/post-upgrade.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,18 @@ fi

KILL_LIST="$(dirname "$0")/skills-kill-list.txt"
REQUIRED_PLUGINS=(dm-context-filter.ts dm-agent-sync.ts)
WP_CODING_AGENTS_SKILLS=(upgrade-wp-coding-agents wp-coding-agents-setup)

is_wp_coding_agents_skill() {
local candidate="$1"
local skill

for skill in "${WP_CODING_AGENTS_SKILLS[@]}"; do
[[ "$candidate" == "$skill" ]] && return 0
done

return 1
}

is_killed_skill() {
local candidate="$1"
Expand Down Expand Up @@ -127,6 +139,10 @@ elif [[ -d "$SKILL_SOURCE_DIR" ]]; then
echo "kimaki-config: skipped killed skill $skill_name"
continue
fi
if ! is_wp_coding_agents_skill "$skill_name"; then
echo "kimaki-config: skipped unmanaged skill $skill_name"
continue
fi
if [[ -f "$skill_dir/SKILL.md" ]]; then
target="$SKILLS_DIR/$skill_name"
rm -rf "$target"
Expand Down
87 changes: 49 additions & 38 deletions lib/skills.sh
Original file line number Diff line number Diff line change
@@ -1,35 +1,40 @@
#!/bin/bash
# Skills: agent skill installation from git repos and the wp-coding-agents repo itself
# Skills: agent skill installation from the wp-coding-agents repo itself.
# Site-specific WordPress, Data Machine, and Homeboy guidance belongs in the
# composed AGENTS.md, which is fresher than static external skill snapshots.

# Install agent skills from a git repo.
# Clones the repo, copies directories containing SKILL.md to the target.
install_skills_from_repo() {
local repo_url="$1"
local label="${2:-skills}"
WP_CODING_AGENTS_SKILLS=(upgrade-wp-coding-agents wp-coding-agents-setup)

if [ "$DRY_RUN" = true ]; then
echo -e "${BLUE}[dry-run]${NC} git clone --depth 1 $repo_url (extract skill dirs to $SKILLS_DIR)"
return
fi
is_wp_coding_agents_skill() {
local candidate="$1"
local skill

local tmp_dir
tmp_dir=$(mktemp -d)
rmdir "$tmp_dir" 2>/dev/null || true # git_clone_with_retry needs a non-existent target on retry.
if git_clone_with_retry "$repo_url" "$tmp_dir" --depth 1; then
for skill_dir in "$tmp_dir"/*/; do
local skill_name
skill_name=$(basename "$skill_dir")
if [ -f "$skill_dir/SKILL.md" ]; then
rm -rf "$SKILLS_DIR/$skill_name"
cp -r "$skill_dir" "$SKILLS_DIR/$skill_name"
log " Installed skill: $skill_name"
fi
done
rm -rf "$tmp_dir"
log "$label installed (latest version)"
else
warn "Could not clone $label from $repo_url"
rm -rf "$tmp_dir"
for skill in "${WP_CODING_AGENTS_SKILLS[@]}"; do
[ "$candidate" = "$skill" ] && return 0
done

return 1
}

remove_unmanaged_skills() {
local target_dir="$1"
local label="$2"

[ -d "$target_dir" ] || return

local removed=0
local skill_dir skill_name
for skill_dir in "$target_dir"/*/; do
[ -d "$skill_dir" ] || continue
skill_name=$(basename "$skill_dir")
if [ -f "$skill_dir/SKILL.md" ] && ! is_wp_coding_agents_skill "$skill_name"; then
rm -rf "$skill_dir"
removed=$((removed + 1))
fi
done

if [ "$removed" -gt 0 ]; then
log "Removed unmanaged skills from $label: $target_dir/ ($removed)"
fi
}

Expand All @@ -42,18 +47,24 @@ install_skills_from_local_repo() {
[ -d "$src_dir" ] || return

if [ "$DRY_RUN" = true ]; then
echo -e "${BLUE}[dry-run]${NC} Would remove unmanaged skills from $SKILLS_DIR/"
for skill_dir in "$src_dir"/*/; do
local skill_name
skill_name=$(basename "$skill_dir")
[ -f "$skill_dir/SKILL.md" ] || continue
echo -e "${BLUE}[dry-run]${NC} Would install in-repo skill: $(basename "$skill_dir") → $SKILLS_DIR/"
is_wp_coding_agents_skill "$skill_name" || continue
echo -e "${BLUE}[dry-run]${NC} Would install in-repo skill: $skill_name → $SKILLS_DIR/"
done
return
fi

remove_unmanaged_skills "$SKILLS_DIR" "runtime skills dir"

local copied=0
for skill_dir in "$src_dir"/*/; do
local skill_name
skill_name=$(basename "$skill_dir")
if [ -f "$skill_dir/SKILL.md" ]; then
if [ -f "$skill_dir/SKILL.md" ] && is_wp_coding_agents_skill "$skill_name"; then
rm -rf "$SKILLS_DIR/$skill_name"
cp -r "$skill_dir" "$SKILLS_DIR/$skill_name"
log " Installed skill: $skill_name"
Expand All @@ -65,8 +76,8 @@ install_skills_from_local_repo() {
fi
}

# Mirror every SKILL.md-containing subdir from $SKILLS_DIR into the
# persistent kimaki-config/skills/ dir. This is the durable source of
# Mirror wp-coding-agents-owned skills into the persistent
# kimaki-config/skills/ dir. This is the durable source of
# truth that survives `npm update -g kimaki` wipes — kimaki/post-upgrade.sh
# reads from this path on every kimaki restart to restore the mirror copy
# at $(npm root -g)/kimaki/skills/.
Expand All @@ -93,12 +104,14 @@ install_skills_to_persistent_source() {
return
}

remove_unmanaged_skills "$persistent_dir" "persistent source"

local copied=0
for skill_dir in "$SKILLS_DIR"/*/; do
for skill_dir in "$SCRIPT_DIR/skills"/*/; do
[ -d "$skill_dir" ] || continue
local skill_name
skill_name=$(basename "$skill_dir")
if [ -f "$skill_dir/SKILL.md" ]; then
if [ -f "$skill_dir/SKILL.md" ] && is_wp_coding_agents_skill "$skill_name"; then
rm -rf "$persistent_dir/$skill_name"
cp -r "$skill_dir" "$persistent_dir/$skill_name"
copied=$((copied + 1))
Expand Down Expand Up @@ -176,8 +189,6 @@ install_skills() {
run_cmd mkdir -p "$SKILLS_DIR"

install_skills_from_local_repo
install_skills_from_repo "https://github.com/WordPress/agent-skills.git" "WordPress agent skills"
install_skills_from_repo "https://github.com/Extra-Chill/data-machine-skills.git" "Data Machine skills"
done

# Reset SKILLS_DIR back to the primary for downstream consumers
Expand All @@ -194,9 +205,9 @@ install_skills() {
elif command -v kimaki &> /dev/null; then
KIMAKI_SKILLS_DIR="$(npm root -g 2>/dev/null)/kimaki/skills"
if [ -d "$KIMAKI_SKILLS_DIR" ]; then
for skill_dir in "$SKILLS_DIR"/*/; do
for skill_dir in "$SCRIPT_DIR/skills"/*/; do
skill_name=$(basename "$skill_dir")
if [ -f "$skill_dir/SKILL.md" ]; then
if [ -f "$skill_dir/SKILL.md" ] && is_wp_coding_agents_skill "$skill_name"; then
cp -r "$skill_dir" "$KIMAKI_SKILLS_DIR/$skill_name"
fi
done
Expand Down
7 changes: 4 additions & 3 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
# Without Discord: ./setup.sh --no-chat
#
# Data Machine is the substrate wp-coding-agents composes on top of — memory
# files (SOUL/MEMORY/USER/RULES/SITE), auto-composed AGENTS.md, skills,
# files (SOUL/MEMORY/USER/RULES/SITE), auto-composed AGENTS.md,
# wp-coding-agents skills,
# workspace primitive, MCP surface. It is not optional. Uninstall the plugin
# later if you don't want it.
#
Expand Down Expand Up @@ -200,13 +201,13 @@ OPTIONS:
--skip-deps Skip apt package installation
--multisite Convert to WordPress Multisite (subdirectory by default)
--subdomain Use subdomain multisite (requires wildcard DNS; use with --multisite)
--no-skills Skip WordPress agent skills installation
--no-skills Skip wp-coding-agents skill installation
--with-homeboy Create/update a Homeboy project and install/verify the
WordPress Homeboy extension
--no-homeboy Skip Homeboy project setup, even if homeboy is installed
--homeboy-project-id <id>
Override Homeboy project ID (default: agent/site slug)
--skills-only Only run skills installation on existing site
--skills-only Only run wp-coding-agents skill installation on existing site
--skip-ssl Skip SSL/HTTPS configuration
--root Run agent as root (default)
--non-root Run agent as dedicated service user (opencode)
Expand Down
2 changes: 1 addition & 1 deletion skills/wp-coding-agents-setup/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ Based on their answers, construct the appropriate command:
Add `--skip-deps` if nginx, PHP, MySQL, Node are already installed.
Add `--skip-ssl` to skip Let's Encrypt certificate.
Add `--root` to run the agent as root (default is dedicated service user).
Add `--no-skills` to skip WordPress agent skills.
Add `--no-skills` to skip wp-coding-agents skills.
Add `--agent-slug <slug>` to override the Data Machine agent slug.
Add `--with-homeboy` when the user wants the optional Homeboy developer power layer. Homeboy remains external; setup should verify or install the CLI and WordPress extension, create/update a Homeboy project for the WordPress site root, attach eligible Data Machine Code primary workspace checkouts as components, skip `@` worktrees by default, sync `datamachine_code_homeboy_available`, and recompose `AGENTS.md`.

Expand Down
39 changes: 25 additions & 14 deletions tests/post-upgrade-restore.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
#
# What we cover:
# 1. Kill pass removes a blacklisted skill from the simulated skills dir.
# 2. Skill restore pass copies a SKILL.md tree from the persistent source
# back into the (wiped) skills dir.
# 2. Skill restore pass copies wp-coding-agents SKILL.md trees from the
# persistent source back into the (wiped) skills dir.
# 3. Default plugin pass is a no-op because opencode loads the persistent
# source dir directly.
# 4. Explicit KIMAKI_PLUGINS_DIR compatibility override still copies *.ts
Expand Down Expand Up @@ -55,16 +55,25 @@ echo "stub" > "$LIVE_SKILLS/blacklisted-skill/SKILL.md"
mkdir -p "$LIVE_SKILLS/persisted-blacklisted-skill"
echo "stub" > "$LIVE_SKILLS/persisted-blacklisted-skill/SKILL.md"

# Seed a skill in the persistent source that should be restored.
mkdir -p "$SRC_SKILLS/restored-skill"
cat > "$SRC_SKILLS/restored-skill/SKILL.md" <<'EOF'
# Seed a wp-coding-agents skill in the persistent source that should be restored.
mkdir -p "$SRC_SKILLS/upgrade-wp-coding-agents"
cat > "$SRC_SKILLS/upgrade-wp-coding-agents/SKILL.md" <<'EOF'
---
name: restored-skill
name: upgrade-wp-coding-agents
description: test fixture
---
body
EOF

mkdir -p "$SRC_SKILLS/unmanaged-skill"
cat > "$SRC_SKILLS/unmanaged-skill/SKILL.md" <<'EOF'
---
name: unmanaged-skill
description: unmanaged fixture
---
body
EOF

mkdir -p "$SRC_SKILLS/persisted-blacklisted-skill"
cat > "$SRC_SKILLS/persisted-blacklisted-skill/SKILL.md" <<'EOF'
---
Expand Down Expand Up @@ -145,9 +154,11 @@ assert_missing "$LIVE_SKILLS/persisted-blacklisted-skill"
assert_log_contains "removed skill persisted-blacklisted-skill"
assert_log_contains "skipped killed skill persisted-blacklisted-skill"

# Pass 2: skill restore copied the SKILL.md tree.
assert_present "$LIVE_SKILLS/restored-skill/SKILL.md"
assert_log_contains "restored skill restored-skill"
# Pass 2: skill restore copied the allowed SKILL.md tree and skipped unmanaged skills.
assert_present "$LIVE_SKILLS/upgrade-wp-coding-agents/SKILL.md"
assert_log_contains "restored skill upgrade-wp-coding-agents"
assert_missing "$LIVE_SKILLS/unmanaged-skill/SKILL.md"
assert_log_contains "skipped unmanaged skill unmanaged-skill"

# Pass 3: default plugin restore is a no-op because opencode loads the
# persistent source directly.
Expand Down Expand Up @@ -213,12 +224,12 @@ FALLBACK_LIVE_SKILLS="$TMP/fallback-live/skills"
FALLBACK_LIVE_PLUGINS="$TMP/fallback-live/plugins"
mkdir -p \
"$FALLBACK_DATA" \
"$FALLBACK_HOME/.kimaki/kimaki-config/skills/home-skill" \
"$FALLBACK_HOME/.kimaki/kimaki-config/skills/wp-coding-agents-setup" \
"$FALLBACK_HOME/.kimaki/kimaki-config/plugins" \
"$FALLBACK_LIVE_SKILLS"
cat > "$FALLBACK_HOME/.kimaki/kimaki-config/skills/home-skill/SKILL.md" <<'EOF'
cat > "$FALLBACK_HOME/.kimaki/kimaki-config/skills/wp-coding-agents-setup/SKILL.md" <<'EOF'
---
name: home-skill
name: wp-coding-agents-setup
description: fallback fixture
---
body
Expand All @@ -233,7 +244,7 @@ KIMAKI_DATA_DIR="$FALLBACK_DATA" \
KIMAKI_SKILLS_DIR="$FALLBACK_LIVE_SKILLS" \
"$TEST_SCRIPT_DIR/post-upgrade.sh" > "$TMP/run4.log" 2>&1

if [[ ! -f "$FALLBACK_LIVE_SKILLS/home-skill/SKILL.md" ]]; then
if [[ ! -f "$FALLBACK_LIVE_SKILLS/wp-coding-agents-setup/SKILL.md" ]]; then
echo "FAIL: missing KIMAKI_DATA_DIR skills source should fall through to HOME source"
cat "$TMP/run4.log"
exit 1
Expand All @@ -243,7 +254,7 @@ if [[ -e "$FALLBACK_LIVE_PLUGINS" ]]; then
cat "$TMP/run4.log"
exit 1
fi
if ! grep -q "restored skill home-skill" "$TMP/run4.log"; then
if ! grep -q "restored skill wp-coding-agents-setup" "$TMP/run4.log"; then
echo "FAIL: fallback run should restore the HOME-backed skill"
cat "$TMP/run4.log"
exit 1
Expand Down
14 changes: 6 additions & 8 deletions upgrade.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# reminds user to `npm update -g cc-connect`.
# telegram: no per-install artifacts; reports binary versions and
# reminds user to `npm update -g @grinev/opencode-telegram-bot`.
# 4. Sync agent skills (WordPress + Data Machine)
# 4. Sync wp-coding-agents skills
# 5. Regenerate AGENTS.md via Data Machine compose
# 6. Smart systemd update (VPS only; dispatches per bridge)
# kimaki → kimaki.service
Expand All @@ -35,7 +35,7 @@
# ./upgrade.sh --dry-run # preview without changes
# ./upgrade.sh --kimaki-only # only sync kimaki config + plugins
# ./upgrade.sh --plugins-only # only update Data Machine plugins
# ./upgrade.sh --skills-only # only sync skills
# ./upgrade.sh --skills-only # only sync wp-coding-agents skills
# ./upgrade.sh --agents-md-only # only regenerate AGENTS.md
# ./upgrade.sh --local --wp-path <path> # local install (auto on macOS)
#
Expand Down Expand Up @@ -141,7 +141,7 @@ USAGE:
backwards compat — also handles cc-connect
and telegram when they are the detected bridge)
./upgrade.sh --plugins-only Only update setup-installed Data Machine plugins
./upgrade.sh --skills-only Only sync agent skills
./upgrade.sh --skills-only Only sync wp-coding-agents skills
./upgrade.sh --agents-md-only Only regenerate AGENTS.md
./upgrade.sh --skip-plugins Skip Data Machine plugin updates during full run
./upgrade.sh --repair-opencode-json
Expand Down Expand Up @@ -501,27 +501,25 @@ check_opencode_json_drift() {
}

# ============================================================================
# Phase 4: Sync agent skills (WordPress + Data Machine)
# Phase 4: Sync wp-coding-agents skills
# ============================================================================

sync_skills() {
_run_filter_active skills || return 0

log "Phase 4: Syncing agent skills..."
log "Phase 4: Syncing wp-coding-agents skills..."

if [ "$DRY_RUN" = true ]; then
SKILLS_DIR="$(runtime_skills_dir)"
echo -e "${BLUE}[dry-run]${NC} Would install in-repo skills from $SCRIPT_DIR/skills → $SKILLS_DIR"
echo -e "${BLUE}[dry-run]${NC} Would clone WordPress/agent-skills → $SKILLS_DIR"
echo -e "${BLUE}[dry-run]${NC} Would clone Extra-Chill/data-machine-skills → $SKILLS_DIR"
if [ "$CHAT_BRIDGE" = "kimaki" ]; then
echo -e "${BLUE}[dry-run]${NC} Would copy skills to kimaki skills dir"
fi
return 0
fi

install_skills
UPDATED_ITEMS+=("agent skills")
UPDATED_ITEMS+=("wp-coding-agents skills")
}

# ============================================================================
Expand Down
Loading