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
21 changes: 7 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ systemctl start kimaki # or: systemctl start cc-connect
| `--existing` | Add to existing WordPress (skip WP install) |
| `--wp-path <path>` | Path to WordPress root (implies `--existing`) |
| `--agent-slug <slug>` | Override Data Machine agent slug (default: derived from domain) |
| `--no-data-machine` | Skip Data Machine (no persistent memory/scheduling) |
| `--no-chat` | Skip chat bridge |
| `--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) |
Expand Down Expand Up @@ -176,10 +175,10 @@ SITE_DOMAIN=example.com ./setup.sh --dry-run
|-----------|------|-----------|
| **WordPress** | Site platform, WP-CLI access | No (existing install on local) |
| **[OpenCode](https://opencode.ai)**, **[Claude Code](https://docs.anthropic.com/en/docs/claude-code)**, or **[Studio Code](https://developer.wordpress.com/studio/)** | AI coding agent runtime | Selected via `--runtime` |
| **[Data Machine](https://github.com/Extra-Chill/data-machine)** | Memory (SOUL/USER/MEMORY.md), self-scheduling, AI tools, Agent Ping | `--no-data-machine` |
| **[Data Machine](https://github.com/Extra-Chill/data-machine)** | Memory (SOUL/USER/MEMORY.md), self-scheduling, AI tools, Agent Ping | No — wp-coding-agents composes on top of DM |
| **[Data Machine Code](https://github.com/Extra-Chill/data-machine-code)** | Workspace management, GitHub integration, git operations | Installed with Data Machine |
| **[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) | Installed with Data Machine |
| **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` |

## VPS vs. Local
Expand Down Expand Up @@ -220,15 +219,16 @@ Data Machine manages memory files across three layers, each scoped to a differen

On activation, Data Machine creates a default agent for the first admin user and scaffolds all three layers. Each additional agent gets its own SOUL.md and MEMORY.md when created, sharing the same SITE.md and USER.md. All discovered files are injected into every session via the runtime's config — `opencode.json` (`{file:}` includes) for OpenCode, `CLAUDE.md` (`@` includes) for Claude Code and Studio Code. The agent doesn't manage memory infrastructure — it just reads and writes these files. DM handles the rest.

**Runtime sync (Claude Code / Studio Code):** A SessionStart hook queries Data Machine on every session start and updates the `@` includes in CLAUDE.md. New agents created after setup are automatically discovered — no manual config regeneration needed. Claude Code's built-in auto-memory is disabled when Data Machine is installed, since DM handles memory. Studio Code uses the same hook mechanism — it runs the Claude Agent SDK with the `claude_code` preset, which loads `.claude/settings.json` hooks by default.
**Runtime sync (Claude Code / Studio Code):** A SessionStart hook queries Data Machine on every session start and updates the `@` includes in CLAUDE.md. New agents created after setup are automatically discovered — no manual config regeneration needed. Claude Code's built-in auto-memory is disabled, since DM handles memory. Studio Code uses the same hook mechanism — it runs the Claude Agent SDK with the `claude_code` preset, which loads `.claude/settings.json` hooks by default.

## Abilities

Data Machine exposes all agent functionality through WordPress core's [Abilities API](https://developer.wordpress.org/reference/functions/wp_register_ability/) (`wp_register_ability`). Every tool an agent can use is a native WordPress primitive — discoverable, permissioned, and executable via REST, CLI, or chat. No proprietary abstraction layer.

## With or Without Data Machine
## What Data Machine Gives You

Data Machine is the substrate wp-coding-agents composes on top of — memory, scheduling, workspace, abilities. It is not optional. Installing wp-coding-agents means installing DM. Uninstall the plugin after the fact if you change your mind.

**With DM (default):**
- Persistent memory across sessions (SOUL.md, USER.md, MEMORY.md)
- Self-scheduling via flows and cron
- Task queues for multi-phase projects
Expand All @@ -238,13 +238,6 @@ Data Machine exposes all agent functionality through WordPress core's [Abilities
- GitHub integration (issues, PRs, repos)
- Policy-controlled git operations (add, commit, push with allowlists; primary checkout is read-only by default)

