跳到主要内容
    ↑↓ 选择↵ 打开esc 关闭
    bojackduy

    Loopd

    @bojackduy/opencode-loopd·v1.9.2·智能体编排

    Codex-inspired background goal engine for OpenCode — autonomous subagents, engine-driven loop, child worker sessions and modal TUI dashboard. Like Claude Code loop for OpenCode.

    GitHub 星标

    0

    月装机量

    3,243

    近 7 天 112

    综合评分

    41.6

    生态多维模型

    最近提交

    5 小时前

    2026-09-13

    快速安装与配置

    opencode.json

    写入当前项目的 opencode.json,只对这个仓库生效。

    opencode.json

    {
      "$schema": "https://opencode.ai/config.json",
      "plugin": ["@bojackduy/opencode-loopd@1.9.2"]
    }

    OpenCode 启动时会通过内嵌运行时自动加载 npm 依赖并缓存至本地目录,无需手动在全局环境执行安装。

    Codex-inspired background goal engine for OpenCode — autonomous subagents, engine-driven loop, and modal TUI dashboard. Like Claude Code's loop, for OpenCode.

    Run long-running tasks as autonomous child sessions (subagents) while the main chat stays interactive. Create a goal with /goal, watch it loop in the background, and monitor everything from a keyboard-driven TUI — without blocking the parent conversation.

    npm version license opencode plugin TUI

    Loop Dashboard — modal TUI with goals, running indicator, and insert mode

    Modal dashboard (/loop / <leader>o): zero chat pollution — keys are trapped inside the dialog, NORMAL vs INSERT modes, vivid per-status coloring.

    Why opencode-loopd

    • Background agents, not blocked chats — an OpenCode plugin that spawns a dedicated worker (child) session per goal. The parent stays free to keep chatting.
    • Codex-style engine-driven loop — idle detection → continuation steering with accumulated context (progress history, transcript tail, inbox). No prompt spam in the parent.
    • Parent ↔ child visibilitylist/inspect/read_transcript/send_input give the parent full observability. Bidirectional inbox lets you steer mid-run.
    • Safe by default — per-goal artifact isolation (.opencode/loopd/goals/<id>/), maxTurns/maxFailures/maxNoProgress, force-finish → semantic complete_goal summary → parent notification via wake-up injection.
    • Scheduled intervalsscheduleEveryMs/scheduleMaxRuns auto-requeues the same goal every N ms (e.g., 10s monitor, 1h report) without manual /goal spam — 5s poll, skip-if-running, workspaceWrite serialization, inbox Scheduled tick N/M.
    • Modal TUI dashboard<leader>o or /loop opens a focused dialog (no leak to chat prompt). Vim-style navigation, live running indicator, per-status borders.

    Keywords: opencode opencode-plugin background-agent autonomous subagent loop goal tui codex claude-code worker

    What it is

    opencode-loopd is an OpenCode plugin (server + TUI) that adds background goals to OpenCode. Each goal owns a worker (child) subagent that loops autonomously; the loop engine drives continuations; the schedule worker requeues the same goal on an interval (scheduleEveryMs); the dashboard and owner tools keep the parent in control. Think Codex goals or Claude Code loop, but native to OpenCode's session model — with scheduled intervals for repetitive dialogues.

    Install

    Plugin — simple (no installer, just the plugin)

    Add the package to both configs.

    ~/.config/opencode/opencode.jsonc — server engine:

    {
      "plugin": ["@bojackduy/opencode-loopd"]
    }
    

    ~/.config/opencode/tui.json — dashboard (modal TUI):

    {
      "plugin": ["@bojackduy/opencode-loopd"]
    }
    

    Then restart OpenCode. Verify with /loop (palette → Loop Dashboard) or <leader>o.

    For a local checkout:

    // opencode.jsonc
    { "plugin": ["./path/to/opencode-loopd"] }
    // tui.json
    { "plugin": ["./path/to/opencode-loopd"] }
    

    Installer — also installs /goal + skill

    npx -y @bojackduy/opencode-loopd@latest
    

    Registers the plugin, installs the /goal slash command and the loopd skill into ~/.config/opencode/. Run again to update. Then restart OpenCode.

    Uninstall:

    npx -y @bojackduy/opencode-loopd@latest --uninstall
    

    Or via global npm:

    npm install -g @bojackduy/opencode-loopd@latest
    opencode-loopd            # install
    opencode-loopd --uninstall # remove
    

    Then restart OpenCode.

    Manual (local dev)

    Add to ~/.config/opencode/opencode.jsonc:

    {
      "plugin": ["@bojackduy/opencode-loopd"]
    }
    

    Or for local checkout:

    {
      "plugin": ["/Users/you/Code/opencode-loopd"]
    }
    

    For safe code-editing defaults, configure the server plugin with an agent and verification commands:

    {
      "plugin": [[
        "@bojackduy/opencode-loopd",
        {
          "defaultAgent": "smart-agent",
          "defaultChecks": ["bun test", "bun run typecheck"]
        }
      ]]
    }
    

    opencode-loopd exposes:

    • opencode-loopd/server → engine plugin
    • opencode-loopd/tui → dashboard plugin

    Usage

    1. Create a goal — /goal

    From any session, tell the agent:

    /goal fetch the latest AI news and save 10 items to ai-news.md
    

    Or be explicit:

    Create a background goal to find all .ts files in src/, count lines, and write the summary to line-counts.md — verify with grep -c.
    

    The agent will clarify (what/where/how to verify) and then call loopd_create_goal. The worker starts immediately in a hidden child session.

    2. Monitor with dashboard — /loop

    Press <leader>o or open the command palette → "Loop Dashboard" (also /loop).

    Dashboard (NORMAL / INSERT :):

    • j/k — move selection
    • g/G — top / bottom
    • o — open child session (full transcript, native OpenCode view)
    • p/r/R/x — pause / resume / retry / clear selected goal
    • : — insert mode → :send <message> to steer, :force / :block to finish manually
    • ? — toggle help — help stays open while you type
    • Ctrl+N — back to NORMAL
    • q — close

    The dashboard traps all keys — even when open via the palette, the chat input cursor won't blink underneath.

    3. Inspect from the main agent (owner tools)

    The parent never needs the dashboard — it can ask:

    list_background_goals()          — status snapshot
    inspect_background_goal()        — full detail: objective, progress, blocker, runtime
    read_goal_transcript()           — last N worker messages (what it's doing)
    send_goal_input(goalID, msg)     — steer: "skip appendix PDFs"
    pause_goal(goalID) / resume / clear
    

    4. Worker tools (child session)

    The child sees:

    • get_goal — read objective, contract, progress, failures
    • report_goal_progress — after durable writes
    • complete_goal — only when checks pass, with evidence
    • block_goal — real blocker needing user
    • question (OpenCode builtin) — clarification → TUI blocker tab

    Completion is semantic: the child writes the summary; the plugin forwards it to the parent via wake-up injection. If limits are hit, the engine first force-asks the child to complete_goal; only if ignored does it auto-block with a generic message.

    Architecture

                            ┌─────────────────────────┐
                            │  Main session (parent)  │
                            │  owner tools            │
                            │  inspect / steer / pause│
                            └────────────┬────────────┘
                                         │  inbox → child
                                         │  wake-up ← engine
                 ┌───────────────────────┼───────────────────────┐
                 ▼                       ▼                       ▼
            ┌─────────┐           ┌──────────┐            ┌─────────┐
            │  Goal A │           │  Goal B  │            │  Goal C │
            │ active  │           │ blocked  │            │  paused │
            └────┬────┘           └────┬─────┘            └────┬────┘
                 │                     │                       │
                 └─────────────────────┼───────────────────────┘
                                       │
                         ┌─────────────┴─────────────┐
                         ▼                           ▼
                  Loopd engine  ──────────►   Child worker (subagent)
                  (plugin server)  steering   get_goal / report / complete
                     │  lease / retry / polling       │  block / question
                     │  force-finish / notify         ▼
                     │                         .opencode/loopd/goals/<id>/
                     │                           progress.md / artifacts
                     └─────────────────────────────────┘
    
    • Engine-driven loop (like Codex): session.idle → lease + retry + polling → re-prompt child. Not a parent-driven re-prompt machine.
    • Scheduled requeue (1.7): createScheduleWorker 5s scans complete goals with scheduleEveryMs/maxRuns; complete→active resurrect with Scheduled tick N/M inbox, skip-if-running and workspaceWrite gate.
    • Accumulated context: each continuation includes progress history, transcript tail, inbox messages, and artifact dir (unless objective names another dir).
    • Parent wake-up: when the child calls complete_goal/block_goal, tool.execute.after injects the child's semantic summary into the owner's session — you see "Loop goal … completed: …" without polling.

    Artifacts

    Every goal writes under its own directory (.opencode/loopd/goals/<goal-id>/); progressFile defaults there. The dashboard and transcript never pollute the project root. If your objective says save to ./reports/, that wins.

    Example — multi-turn with force-finish

    # Parent: /goal
    goal: "Generate 5 files file1..5.md under artifacts/, 2 lines each — verify with glob."
    maxTurns: 1
    
    # Turn 1: child writes file1..3, reports progress
    # → engine hits maxTurns, injects FINAL REPORT REQUIRED
    # Turn 2 (forced): child wraps up, calls complete_goal(summary="created 5 files…", evidence="glob confirmed…")
    # → engine forwards to parent: "Loop goal … completed: created 5 files…"
    # → Artifacts: .opencode/loopd/goals/<id>/file*.md
    

    See assets/demo.png above for the dashboard at rest (0 active, 7 done) with vivid status colors, running spinner, and INSERT badge.

    Configuration

    Goals accept:

    Option Default Description
    maxTurns 50 Max continuation turns before force-finish
    maxFailures 3 Consecutive failures before block
    maxNoProgress 3 Turns without progress before force-finish
    timeoutMs 300000 Per-turn lease (5 min)
    compactEvery Compact child every N turns
    scheduleEveryMs Interval in ms to auto-requeue the same goal after each completion. Minimum 1000. Enables repetitive dialogue reduction without manual re-prompt
    scheduleMaxRuns Maximum total runs including the initial run. Undefined = unlimited. Requires scheduleEveryMs
    checks [] Shell commands that must pass for complete_goal
    checkCwd artifact directory Directory where completion checks run; workspace writes default to project root
    workspaceWrite true Marks shared-workspace mutation; only one active workspace writer is allowed. Set false explicitly for artifact-only/read-only work
    agent defaultAgent Worker agent; goal creation fails if neither is configured nor supplied
    progressFile <artifactDir>/progress.md Transaction state file
    artifactDir goals/<id>/ Auto — override only if objective names another dir

    Artifacts, logs, and state live under .opencode/loopd/ (project-local). Locks live in /tmp/loopd-locks/<project-hash>/ to avoid snapshot noise.

    Workspace-writing goals must have deterministic checks and are serialized to prevent concurrent agents or git stash operations from overwriting each other. Artifact-only research goals may run concurrently by setting workspaceWrite: false explicitly.

    Scheduled goals — repetitive dialogues without manual re-prompt

    One /goal can now loop on an interval — the engine requeues the same goal after each complete:

    loopd_create_goal({
      name: "hourly-report",
      objective: "Append date -u to tick.txt each run",
      agent: "smart-agent",
      checks: ["test -f tick.txt"],
      scheduleEveryMs: 3600000, // 1h, min 1000
      scheduleMaxRuns: 24,      // total incl initial, omit for unlimited
      workspaceWrite: false
    })
    
    • Poll: 5s createScheduleWorker scans complete scheduled goals; skip-if-running (lease/phase/workspaceWrite gate).
    • Resurrect: complete → active phase=idle, injects inbox Scheduled tick N/M — re-execute objective, then continueTurn.
    • State: scheduleRunCount/nextRunAt/lastScheduleAt (v6 state.json), schedule.tick events, schedule.resurrected server log.
    • Live proof: sched-live-verify 09cb837c 10s maxRuns 3tick.txt 3 lines 02:00:56 02:03:43 02:05:47 with runCount 3.

    Without schedule you’d send /goal 3× manually; with schedule one creation covers monitor deploy, periodic tests, keep going until done.

    Dashboard tips

    • Press : then type bare text → sent as send_goal_input to the selected goal.
    • Bare :force my summary --evidence "glob ok" bypasses verification when the child is stuck.
    • o jumps to the native OpenCode child session — full transcript, diffs, tool calls.

    Related / SEO

    OpenCode plugin for background agents, autonomous subagents, loop, goal, TUI dashboard, Codex-style continuation, Claude Code loop alternative, opencode-tui, worker sessions. Pairs well with opencode-telescope (search) and lazyjira/lazyconfluence (ATUI) from the same author.

    License

    AGPL-3.0-or-later — see LICENSE.

    同类生态推荐