From 4d323810fbf3b9a02f382436dcc939d3b040e785 Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Wed, 22 Apr 2026 09:33:58 -0400 Subject: [PATCH 1/2] feat!: make Data Machine mandatory, drop --no-data-machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wp-coding-agents composes on top of Data Machine — memory files, auto- composed AGENTS.md, skills, workspace primitive, MCP surface. Without DM the installer degrades to "npm i -g claude + write a settings.json," which is not a product. Breaking: `--no-data-machine` is removed from setup.sh and upgrade.sh. Everyone gets DM. If a user changes their mind after the fact they can disable/uninstall the plugin via the admin UI. Managed-host framing is also dropped: wp-coding-agents is a local/VPS installer that runs node, npm, and systemd/launchd, so it was never going to work on WP.com / VIP / Pressable regardless of DM. The Data Machine plugin on its own is a normal WP plugin and can run on managed hosts — that's a separate onboarding path, not a setup.sh flag. Scope of cleanup: - setup.sh: drop flag, default, and help entry. Shebang comment reframes DM as substrate. - upgrade.sh: drop INSTALL_DATA_MACHINE default + the guard around regenerate_agents_md. Drift-check now always announces DM plugin install in dry-run. - lib/data-machine.sh: drop --no-data-machine skip branch from install_data_machine and create_dm_agent. - lib/skills.sh: Data Machine skills repo is now always cloned. - lib/detect.sh / lib/summary.sh: drop DM conditionals and credentials field. Summary unconditionally prints the DM block. - lib/repair-opencode-json.py: drop required --install-dm arg; the `dm-context-filter.ts` + `dm-agent-sync.ts` plugins are now keyed on CHAT_BRIDGE == kimaki alone. - runtimes/claude-code.sh, studio-code.sh, opencode.sh: - runtime_discover_dm_paths: drop early-return on !DM. - runtime_generate_config: collapse IF_DATA_MACHINE / IF_NO_DATA_MACHINE branching into a single DM-included code path. CLAUDE.md template loses its conditional sentinels; only the Studio conditional remains. - runtime_install_hooks: drop early-return on !DM. SessionStart hook + workspace allow rules always install. - runtime_generate_instructions: `wp datamachine agent compose AGENTS.md` is now the default; static template remains only as a dry-run / compose-failure fallback. - opencode permission block + DM kimaki plugins always wire up. - workspace/CLAUDE.md.tmpl: remove {{IF_DATA_MACHINE}} / {{IF_NO_DATA_MACHINE}} sentinel pair. - README.md: drop --no-data-machine row, reframe the old "With/Without DM" section as "What Data Machine Gives You." - skills/wp-coding-agents-setup/SKILL.md: drop Autonomous Operation question (Q3 — was the --no-data-machine proxy), drop the "no DM" command table rows, renumber remaining questions. docs/changelog.md is untouched (historical entries stay accurate; CHANGELOG is regenerated from commits at release per repo convention). --- README.md | 19 +++---- lib/data-machine.sh | 10 ---- lib/detect.sh | 1 - lib/repair-opencode-json.py | 14 ++---- lib/skills.sh | 4 +- lib/summary.sh | 34 ++++++------- runtimes/claude-code.sh | 37 +++++--------- runtimes/opencode.sh | 31 +++++------- runtimes/studio-code.sh | 68 ++++++++++---------------- setup.sh | 12 ++--- skills/wp-coding-agents-setup/SKILL.md | 20 ++------ upgrade.sh | 20 ++------ workspace/CLAUDE.md.tmpl | 7 +-- 13 files changed, 87 insertions(+), 190 deletions(-) diff --git a/README.md b/README.md index d07f91a..1f4c049 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,6 @@ systemctl start kimaki # or: systemctl start cc-connect | `--existing` | Add to existing WordPress (skip WP install) | | `--wp-path ` | Path to WordPress root (implies `--existing`) | | `--agent-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 ` | 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) | @@ -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 @@ -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 @@ -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: diff --git a/lib/data-machine.sh b/lib/data-machine.sh index 937a45f..0c52fbb 100644 --- a/lib/data-machine.sh +++ b/lib/data-machine.sh @@ -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 @@ -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 diff --git a/lib/detect.sh b/lib/detect.sh index d9e933f..40cf5af 100644 --- a/lib/detect.sh +++ b/lib/detect.sh @@ -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" diff --git a/lib/repair-opencode-json.py b/lib/repair-opencode-json.py index faf8b85..142fa04 100755 --- a/lib/repair-opencode-json.py +++ b/lib/repair-opencode-json.py @@ -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 @@ -19,7 +20,6 @@ repair-opencode-json.py --file \ --runtime \ --chat-bridge \ - --install-dm \ [--kimaki-plugins-dir ] \ [--apply] \ [--backup-suffix ] @@ -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. @@ -63,7 +62,7 @@ def expected_plugins( 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": + if chat_bridge == "kimaki": plugins.append(f"{kimaki_plugins_dir}/dm-context-filter.ts") plugins.append(f"{kimaki_plugins_dir}/dm-agent-sync.ts") @@ -120,11 +119,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", @@ -159,11 +153,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("/"), ) diff --git a/lib/skills.sh b/lib/skills.sh index 5c45b21..d26dfea 100644 --- a/lib/skills.sh +++ b/lib/skills.sh @@ -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 diff --git a/lib/summary.sh b/lib/summary.sh index 52e2a69..cffa4c6 100644 --- a/lib/summary.sh +++ b/lib/summary.sh @@ -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)" @@ -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 @@ -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() { diff --git a/runtimes/claude-code.sh b/runtimes/claude-code.sh index 8f903b5..3204845 100644 --- a/runtimes/claude-code.sh +++ b/runtimes/claude-code.sh @@ -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="" @@ -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=" + DISCOVER_LINE="Discover DM paths: \`$WP_CLI_DISPLAY datamachine agent paths\`" + SENTINEL_CONTENT=" ${AT_INCLUDES} ${DISCOVER_LINE} " - CLAUDE_MD=$(python3 -c " + CLAUDE_MD=$(python3 -c " import sys content = sys.argv[1] block = sys.argv[2] @@ -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') @@ -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" @@ -244,8 +228,9 @@ 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 @@ -253,7 +238,7 @@ runtime_generate_instructions() { 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" diff --git a/runtimes/opencode.sh b/runtimes/opencode.sh index 59c2c99..7ffe1c7 100644 --- a/runtimes/opencode.sh +++ b/runtimes/opencode.sh @@ -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 @@ -219,8 +214,8 @@ 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 DM memory is surfaced via Kimaki. + 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 @@ -252,13 +247,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}" @@ -277,10 +270,10 @@ 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 @@ -288,7 +281,7 @@ runtime_generate_instructions() { 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" diff --git a/runtimes/studio-code.sh b/runtimes/studio-code.sh index 9f2c9f8..0cf02cd 100755 --- a/runtimes/studio-code.sh +++ b/runtimes/studio-code.sh @@ -47,9 +47,6 @@ runtime_discover_dm_paths() { log "Phase 7: Configuring Studio Code..." DM_FILES=() - if [ "$INSTALL_DATA_MACHINE" != true ]; then - return - fi if [ "$DRY_RUN" = false ] && [ -f "$SITE_PATH/wp-config.php" ]; then AGENT_FLAG="" @@ -115,25 +112,24 @@ runtime_generate_config() { if [ "$DRY_RUN" = false ] && [ -f "$SITE_PATH/CLAUDE.md" ]; then log "Existing CLAUDE.md found — merging Data Machine context..." - if [ "$INSTALL_DATA_MACHINE" = true ]; then - # Build the DM sync block - AT_INCLUDES="" - for dm_file in "${DM_FILES[@]}"; do - AT_INCLUDES="${AT_INCLUDES}@${dm_file} + # Build the DM sync block + AT_INCLUDES="" + for dm_file in "${DM_FILES[@]}"; do + AT_INCLUDES="${AT_INCLUDES}@${dm_file} " - done + done - DISCOVER_LINE="Discover DM paths: \`studio wp datamachine agent paths\`" - SENTINEL_CONTENT=" + DISCOVER_LINE="Discover DM paths: \`studio wp datamachine agent paths\`" + SENTINEL_CONTENT=" ${AT_INCLUDES} ${DISCOVER_LINE} " - EXISTING=$(cat "$SITE_PATH/CLAUDE.md") + EXISTING=$(cat "$SITE_PATH/CLAUDE.md") - if echo "$EXISTING" | grep -q ''; then - # Update existing sentinel block - python3 -c " + if echo "$EXISTING" | grep -q ''; then + # Update existing sentinel block + python3 -c " import sys content = sys.stdin.read() block = sys.argv[1] @@ -143,17 +139,16 @@ si = content.index(start) ei = content.index(end) + len(end) print(content[:si] + block + content[ei:], end='') " "$SENTINEL_CONTENT" <<< "$EXISTING" > "$SITE_PATH/CLAUDE.md" - else - # Append DM section to existing CLAUDE.md - cat >> "$SITE_PATH/CLAUDE.md" << APPENDEOF + else + # Append DM section to existing CLAUDE.md + cat >> "$SITE_PATH/CLAUDE.md" << APPENDEOF ## Data Machine Memory ${SENTINEL_CONTENT} APPENDEOF - fi - log "Added Data Machine context to existing CLAUDE.md" fi + log "Added Data Machine context to existing CLAUDE.md" return fi @@ -171,24 +166,19 @@ APPENDEOF # Studio sites always have STUDIO.md — include it CLAUDE_MD=$(echo "$CLAUDE_MD" | sed '/{{IF_STUDIO}}/d; /{{END_IF_STUDIO}}/d') - # 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: \`studio wp datamachine agent paths\`" - SENTINEL_CONTENT=" + DISCOVER_LINE="Discover DM paths: \`studio wp datamachine agent paths\`" + SENTINEL_CONTENT=" ${AT_INCLUDES} ${DISCOVER_LINE} " - CLAUDE_MD=$(python3 -c " + CLAUDE_MD=$(python3 -c " import sys content = sys.argv[1] block = sys.argv[2] @@ -198,10 +188,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') @@ -211,10 +197,6 @@ print(content[:si] + block + content[ei:], end='') } runtime_install_hooks() { - if [ "$INSTALL_DATA_MACHINE" != true ]; then - return - fi - log "Installing Studio Code SessionStart hook..." local hooks_dir="$SITE_PATH/.claude/hooks" @@ -316,8 +298,8 @@ 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. + if [ "$DRY_RUN" = false ]; then if wp_cmd datamachine agent compose AGENTS.md 2>/dev/null; then log "AGENTS.md composed from SectionRegistry" return @@ -325,7 +307,7 @@ runtime_generate_instructions() { 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" diff --git a/setup.sh b/setup.sh index a068752..ab2876b 100755 --- a/setup.sh +++ b/setup.sh @@ -10,7 +10,11 @@ # Local (macOS): EXISTING_WP=/path/to/wordpress ./setup.sh --local # Claude Code: ./setup.sh --runtime claude-code # Without Discord: ./setup.sh --no-chat -# Without DM: ./setup.sh --no-data-machine +# +# Data Machine is the substrate wp-coding-agents composes on top of — memory +# files (SOUL/MEMORY/USER/RULES/SITE), auto-composed AGENTS.md, skills, +# workspace primitive, MCP surface. It is not optional. Uninstall the plugin +# later if you don't want it. # set -e @@ -38,7 +42,6 @@ MODE="fresh" LOCAL_MODE=false SKIP_DEPS=false SKIP_SSL=false -INSTALL_DATA_MACHINE=true INSTALL_CHAT=true CHAT_BRIDGE="" SHOW_HELP=false @@ -79,10 +82,6 @@ while [[ $# -gt 0 ]]; do SKIP_DEPS=true shift ;; - --no-data-machine) - INSTALL_DATA_MACHINE=false - shift - ;; --no-chat) INSTALL_CHAT=false shift @@ -172,7 +171,6 @@ OPTIONS: Available: ${AVAILABLE_RUNTIMES[*]} --agent-slug Override Data Machine agent slug (default: derived from domain) --agent-name Override Data Machine agent display name (default: blogname) - --no-data-machine Skip Data Machine plugin (no persistent memory/scheduling) --no-chat Skip chat bridge installation --chat Chat bridge to install (default: kimaki for opencode, cc-connect for claude-code) diff --git a/skills/wp-coding-agents-setup/SKILL.md b/skills/wp-coding-agents-setup/SKILL.md index 26b12fc..9ec3938 100644 --- a/skills/wp-coding-agents-setup/SKILL.md +++ b/skills/wp-coding-agents-setup/SKILL.md @@ -36,14 +36,7 @@ This skill is for the **local agent** (Claude Code, Cursor, etc.) assisting with > > If multiple are installed, the script auto-detects. You can also specify with `--runtime` (e.g., `--runtime claude-code,studio-code`)." -### Question 3: Autonomous Operation - -> "Do you want **autonomous operation** capabilities? This includes Data Machine — a self-scheduling system that lets your agent set reminders, queue tasks, and operate 24/7 without human intervention. -> -> - **Yes (recommended for content sites)** — Full autonomy, self-scheduling, proactive operation -> - **No (simpler setup)** — Agent responds when asked, no self-scheduling overhead" - -### Question 4: Chat Bridge +### Question 3: Chat Bridge > "How do you want to communicate with your agent? > @@ -52,7 +45,7 @@ This skill is for the **local agent** (Claude Code, Cursor, etc.) assisting with > - **Telegram** — Your agent gets a Telegram bot (via @grinev/opencode-telegram-bot). OpenCode only. > - **No chat bridge** — Run the agent manually via SSH or terminal when needed." -### Question 5: Agent Name +### Question 4: Agent Name > "What would you like to name your agent? This becomes the agent slug used by Data Machine for identity and memory files. > @@ -60,7 +53,7 @@ This skill is for the **local agent** (Claude Code, Cursor, etc.) assisting with Maps to `--agent-slug `. If the user is happy with the default, skip this flag. -### Question 6: Server/Local Details +### Question 5: Server/Local Details **For VPS installs:** @@ -73,7 +66,7 @@ Maps to `--agent-slug `. If the user is happy with the default, skip this > "Where is WordPress installed on your machine? (e.g., `~/Studio/my-wordpress-website`, `/Applications/MAMP/htdocs/wordpress`)" -### Question 7: For Existing WordPress +### Question 6: For Existing WordPress If they chose existing WordPress (VPS or local): @@ -91,7 +84,6 @@ Based on their answers, construct the appropriate command: | Fresh VPS + Claude Code + DM | `SITE_DOMAIN=example.com ./setup.sh --runtime claude-code` | | Fresh VPS + DM + Telegram | `SITE_DOMAIN=example.com ./setup.sh --chat telegram` | | Fresh VPS + DM, no chat | `SITE_DOMAIN=example.com ./setup.sh --no-chat` | -| Fresh VPS, no DM | `SITE_DOMAIN=example.com ./setup.sh --no-data-machine` | | Existing VPS + DM | `EXISTING_WP=/var/www/mysite ./setup.sh --existing` | | Existing VPS + Claude Code | `EXISTING_WP=/var/www/mysite ./setup.sh --existing --runtime claude-code` | | **Local + OpenCode + DM + Discord** | `EXISTING_WP=~/Studio/my-site ./setup.sh --local` | @@ -100,7 +92,6 @@ Based on their answers, construct the appropriate command: | **Local + multiple runtimes** | `EXISTING_WP=~/Studio/my-site ./setup.sh --local --runtime claude-code,studio-code` | | **Local + DM + Telegram** | `EXISTING_WP=~/Studio/my-site ./setup.sh --local --chat telegram` | | **Local + DM, no chat** | `EXISTING_WP=~/Studio/my-site ./setup.sh --local --no-chat` | -| **Local, no DM** | `EXISTING_WP=~/Studio/my-site ./setup.sh --local --no-data-machine` | | **Local (Studio) with WP_CMD** | `WP_CMD="studio wp" EXISTING_WP=~/Studio/my-site ./setup.sh --local` | | **Using --wp-path** | `./setup.sh --wp-path ~/Studio/my-site --runtime claude-code` | | Multisite | `SITE_DOMAIN=example.com ./setup.sh --multisite` | @@ -126,7 +117,6 @@ Before running anything, summarize what you're about to do: > - **Agent name:** example (or custom name) > - **Type:** Fresh install > - **Runtime:** OpenCode -> - **Data Machine:** Yes > - **Chat bridge:** Kimaki (Discord) > - **Command:** `SITE_DOMAIN=example.com ./setup.sh` > @@ -205,7 +195,7 @@ wp option get siteurl --path=/path/to/site studio wp option get siteurl ``` -### Data Machine (if installed) +### Data Machine **VPS:** ```bash diff --git a/upgrade.sh b/upgrade.sh index 5902b61..af6a563 100755 --- a/upgrade.sh +++ b/upgrade.sh @@ -82,7 +82,6 @@ SHOW_HELP=false LOCAL_MODE=false SKIP_DEPS=true SKIP_SSL=true -INSTALL_DATA_MACHINE=true INSTALL_CHAT=true INSTALL_SKILLS=true RUN_AS_ROOT=true @@ -469,7 +468,7 @@ _sync_kimaki_config() { # opencode.json is user-owned (model settings, agent prompt files, permissions, # etc.), so this phase is read-only by default. It compares the file's # `plugin` array against what current setup would produce for the detected -# (RUNTIME, CHAT_BRIDGE, INSTALL_DATA_MACHINE) combo and surfaces drift. +# (RUNTIME, CHAT_BRIDGE) combo and surfaces drift. # # The most common drift vectors: # - install predates v0.4.0 (no `plugin` key at all) @@ -503,8 +502,6 @@ check_opencode_json_drift() { fi local BRIDGE_ARG="${CHAT_BRIDGE:-none}" - local DM_ARG="false" - [ "$INSTALL_DATA_MACHINE" = true ] && DM_ARG="true" # Kimaki plugins dir — match what _sync_kimaki_config resolved. local PLUGINS_DIR="${RESOLVED_KIMAKI_PLUGINS_DIR:-/opt/kimaki-config/plugins}" @@ -512,14 +509,13 @@ check_opencode_json_drift() { if [ "$REPAIR_OPENCODE_JSON" = true ]; then log "Phase 2b: Repairing opencode.json plugin array..." if [ "$DRY_RUN" = true ]; then - echo -e "${BLUE}[dry-run]${NC} Would run: python3 $HELPER --file $OPENCODE_JSON_FILE --runtime $RUNTIME --chat-bridge $BRIDGE_ARG --install-dm $DM_ARG --kimaki-plugins-dir $PLUGINS_DIR --apply" + echo -e "${BLUE}[dry-run]${NC} Would run: python3 $HELPER --file $OPENCODE_JSON_FILE --runtime $RUNTIME --chat-bridge $BRIDGE_ARG --kimaki-plugins-dir $PLUGINS_DIR --apply" # Still show the diagnostic even in dry-run local dry_out dry_out=$(python3 "$HELPER" \ --file "$OPENCODE_JSON_FILE" \ --runtime "$RUNTIME" \ --chat-bridge "$BRIDGE_ARG" \ - --install-dm "$DM_ARG" \ --kimaki-plugins-dir "$PLUGINS_DIR" 2>&1 || true) echo "$dry_out" | sed 's/^/ /' return 0 @@ -530,7 +526,6 @@ check_opencode_json_drift() { --file "$OPENCODE_JSON_FILE" \ --runtime "$RUNTIME" \ --chat-bridge "$BRIDGE_ARG" \ - --install-dm "$DM_ARG" \ --kimaki-plugins-dir "$PLUGINS_DIR" \ --apply \ --backup-suffix "$TIMESTAMP" 2>&1) && rc=0 || rc=$? @@ -564,7 +559,6 @@ check_opencode_json_drift() { --file "$OPENCODE_JSON_FILE" \ --runtime "$RUNTIME" \ --chat-bridge "$BRIDGE_ARG" \ - --install-dm "$DM_ARG" \ --kimaki-plugins-dir "$PLUGINS_DIR" 2>&1) && rc=0 || rc=$? local status @@ -600,10 +594,9 @@ sync_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" - if [ "$INSTALL_DATA_MACHINE" = true ]; then - echo -e "${BLUE}[dry-run]${NC} Would clone Extra-Chill/data-machine-skills → $SKILLS_DIR" - fi + 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 @@ -626,11 +619,6 @@ regenerate_agents_md() { local AGENTS_MD="$SITE_PATH/AGENTS.md" local BACKUP="$SITE_PATH/AGENTS.md.backup.$TIMESTAMP" - if [ "$INSTALL_DATA_MACHINE" != true ]; then - warn " Data Machine not installed — skipping (nothing to compose)" - return 0 - fi - if [ "$DRY_RUN" = true ]; then echo -e "${BLUE}[dry-run]${NC} Would backup $AGENTS_MD → $BACKUP" echo -e "${BLUE}[dry-run]${NC} Would run: $WP_CMD datamachine agent compose AGENTS.md $WP_ROOT_FLAG" diff --git a/workspace/CLAUDE.md.tmpl b/workspace/CLAUDE.md.tmpl index a9dfe61..bcf9156 100644 --- a/workspace/CLAUDE.md.tmpl +++ b/workspace/CLAUDE.md.tmpl @@ -5,11 +5,6 @@ {{END_IF_STUDIO}} ## Data Machine Memory -{{IF_DATA_MACHINE}} + -{{END_IF_DATA_MACHINE}} -{{IF_NO_DATA_MACHINE}} -Data Machine not installed. Install with: -`{{WP_CLI_CMD}} plugin install data-machine --activate` -{{END_IF_NO_DATA_MACHINE}} From 99603c887c6787be91deeb1bd048a1b04f86ad68 Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Wed, 22 Apr 2026 10:21:15 -0400 Subject: [PATCH 2/2] chore: tighten three DM-conditional comments missed in the first pass MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With DM mandatory, "When Data Machine is installed, …" and "only when DM memory is surfaced via Kimaki" read as vestigial. Rewrite them to pin the real condition: the chat bridge being Kimaki, since that's what actually gates the dm-context-filter / dm-agent-sync plugins. - README.md: Kimaki "Filter redundant context" bullet drops the DM clause. - runtimes/opencode.sh: comment above the Kimaki plugins block pins on "bridge is Kimaki" instead of "DM memory surfaced via Kimaki". - lib/repair-opencode-json.py: same comment update in expected_plugins(). No behavior change. --- README.md | 2 +- lib/repair-opencode-json.py | 3 ++- runtimes/opencode.sh | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1f4c049..e2a93fd 100644 --- a/README.md +++ b/README.md @@ -257,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. diff --git a/lib/repair-opencode-json.py b/lib/repair-opencode-json.py index 142fa04..9e92c4f 100755 --- a/lib/repair-opencode-json.py +++ b/lib/repair-opencode-json.py @@ -61,7 +61,8 @@ 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. + # 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") diff --git a/runtimes/opencode.sh b/runtimes/opencode.sh index 7ffe1c7..9f73861 100644 --- a/runtimes/opencode.sh +++ b/runtimes/opencode.sh @@ -214,7 +214,8 @@ runtime_generate_config() { OPENCODE_PLUGINS="${OPENCODE_PLUGINS}\n \"opencode-claude-auth@latest\"," fi - # DM context filter + agent sync — only when DM memory is surfaced via Kimaki. + # 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"