From 699724bb789ba5996f1d8795cef5021beae38755 Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Sun, 3 May 2026 18:25:00 +0000 Subject: [PATCH] =?UTF-8?q?fix(claude):=20symlink=20CLAUDE.md=20=E2=86=92?= =?UTF-8?q?=20AGENTS.md=20for=20Claude-model=20opencode=20sessions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Claude model running inside an OpenCode session does not honor SOUL.md/MEMORY.md content composed into AGENTS.md alone — empirically it self-reports the DM bundle as 'not in context'. A side-by-side fresh session with the same config running glm-5.1 self-identifies as 'Extra Chill Bot' with phrasing pulled from SOUL.md. OpenCode reads both AGENTS.md and CLAUDE.md from cwd (it globs ["AGENTS.md", "CLAUDE.md", "CONTEXT.md"], deduped), so writing CLAUDE.md is purely additive. Claude Code reads only CLAUDE.md. The fix symlinks CLAUDE.md → AGENTS.md (relative target) so: - upgrade.sh Phase 5 self-heals the symlink after every compose - runtimes/opencode.sh fresh installs create the symlink at first run - claude-code/studio-code runtimes that ship a real CLAUDE.md are left untouched (the helper only acts when CLAUDE.md is missing or already a symlink) Closes #108 --- runtimes/opencode.sh | 20 ++++++++++++++++++++ upgrade.sh | 19 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/runtimes/opencode.sh b/runtimes/opencode.sh index c57d31a..8d213ae 100644 --- a/runtimes/opencode.sh +++ b/runtimes/opencode.sh @@ -375,6 +375,7 @@ _runtime_repair_opencode_json_additive() { runtime_generate_instructions() { if [ "$DRY_RUN" = false ] && [ -f "$SITE_PATH/AGENTS.md" ]; then log "Phase 8: AGENTS.md already exists — skipping (delete to regenerate)" + _opencode_symlink_claude_md return fi @@ -387,6 +388,7 @@ runtime_generate_instructions() { sync_homeboy_availability if wp_cmd datamachine memory compose AGENTS.md 2>/dev/null; then log "AGENTS.md composed from SectionRegistry" + _opencode_symlink_claude_md return fi warn "Compose failed — falling back to static template" @@ -407,8 +409,26 @@ runtime_generate_instructions() { if [ "$DRY_RUN" = true ]; then echo -e "${BLUE}[dry-run]${NC} Would generate AGENTS.md from template" + echo -e "${BLUE}[dry-run]${NC} Would symlink CLAUDE.md → AGENTS.md (Claude-model context)" else sed "s|{{WP_CLI_CMD}}|$wp_cli_display|g" "$agents_tmpl" > "$SITE_PATH/AGENTS.md" + _opencode_symlink_claude_md + fi +} + +# Symlink CLAUDE.md → AGENTS.md so Claude-model opencode sessions inherit the +# same DM context. OpenCode globs ["AGENTS.md", "CLAUDE.md", "CONTEXT.md"] from +# cwd; Claude Code reads only CLAUDE.md. Relative target survives directory moves. +# Skipped when CLAUDE.md is a regular file (claude-code/studio-code runtimes +# manage their own template-based CLAUDE.md). +# See: Extra-Chill/wp-coding-agents#108 +_opencode_symlink_claude_md() { + local agents_md="$SITE_PATH/AGENTS.md" + local claude_md="$SITE_PATH/CLAUDE.md" + [ -f "$agents_md" ] || return 0 + if [ -L "$claude_md" ] || [ ! -e "$claude_md" ]; then + (cd "$SITE_PATH" && ln -sf AGENTS.md CLAUDE.md) + log "Symlinked CLAUDE.md → AGENTS.md (covers Claude-model opencode sessions)" fi } diff --git a/upgrade.sh b/upgrade.sh index 21d1b6e..76c9d44 100755 --- a/upgrade.sh +++ b/upgrade.sh @@ -537,10 +537,12 @@ regenerate_agents_md() { local AGENTS_MD="$SITE_PATH/AGENTS.md" local BACKUP="$SITE_PATH/AGENTS.md.backup.$TIMESTAMP" + local CLAUDE_MD="$SITE_PATH/CLAUDE.md" 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 memory compose AGENTS.md $WP_ROOT_FLAG" + echo -e "${BLUE}[dry-run]${NC} Would symlink $CLAUDE_MD → AGENTS.md (Claude-model context)" return 0 fi @@ -575,6 +577,23 @@ regenerate_agents_md() { warn " Restored AGENTS.md from backup" fi fi + + # Symlink CLAUDE.md → AGENTS.md so Claude-model sessions get the same DM context. + # OpenCode reads both filenames from the cwd glob (AGENTS.md, CLAUDE.md, CONTEXT.md), + # Claude Code reads only CLAUDE.md. Symlink keeps both runtimes covered without + # duplicating content or risking drift on AGENTS.md regeneration. Relative target + # ensures the symlink survives directory moves. + # See: Extra-Chill/wp-coding-agents#108 + if [ -f "$AGENTS_MD" ]; then + # Skip if CLAUDE.md exists as a regular file (e.g. claude-code/studio-code runtimes + # generate their own CLAUDE.md from a template — don't clobber it). + if [ -L "$CLAUDE_MD" ] || [ ! -e "$CLAUDE_MD" ]; then + (cd "$SITE_PATH" && ln -sf AGENTS.md CLAUDE.md) + log " Symlinked CLAUDE.md → AGENTS.md (covers Claude-model opencode sessions)" + else + log " CLAUDE.md exists as a regular file — leaving it alone (runtime-managed)" + fi + fi } # ============================================================================