**Without DM (`--no-data-machine`):**
- Agent responds when prompted, no autonomous operation
- No persistent memory between sessions
- No self-scheduling
- No managed workspace or GitHub integration
- Good for development-only setups where you just need a coding assistant

## Why Root? (VPS only)

wp-coding-agents defaults to running the agent as `root` on VPS installs. On a single-purpose agent VPS, root keeps things simple:
Expand All @@ -264,7 +257,7 @@ Local installs run as your current user — no root, no service user, no chown.
The default chat bridge for OpenCode. On VPS, wp-coding-agents installs post-upgrade hooks that:

- **Remove unwanted bundled skills** — Kimaki ships with skills for frameworks and tools that aren't relevant to WordPress agent workflows. The kill list (`kimaki/skills-kill-list.txt`) controls which skills are removed after each upgrade.
- **Filter redundant context** — When Data Machine is installed, a plugin strips Kimaki's built-in memory injection and scheduling instructions from the agent context, since DM handles those concerns. Saves ~2,400 tokens per session.
- **Filter redundant context** — A plugin strips Kimaki's built-in memory injection and scheduling instructions from the agent context, since DM handles those concerns. Saves ~2,400 tokens per session.

To customize the kill list, edit `kimaki/skills-kill-list.txt` before running setup, or edit `/opt/kimaki-config/skills-kill-list.txt` on the server after install.

Expand Down
10 changes: 0 additions & 10 deletions lib/data-machine.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@
# Data Machine: plugin installation, agent creation, SOUL/MEMORY scaffold

