• huo0

    基于作者原帖:【拯救 5.6 Sol(1)】开箱即用、快速高效、减少上下文腐烂的Codex子代理实践

    丢给ai 写了一套 Claude Code适用版本的sh

    目前我也是刚上手体验```
    #!/usr/bin/env bash
    set -euo pipefail

    TARGET_HOME="${TARGET_HOME:-$HOME}"
    CLAUDE_DIR="$TARGET_HOME/.claude"
    TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
    BACKUP_DIR="$CLAUDE_DIR/backups/subagent-policy-$TIMESTAMP"
    STAGE_DIR="$(mktemp -d "${TMPDIR:-/tmp}/claude-subagent-policy.XXXXXX")"

    cleanup() {
    rm -rf "$STAGE_DIR"
    }
    trap cleanup EXIT

    mkdir -p "$CLAUDE_DIR/agents" "$BACKUP_DIR"

    backup_file() {
    local rel="$1"
    local src="$CLAUDE_DIR/$rel"
    if [[ -f "$src" ]]; then
    mkdir -p "$BACKUP_DIR/$(dirname "$rel")"
    cp -a "$src" "$BACKUP_DIR/$rel"
    printf 'present\t%s\n' "$rel" >> "$BACKUP_DIR/manifest.tsv"
    else
    printf 'absent\t%s\n' "$rel" >> "$BACKUP_DIR/manifest.tsv"
    fi
    }

    backup_file "settings.json"
    backup_file "CLAUDE.md"
    backup_file "agents/default.md"
    backup_file "subagent-policy.sh"

    python3 - "$CLAUDE_DIR/settings.json" "$CLAUDE_DIR/CLAUDE.md" "$STAGE_DIR/settings.json" <<'PY'
    from pathlib import Path
    import json
    import sys

    settings_path = Path(sys.argv[1])
    claude_md_path = Path(sys.argv[2])
    dst = Path(sys.argv[3])

    merged = {}

    if settings_path.exists():
    loaded = json.loads(settings_path.read_text(encoding="utf-8"))
    if not isinstance(loaded, dict):
    raise SystemExit("settings.json 顶层必须是 JSON 对象")
    merged.update(loaded)

    兼容修正:如果现有 CLAUDE.md 实际是误放的 JSON 配置,则迁移合并到 settings.json。

    if claude_md_path.exists():
    raw = claude_md_path.read_text(encoding="utf-8").strip()
    if raw.startswith("{"):
    try:
    misplaced = json.loads(raw)
    except json.JSONDecodeError:
    misplaced = None
    if isinstance(misplaced, dict):
    def deep_merge(a, b):
    for k, v in b.items():
    if isinstance(v, dict) and isinstance(a.get(k), dict):
    deep_merge(a[k], v)
    elif k not in a:
    a[k] = v
    return a
    deep_merge(merged, misplaced)

    merged.setdefault("$schema", "https://json.schemastore.org/claude-code-settings.json")

    env = merged.setdefault("env", {})
    if not isinstance(env, dict):
    raise SystemExit("settings.json 的 env 必须是对象")

    Claude Code 的并发值只计算子代理,因此主代理 + 6 个子代理对应 6。

    env["CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS"] = "6"

    设为 1 表示子代理不能继续派生子代理。

    env["CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH"] = "1"

    禁用内置 Explore/Plan 代理入口,策略上统一引导使用自定义 default。

    env["CLAUDE_CODE_DISABLE_EXPLORE_PLAN_AGENTS"] = "1"

    permissions = merged.setdefault("permissions", {})
    if not isinstance(permissions, dict):
    raise SystemExit("settings.json 的 permissions 必须是对象")

    deny = permissions.setdefault("deny", [])
    if not isinstance(deny, list):
    raise SystemExit("settings.json 的 permissions.deny 必须是数组")

    default 不是 Claude Code 的特殊保留名;这里通过提示词 + 禁用其他代理名来约束派发选择。

    for item in [
    "Agent(Explore)",
    "Agent(Plan)",
    "Agent(general-purpose)",
    "Agent(claude)",
    ]:
    if item not in deny:
    deny.append(item)

    dst.write_text(json.dumps(merged, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
    PY

    cat > "$STAGE_DIR/CLAUDE.md" <<'EOF'

    子代理使用

    子代理在我们的工作里只用于探索,是主代理的探子。把 default 子代理当成用于「宽而重」读取的工具:只有在它能减少主线程上下文污染、提高并行度或者提供独立核验时才使用,但需要比默认行为更积极、更频繁地考虑派发,而不只在任务开头使用。

    何时直接处理

    以下内容由主代理直接读取和处理,不派子代理:

    • 已知位置的小文件、少量代码或者单一事实;
    • 即将修改的确切代码;
    • 派发、等待和复核成本不低于直接读取的任务;
    • 奠基性文档,无论多长都由主代理完整阅读,包括架构文档、设计文档、交接备忘录以及其他用于建立全局视角的材料。它们的价值在细节和脉络,不能由子代理转述代替。

    何时适合派发

    适合交给子代理的任务:

    • 巨型文件(奠基性文档除外)、跨文件或者跨目录检索;
    • 相互独立、可以并行的探索或者核验;
    • 长任务中需要重新确认某个模块现状的工作;
    • 会产生大量日志、搜索结果或者外围材料的阅读。

    多个独立任务应在同一轮并发派发。

    委派与验证

    给子代理的任务必须自包含,明确检索范围、具体问题和期望输出。精度重要时,要求返回 file:line、符号名和必要的关键原文。

    子代理结果只是线索,可能遗漏或者出错。复核时顺着它提供的 file:line 和关键原文抽查必要的小范围内容,不重新通读它已经处理的全部材料。只有两类内容需要主代理完整阅读:即将修改的确切代码,以及奠基性文档。子代理对这两类内容最多负责定位。

    子代理默认只做探索、检索和核验。代码修改、方案取舍和最终验证由主代理负责。

    Claude Code 派发规则

    • 是否派发以及派发数量由主代理自主决定;较重探索应拆成多个独立轻任务并发处理。
    • 最多并行派发 6 个子代理。
    • 只使用名为 default 的自定义子代理,不使用 Explore、Plan、general-purpose、claude 或其他角色。
    • 使用命名子代理,不使用 /subtask 或其他 conversation fork(对话分叉)。命名子代理天然使用新的独立上下文,不继承主对话历史;因此每个任务都必须自包含。
    • 派发多个子代理后,主代理停止其他读取、检索、命令执行和文件修改,等待全部结果返回后再继续。
    • 每个子代理只使用一次,不恢复、不追派。需要进一步拆分时,由主代理重新创建新的自包含任务。
    • 子代理运行超过 10 分钟仍未完成时视为异常。主代理应检查代理面板或已有结果,采用可用的部分输出并停止该子代理,再决定是否拆分成更小任务重新派发。

    EOF

    cat > "$STAGE_DIR/agents-default.md" <<'EOF'


    name: default
    description: 通用只读探索子代理。用于巨型文件、跨文件或跨目录检索、并行探索、独立核验以及高输出量材料整理。主代理应主动使用;不要用于即将修改的确切代码或奠基性文档。
    tools: Read, Grep, Glob
    disallowedTools: Write, Edit, Bash, PowerShell, Agent, Skill, mcp__*
    model: haiku
    effort: low
    permissionMode: plan
    maxTurns: 30


    你是通用只读探索子代理,是主代理派出的探子。你只做探索、检索和核验:不改动任何东西,不做方案取舍或者最终判断,这些由主代理负责。

    不要派生、调用或者请求新的子代理。任务需要继续拆分时,把拆分建议返回给主代理。

    交付要求:

    • 产出直接提供给主代理作为行动依据。内容密集,不寒暄,不复述过程,不写客套结论。
    • 给证据,不做包装。关键处附上 file:line、符号名和必要的逐字原文,出处必须准确并足以复核。
    • 明确区分「看到的事实」和「你的推断」,存疑内容必须标注,不把猜测写成事实。
    • 压缩体量,但保留确切名称、签名、取值和路径,不在转述中改变精确信息。

    工作方式:

    • 每次调用只有一轮,任务必须自包含。不要反问,用这一轮尽量覆盖完整范围。
    • 无法答全时,明确说明查到了什么、没有覆盖什么、哪里存疑或者存在矛盾。宁可写明「没查到」或「没覆盖」,不要含糊省略。

    EOF

    python3 - "$STAGE_DIR/settings.json" "$STAGE_DIR/CLAUDE.md" "$STAGE_DIR/agents-default.md" <<'PY'
    from pathlib import Path
    import json
    import re
    import sys

    settings_path, claude_md_path, agent_path = map(Path, sys.argv[1:])
    settings = json.loads(settings_path.read_text(encoding="utf-8"))
    env = settings["env"]
    assert env["CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS"] == "6"
    assert env["CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH"] == "1"
    assert env["CLAUDE_CODE_DISABLE_EXPLORE_PLAN_AGENTS"] == "1"
    for item in ["Agent(Explore)", "Agent(Plan)", "Agent(general-purpose)", "Agent(claude)"]:
    assert item in settings["permissions"]["deny"]

    claude_md = claude_md_path.read_text(encoding="utf-8")
    assert claude_md.count("## 子代理使用") == 1
    assert "只使用名为 default" in claude_md

    agent = agent_path.read_text(encoding="utf-8")
    assert agent.startswith("---\n")
    assert re.search(r"(?m)^name: default$", agent)
    assert re.search(r"(?m)^tools: Read, Grep, Glob$", agent)
    assert re.search(r"(?m)^disallowedTools: .*Agent", agent)
    assert re.search(r"(?m)^model: haiku$", agent)
    assert re.search(r"(?m)^effort: low$", agent)
    assert re.search(r"(?m)^permissionMode: plan$", agent)
    PY

    install -m 600 "$STAGE_DIR/settings.json" "$CLAUDE_DIR/settings.json"
    install -m 644 "$STAGE_DIR/CLAUDE.md" "$CLAUDE_DIR/CLAUDE.md"
    install -m 644 "$STAGE_DIR/agents-default.md" "$CLAUDE_DIR/agents/default.md"

    python3 -m json.tool "$CLAUDE_DIR/settings.json" >/dev/null

    printf 'Claude Code 用户级子代理策略已写入。\n'
    printf '备份目录:%s\n' "$BACKUP_DIR"
    printf '已更新:%s\n' "$CLAUDE_DIR/settings.json"
    printf '已更新:%s\n' "$CLAUDE_DIR/CLAUDE.md"
    printf '已更新:%s\n' "$CLAUDE_DIR/agents/default.md"
    printf '已保存脚本:%s\n' "$CLAUDE_DIR/subagent-policy.sh"
    printf '新建或修改 agents 目录后,已运行的 Claude Code 会话需要重启一次。\n'

    主楼
  • cuican

    好用吗,佬,我也想试试,有没有后续优化

    #1
  • huo0

    有没有后续优化

    我这个一直在用,配合他那个tool mcp更爽,一定要配上

    #2

发表回复

登录后回复