If you're authoring shared instructions across both Claude Code and Cowork from the same repo, bridge
AGENTS.md → CLAUDE.mdwith a symlink, not an@import— Code expands@AGENTS.md, Cowork treats it as literal text. Discovered the hard way; fix isln -s AGENTS.md CLAUDE.md.
Context. Spent yesterday refactoring a combo repo to work cleanly across Code + Cowork — extracting procedures into skills, trimming AGENTS.md, putting an audit on quarterly cadence. Found 5 Code/Cowork asymmetries that matter for anyone using both surfaces on the same repo.
1. CLAUDE.md @import doesn't work in Cowork.
The Anthropic memory docs recommend a CLAUDE.md containing @AGENTS.md to bridge naming conventions. Code expands this directive on load. Cowork treats it as literal text. Result: instructions silently disappear in Cowork while your Code session looks fine.
Fix: replace the import with a symlink.
rm CLAUDE.md && ln -s AGENTS.md CLAUDE.mdSymlinks are filesystem-transparent — both surfaces read CLAUDE.md and get AGENTS.md's content. Single source of truth, no expansion semantics needed. Trade-off: git diff shows it as a typechange rather than visible text. Worth it.
2. Skill discovery is surface-different.
- Code: filesystem-scans
~/.claude/skills/and project-local<repo>/.claude/skills/automatically. - Cowork: only registers skills you explicitly import via Customize → Add skill (UI). Doesn't auto-discover the filesystem.
So loose user skills under ~/.claude/skills/ are Code-only by default. You have to manually import each one into Cowork.
3. Cowork's import is a snapshot, not a live link.
When you import a skill from a file, Cowork copies it into its own storage at ~/Library/Application Support/Claude/local-agent-mode-sessions/skills-plugin/.../skills/. Later edits to the Code source don't propagate. Edit-then-forget creates silent drift — Code sees your tightened description; Cowork still has the old version.
Drift-detection script I wrote that you can lift:
# ~/.claude/skills/workflow-hygiene/audit-cowork-drift.sh
# Reports NOT-IN-COWORK / DRIFTED / COWORK-ONLY. Silent = clean.Full script in this dropdown
#!/usr/bin/env bash
# audit-cowork-drift.sh — detect Code↔Cowork skill copy drift.
#
# Cowork's "Customize → Add skill → import from file" copies SKILL.md into
# Cowork-managed storage. After the import, the two copies (Code's source +
# Cowork's frozen snapshot) drift independently — edits in one don't
# propagate to the other. This script surfaces the drift.
#
# Usage:
# audit-cowork-drift.sh # checks ~/.claude/skills/ + ./.claude/skills/
# audit-cowork-drift.sh <skill-dir> [...] # checks additional Code-side dirs
#
# Output:
# NOT-IN-COWORK (origin): <name> — exists in Code, not imported into Cowork
# DRIFTED (origin): <name> — both exist but contents differ; re-import to sync
# COWORK-ONLY: <name> — exists in Cowork only (plugin-bundled or manually added)
#
# "origin" is `personal` for ~/.claude/skills/ or `project-local` for any
# <repo>/.claude/skills/. Silent on skills that match — no output = clean.
set -euo pipefail
CODE_PERSONAL_DIR="$HOME/.claude/skills"
COWORK_ROOT="$HOME/Library/Application Support/Claude/local-agent-mode-sessions/skills-plugin"
# Resolve dir to its canonical path (follow symlinks), suppress errors.
canonical() {
cd "$1" 2>/dev/null && pwd -P
}
# Collect Code-side skill dirs: personal + cwd project-local + any explicit args.
SKILL_DIRS=("$CODE_PERSONAL_DIR")
PERSONAL_CANON=$(canonical "$CODE_PERSONAL_DIR" || true)
if [ -d "$PWD/.claude/skills" ]; then
PWD_CANON=$(canonical "$PWD/.claude/skills" || true)
if [ -n "$PWD_CANON" ] && [ "$PWD_CANON" != "$PERSONAL_CANON" ]; then
SKILL_DIRS+=("$PWD/.claude/skills")
fi
fi
for arg in "$@"; do
if [ -d "$arg" ]; then
SKILL_DIRS+=("$arg")
else
echo "warning: $arg is not a directory, skipping" >&2
fi
done
# Cowork stores skills at:
# $COWORK_ROOT/<plugin-id>/<account-id>/skills/<name>/SKILL.md
# Find the active skills dir (most recent mtime if multiple accounts exist).
COWORK_SKILLS_DIR=$(find "$COWORK_ROOT" -type d -name skills 2>/dev/null \
| xargs -I{} stat -f "%m %N" {} 2>/dev/null \
| sort -rn | head -1 | cut -d' ' -f2-)
if [ -z "$COWORK_SKILLS_DIR" ] || [ ! -d "$COWORK_SKILLS_DIR" ]; then
echo "warning: no Cowork skills directory found under $COWORK_ROOT" >&2
echo " (Cowork may not be installed, or no skills have been imported yet)" >&2
exit 0
fi
# Track which skill names we've seen on the Code side (for the reverse pass).
CODE_NAMES_FILE=$(mktemp)
trap 'rm -f "$CODE_NAMES_FILE"' EXIT
# For each Code-side dir, check each skill against Cowork.
for dir in "${SKILL_DIRS[@]}"; do
DIR_CANON=$(canonical "$dir" || echo "$dir")
if [ "$DIR_CANON" = "$PERSONAL_CANON" ]; then
origin="personal"
else
origin="project-local"
fi
for code_skill in "$dir"/*/SKILL.md; do
[ -f "$code_skill" ] || continue
name=$(basename "$(dirname "$code_skill")")
echo "$name" >> "$CODE_NAMES_FILE"
cowork_skill="$COWORK_SKILLS_DIR/$name/SKILL.md"
if [ ! -f "$cowork_skill" ]; then
echo "NOT-IN-COWORK ($origin): $name"
elif ! diff -q "$code_skill" "$cowork_skill" >/dev/null 2>&1; then
echo "DRIFTED ($origin): $name"
fi
done
done
# Reverse pass: skills in Cowork but no Code counterpart anywhere.
for cowork_skill in "$COWORK_SKILLS_DIR"/*/SKILL.md; do
[ -f "$cowork_skill" ] || continue
name=$(basename "$(dirname "$cowork_skill")")
if ! grep -qx "$name" "$CODE_NAMES_FILE"; then
echo "COWORK-ONLY: $name"
fi
done4. Cowork's file import only takes single-file SKILL.md.
If your skill has bundled assets (helper scripts, reference docs), Cowork's import UI won't accept the directory. Options: inline the assets into SKILL.md, package as a plugin (~/.claude/plugins/marketplaces/<name>/), or accept that the skill is Code-only.
5. claude is a reserved word in skill names.
Cowork's name validator rejects any skill name containing claude. Other product names may have similar constraints. Substitute (e.g., I named one bridging-agents-md-cowork-md after the validator rejected bridging-agents-md-claude-md).
Net. The portable form across both surfaces is: AGENTS.md as canonical brief, CLAUDE.md as a symlink to it, skills authored as single-file SKILL.md with neutral names, imported once to Cowork, then audited periodically for drift. None of this is in the docs as far as I can tell—discovered empirically.