install_data_machine() {
if [ "$INSTALL_DATA_MACHINE" != true ]; then
log "Phase 4: Skipping Data Machine (--no-data-machine)"
return
fi

log "Phase 4: Installing Data Machine..."
install_plugin data-machine https://github.com/Extra-Chill/data-machine.git

Expand All @@ -32,11 +27,6 @@ install_data_machine() {
}

create_dm_agent() {
if [ "$INSTALL_DATA_MACHINE" != true ]; then
AGENT_SLUG=""
return
fi

log "Phase 4.5: Creating Data Machine agent..."

# Derive agent slug from domain
Expand Down
1 change: 0 additions & 1 deletion lib/detect.sh
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ detect_environment() {
log "Detected OS: $OS (platform: $PLATFORM, local: $LOCAL_MODE)"
log "Mode: $MODE"
log "Runtime: $RUNTIME"
log "Data Machine: $INSTALL_DATA_MACHINE"
log "Multisite: $MULTISITE ($MULTISITE_TYPE)"
if [ "$DRY_RUN" = true ]; then
log "Dry-run mode: commands will be printed, not executed"
Expand Down
17 changes: 5 additions & 12 deletions lib/repair-opencode-json.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"""
repair-opencode-json.py — Detect and optionally repair the `plugin` array in
an existing opencode.json against what the current wp-coding-agents setup
would produce for the detected (RUNTIME, CHAT_BRIDGE, INSTALL_DATA_MACHINE).
would produce for the detected (RUNTIME, CHAT_BRIDGE). Data Machine is
always installed.

Exit codes:
0 — no drift; file is already correct
Expand All @@ -19,7 +20,6 @@
repair-opencode-json.py --file <path> \
--runtime <opencode|claude-code|studio-code> \
--chat-bridge <kimaki|cc-connect|telegram|none> \
--install-dm <true|false> \
[--kimaki-plugins-dir <path>] \
[--apply] \
[--backup-suffix <timestamp>]
Expand All @@ -39,7 +39,6 @@
def expected_plugins(
runtime: str,
chat_bridge: str,
install_dm: bool,
kimaki_plugins_dir: str,
) -> List[str]:
"""Return the `plugin` array wp-coding-agents setup would produce today.
Expand All @@ -62,8 +61,9 @@ def expected_plugins(
if chat_bridge != "kimaki":
plugins.append("opencode-claude-auth@latest")

# DM context filter + agent sync: only when DM handles memory via Kimaki.
if install_dm and chat_bridge == "kimaki":
# DM context filter + agent sync: only when the bridge is Kimaki, since
# these plugins rewrite Kimaki-specific prompts.
if chat_bridge == "kimaki":
plugins.append(f"{kimaki_plugins_dir}/dm-context-filter.ts")
plugins.append(f"{kimaki_plugins_dir}/dm-agent-sync.ts")

Expand Down Expand Up @@ -120,11 +120,6 @@ def main() -> int:
required=True,
choices=["kimaki", "cc-connect", "telegram", "none"],
)
parser.add_argument(
"--install-dm",
required=True,
choices=["true", "false"],
)
parser.add_argument(
"--kimaki-plugins-dir",
default="/opt/kimaki-config/plugins",
Expand Down Expand Up @@ -159,11 +154,9 @@ def main() -> int:
)
return 2

install_dm = args.install_dm == "true"
expected = expected_plugins(
runtime=args.runtime,
chat_bridge=args.chat_bridge,
install_dm=install_dm,
kimaki_plugins_dir=args.kimaki_plugins_dir.rstrip("/"),
)

Expand Down
4 changes: 1 addition & 3 deletions lib/skills.sh
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,7 @@ install_skills() {

install_skills_from_repo "https://github.com/WordPress/agent-skills.git" "WordPress agent skills"

if [ "$INSTALL_DATA_MACHINE" = true ]; then
install_skills_from_repo "https://github.com/Extra-Chill/data-machine-skills.git" "Data Machine skills"
fi
install_skills_from_repo "https://github.com/Extra-Chill/data-machine-skills.git" "Data Machine skills"

# Copy skills to Kimaki's directory if Kimaki is the chat bridge.
# Kimaki overrides OpenCode's skill discovery to only look in its
Expand Down
34 changes: 14 additions & 20 deletions lib/summary.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,14 @@ print_summary() {
echo " Type: $MULTISITE_TYPE"
echo ""
fi
if [ "$INSTALL_DATA_MACHINE" = true ]; then
echo "Data Machine:"
if [ -n "$AGENT_SLUG" ]; then
echo " Agent: $AGENT_SLUG"
fi
echo " Discover: $WP_CMD datamachine agent paths${AGENT_SLUG:+ --agent=$AGENT_SLUG} $WP_ROOT_FLAG"
echo " Code tools: data-machine-code (workspace, GitHub, git)"
echo " Workspace: $DM_WORKSPACE_DIR (created on first use)"
echo ""
echo "Data Machine:"
if [ -n "$AGENT_SLUG" ]; then
echo " Agent: $AGENT_SLUG"
fi
echo " Discover: $WP_CMD datamachine agent paths${AGENT_SLUG:+ --agent=$AGENT_SLUG} $WP_ROOT_FLAG"
echo " Code tools: data-machine-code (workspace, GitHub, git)"
echo " Workspace: $DM_WORKSPACE_DIR (created on first use)"
echo ""
echo "Agent:"
if [ "$LOCAL_MODE" = true ]; then
echo " User: $(whoami) (local)"
Expand Down Expand Up @@ -71,7 +69,6 @@ WP_ADMIN_PASS=$WP_ADMIN_PASS
DB_NAME=$DB_NAME
DB_USER=$DB_USER
DB_PASS=$DB_PASS
DATA_MACHINE=$INSTALL_DATA_MACHINE
AGENT_SLUG=$AGENT_SLUG
MULTISITE=$MULTISITE
MULTISITE_TYPE=$MULTISITE_TYPE
Expand Down Expand Up @@ -100,17 +97,14 @@ _print_next_steps() {
_print_vps_next_steps
fi

if [ "$INSTALL_DATA_MACHINE" = true ]; then
echo " Configure Data Machine:"
echo " - Set AI provider API keys in WP Admin → Data Machine → Settings"
if [ "$LOCAL_MODE" = false ]; then
echo " - Or via WP-CLI: $WP_CMD datamachine settings --allow-root"
else
echo " - Or via WP-CLI: $WP_CMD datamachine settings --path=$SITE_PATH"
fi
echo ""
echo " Configure Data Machine:"
echo " - Set AI provider API keys in WP Admin → Data Machine → Settings"
if [ "$LOCAL_MODE" = false ]; then
echo " - Or via WP-CLI: $WP_CMD datamachine settings --allow-root"
else
echo " - Or via WP-CLI: $WP_CMD datamachine settings --path=$SITE_PATH"
fi

echo ""
}

_print_local_next_steps() {
Expand Down
37 changes: 11 additions & 26 deletions runtimes/claude-code.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ runtime_discover_dm_paths() {
fi

DM_FILES=()
if [ "$INSTALL_DATA_MACHINE" != true ]; then
return
fi

if [ "$DRY_RUN" = false ] && [ -f "$SITE_PATH/wp-config.php" ]; then
AGENT_FLAG=""
Expand Down Expand Up @@ -109,24 +106,19 @@ runtime_generate_config() {
CLAUDE_MD=$(echo "$CLAUDE_MD" | sed '/{{IF_STUDIO}}/,/{{END_IF_STUDIO}}/d')
fi

# Process Data Machine conditional
if [ "$INSTALL_DATA_MACHINE" = true ]; then
CLAUDE_MD=$(echo "$CLAUDE_MD" | sed '/{{IF_DATA_MACHINE}}/d; /{{END_IF_DATA_MACHINE}}/d')
CLAUDE_MD=$(echo "$CLAUDE_MD" | sed '/{{IF_NO_DATA_MACHINE}}/,/{{END_IF_NO_DATA_MACHINE}}/d')

AT_INCLUDES=""
for dm_file in "${DM_FILES[@]}"; do
AT_INCLUDES="${AT_INCLUDES}@${dm_file}
AT_INCLUDES=""
for dm_file in "${DM_FILES[@]}"; do
AT_INCLUDES="${AT_INCLUDES}@${dm_file}
"
done
done

DISCOVER_LINE="Discover DM paths: \`$WP_CLI_DISPLAY datamachine agent paths\`"
SENTINEL_CONTENT="<!-- DM_AGENT_SYNC_START -->
DISCOVER_LINE="Discover DM paths: \`$WP_CLI_DISPLAY datamachine agent paths\`"
SENTINEL_CONTENT="<!-- DM_AGENT_SYNC_START -->
${AT_INCLUDES}
${DISCOVER_LINE}
<!-- DM_AGENT_SYNC_END -->"

CLAUDE_MD=$(python3 -c "
CLAUDE_MD=$(python3 -c "
import sys
content = sys.argv[1]
block = sys.argv[2]
Expand All @@ -136,10 +128,6 @@ si = content.index(start)
ei = content.index(end) + len(end)
print(content[:si] + block + content[ei:], end='')
" "$CLAUDE_MD" "$SENTINEL_CONTENT")
else
CLAUDE_MD=$(echo "$CLAUDE_MD" | sed '/{{IF_DATA_MACHINE}}/,/{{END_IF_DATA_MACHINE}}/d')
CLAUDE_MD=$(echo "$CLAUDE_MD" | sed '/{{IF_NO_DATA_MACHINE}}/d; /{{END_IF_NO_DATA_MACHINE}}/d')
fi

# Clean up stacked empty lines from conditional removal
CLAUDE_MD=$(echo "$CLAUDE_MD" | sed '/^$/N;/^\n$/d')
Expand All @@ -149,10 +137,6 @@ print(content[:si] + block + content[ei:], end='')
}

runtime_install_hooks() {
if [ "$INSTALL_DATA_MACHINE" != true ]; then
return
fi

log "Installing Claude Code SessionStart hook..."

local hooks_dir="$SITE_PATH/.claude/hooks"
Expand Down Expand Up @@ -244,16 +228,17 @@ runtime_generate_instructions() {

log "Generating AGENTS.md..."

# When Data Machine is installed, compose from registered sections.
if [ "$INSTALL_DATA_MACHINE" = true ] && [ "$DRY_RUN" = false ]; then
# Compose from Data Machine's SectionRegistry. DM is mandatory, so this is
# the only source of truth for AGENTS.md content.
if [ "$DRY_RUN" = false ]; then
if wp_cmd datamachine agent compose AGENTS.md 2>/dev/null; then
log "AGENTS.md composed from SectionRegistry"
return
fi
warn "Compose failed — falling back to static template"
fi

# Fallback: minimal template for non-DM installs or dry-run.
# Fallback for dry-run or compose failure: ship a minimal static template.
local agents_tmpl="$SCRIPT_DIR/workspace/AGENTS.md"
if [ ! -f "$agents_tmpl" ]; then
error "AGENTS.md template not found at $agents_tmpl"
Expand Down
32 changes: 13 additions & 19 deletions runtimes/opencode.sh
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,6 @@ _patch_claude_auth_plugin() {
}

runtime_discover_dm_paths() {
if [ "$INSTALL_DATA_MACHINE" != true ]; then
OPENCODE_PROMPT='{file:./AGENTS.md}'
return
fi

if [ "$DRY_RUN" = false ] && [ -f "$SITE_PATH/wp-config.php" ]; then
AGENT_FLAG=""
if [ -n "$AGENT_SLUG" ]; then
Expand Down Expand Up @@ -219,8 +214,9 @@ runtime_generate_config() {
OPENCODE_PLUGINS="${OPENCODE_PLUGINS}\n \"opencode-claude-auth@latest\","
fi

# DM context filter + agent sync — only when DM handles memory via Kimaki
if [ "$INSTALL_DATA_MACHINE" = true ] && [ "$CHAT_BRIDGE" = "kimaki" ]; then
# DM context filter + agent sync — only when the bridge is Kimaki, since
# these plugins rewrite Kimaki-specific prompts.
if [ "$CHAT_BRIDGE" = "kimaki" ]; then
if [ "$LOCAL_MODE" = true ]; then
KIMAKI_PLUGINS_DIR="$(npm root -g 2>/dev/null)/kimaki/plugins"
if [ "$DRY_RUN" = false ] && [ -d "$(dirname "$KIMAKI_PLUGINS_DIR")" ]; then
Expand Down Expand Up @@ -252,13 +248,11 @@ runtime_generate_config() {
OPENCODE_JSON="$OPENCODE_JSON\n }"

# Permission: allow DM workspace as external directory
if [ "$INSTALL_DATA_MACHINE" = true ]; then
OPENCODE_JSON="$OPENCODE_JSON,\n \"permission\": {"
OPENCODE_JSON="$OPENCODE_JSON\n \"external_directory\": {"
OPENCODE_JSON="$OPENCODE_JSON\n \"${DM_WORKSPACE_DIR}/**\": \"allow\""
OPENCODE_JSON="$OPENCODE_JSON\n }"
OPENCODE_JSON="$OPENCODE_JSON\n }"
fi
OPENCODE_JSON="$OPENCODE_JSON,\n \"permission\": {"
OPENCODE_JSON="$OPENCODE_JSON\n \"external_directory\": {"
OPENCODE_JSON="$OPENCODE_JSON\n \"${DM_WORKSPACE_DIR}/**\": \"allow\""
OPENCODE_JSON="$OPENCODE_JSON\n }"
OPENCODE_JSON="$OPENCODE_JSON\n }"

OPENCODE_JSON="$OPENCODE_JSON\n}"

Expand All @@ -277,18 +271,18 @@ runtime_generate_instructions() {

log "Phase 8: Generating AGENTS.md..."

# When Data Machine is installed, compose from registered sections.
# This handles WP-CLI prefix resolution, multisite detection, and plugin
# sections (intelligence, etc.) automatically at runtime.
if [ "$INSTALL_DATA_MACHINE" = true ] && [ "$DRY_RUN" = false ]; then
# Compose from Data Machine's SectionRegistry. DM is mandatory, and compose
# handles WP-CLI prefix resolution, multisite detection, and plugin sections
# (intelligence, etc.) automatically at runtime.
if [ "$DRY_RUN" = false ]; then
if wp_cmd datamachine agent compose AGENTS.md 2>/dev/null; then
log "AGENTS.md composed from SectionRegistry"
return
fi
warn "Compose failed — falling back to static template"
fi

# Fallback: minimal template for non-DM installs or dry-run.
# Fallback for dry-run or compose failure: ship a minimal static template.
local agents_tmpl="$SCRIPT_DIR/workspace/AGENTS.md"
if [ ! -f "$agents_tmpl" ]; then
error "AGENTS.md template not found at $agents_tmpl"
Expand Down
Loading
Loading