Skip to content

feat(opencode): add /goal plugin for autonomous task completion - #28610

Closed
NathanKong76 wants to merge 2 commits into
anomalyco:devfrom
NathanKong76:feat/native-goal-command
Closed

NathanKong76 wants to merge 2 commits into
anomalyco:devfrom
NathanKong76:feat/native-goal-command

Conversation

@NathanKong76

@NathanKong76 NathanKong76 commented May 21, 2026 •

Copy link
Copy Markdown

Summary

A built-in plugin that enables multi-turn autonomous goal execution via /goal command. Zero core changes — all business logic in the plugin, command registration via existing skill system.

  • create_goal / update_goal / get_goal tools via Hooks.tool
  • /goal pause / resume / clear via command.execute.before
  • Idle-event continuation loop via client.promptAsync()
  • Storage: .opencode/goals.json per directory (atomic write)

Closes #27167

Testing

  • bun test test/plugin/goal.test.ts: 18/18 pass (storage, logic, formatting)
  • bun test test/plugin/goal.integration.test.ts: 16/16 pass (all hooks via mock PluginInput)
  • bun typecheck: 0 errors
  • No regression in existing tests

Copilot AI review requested due to automatic review settings May 21, 2026 08:15
@github-actions github-actions Bot added needs:compliance This means the issue will auto-close after 2 hours. and removed needs:compliance This means the issue will auto-close after 2 hours. labels May 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Introduces an experimental “goals” capability that lets a session persist an objective, continue autonomously across turns, and update goal status via new tools and a /goal command.

Changes:

  • Added goal session storage + service layer and wired it into the app/runtime layers.
  • Introduced create_goal / update_goal tools and a new /goal command template.
  • Extended the session prompt loop to optionally auto-continue when a goal is active.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
packages/opencode/src/tool/registry.ts Registers goal tools and provides the goal service layer.
packages/opencode/src/tool/goal.ts Implements create_goal and update_goal tools.
packages/opencode/src/session/session.sql.ts Adds GoalStatus and a new goal SQLite table.
packages/opencode/src/session/prompt.ts Adds experimental auto-continue behavior based on active goals.
packages/opencode/src/session/goal.ts New SessionGoal service for CRUD + iteration/token tracking.
packages/opencode/src/effect/app-runtime.ts Provides SessionGoal layer at the app level.
packages/opencode/src/config/config.ts Adds experimental.goals config flag.
packages/opencode/src/command/template/goal.txt Adds /goal command prompt template.
packages/opencode/src/command/index.ts Registers /goal command when experimental.goals is enabled.
packages/core/src/session-message-updater.ts Adds no-op handlers for new goal events.
packages/core/src/session-event.ts Defines new goal-related session events and includes them in the union.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/opencode/src/session/prompt.ts Outdated
Comment on lines +1477 to +1491
if (outcome === "break") {
const goalSvc = yield* SessionGoal.Service
const configSvc = yield* Config.Service
const cfg = yield* configSvc.get()
const goalsEnabled = cfg.experimental?.goals === true
if (goalsEnabled) {
const goal = yield* goalSvc.get(sessionID)
if (goal && goalSvc.isGoalContinueNeeded(goal)) {
yield* goalSvc.incrementIteration(sessionID)
const updatedGoal = yield* goalSvc.get(sessionID)
if (updatedGoal && goalSvc.isGoalContinueNeeded(updatedGoal)) {
const contPrompt = updatedGoal.status === "budget_limited"
? goalSvc.getBudgetLimitPrompt(updatedGoal)
: goalSvc.getContinuationPrompt(updatedGoal)
const msgId = MessageID.ascending()
Comment thread packages/opencode/src/session/goal.ts Outdated
})

const isGoalContinueNeeded: Interface["isGoalContinueNeeded"] = (state: GoalState) => {
return state.status === "active"
Comment thread packages/opencode/src/session/prompt.ts Outdated
@@ -1237,7 +1238,7 @@ export const layer = Layer.effect(
throw new Error("Impossible")
})

const runLoop: (sessionID: SessionID) => Effect.Effect<MessageV2.WithParts> = Effect.fn("SessionPrompt.run")(
const runLoop: (sessionID: SessionID) => Effect.Effect<MessageV2.WithParts, never, SessionGoal.Service | Config.Service> = Effect.fn("SessionPrompt.run")(
Comment thread packages/opencode/src/session/prompt.ts Outdated
@@ -1485,7 +1523,7 @@ export const layer = Layer.effect(
const loop: (input: LoopInput) => Effect.Effect<MessageV2.WithParts> = Effect.fn("SessionPrompt.loop")(function* (
input: LoopInput,
) {
return yield* state.ensureRunning(input.sessionID, lastAssistant(input.sessionID), runLoop(input.sessionID))
return yield* state.ensureRunning(input.sessionID, lastAssistant(input.sessionID), runLoop(input.sessionID) as Effect.Effect<MessageV2.WithParts>)
Comment thread packages/opencode/src/tool/goal.ts Outdated
Comment on lines +14 to +18
const UpdateGoalParams = Schema.Struct({
status: Schema.String.annotate({
description: 'New status: "complete" (goal achieved), "blocked" (cannot proceed)',
}),
})
Comment thread packages/opencode/src/session/goal.ts Outdated
@@ -0,0 +1,230 @@
import { Effect, Layer, Context, Schema } from "effect"
Comment thread packages/opencode/src/session/goal.ts Outdated
Comment on lines +6 to +9
import * as Log from "@opencode-ai/core/util/log"

const DEFAULT_MAX_ITERATIONS = 50
const log = Log.create({ service: "session.goal" })
Comment thread packages/opencode/src/session/goal.ts Outdated
timeUpdated: number
}

export class GoalNotFoundError extends Error {
Comment thread packages/opencode/src/session/goal.ts Outdated
}
}

export class GoalAlreadyExistsError extends Error {
Comment on lines +412 to +415
"session.next.goal.set": () => {},
"session.next.goal.updated": () => {},
"session.next.goal.cleared": () => {},
"session.next.goal.completed": () => {},
@NathanKong76
NathanKong76 force-pushed the feat/native-goal-command branch 3 times, most recently from 3d912fc to 33076c5 Compare May 21, 2026 13:45
@NathanKong76
NathanKong76 force-pushed the feat/native-goal-command branch from 4728f09 to b2c696b Compare May 27, 2026 02:31
@github-actions github-actions Bot added the needs:compliance This means the issue will auto-close after 2 hours. label May 27, 2026
@NathanKong76 NathanKong76 changed the title feat: add native /goal command for autonomous task completion feat: add /goal plugin for autonomous task completion May 27, 2026
@NathanKong76

Copy link
Copy Markdown
Author

Rewritten as a plugin per @aiden Cline feedback — zero core code changes, just 2 files.

Architecture

  • Tools: create_goal / update_goal / get_goal registered via Hooks.tool
  • Commands: /goal pause|resume|clear and --token-budget handled via Hooks["command.execute.before"]
  • Continuation: subscribes to session.status idle event via Hooks.event, injects <system-reminder> prompt via client.prompt() to trigger next LLM turn
  • Storage: .opencode/goals.json (single file, atomic tmp+rename write)

Design

  • No SQLite migration, no core schema changes
  • <system-reminder> tags keep continuation prompts invisible in chat
  • 30s client.prompt() timeout + inFlight set prevents duplicate continuations
  • Budget uses iteration×4000 token estimate

Open to feedback — happy to adjust anything. If this pattern works, future goal features (time limits, subtask goals, etc.) can be added to the plugin without touching core.

@NathanKong76
NathanKong76 force-pushed the feat/native-goal-command branch 3 times, most recently from 0030ef4 to 1268d72 Compare May 27, 2026 03:06
@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label May 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

@LeandroBenitez1998

Copy link
Copy Markdown
image you are genius !

@NathanKong76
NathanKong76 force-pushed the feat/native-goal-command branch from 1268d72 to 05c7a21 Compare May 27, 2026 14:30
@NathanKong76
NathanKong76 force-pushed the feat/native-goal-command branch 2 times, most recently from d11ead8 to 6b656b6 Compare May 28, 2026 04:09
@github-actions github-actions Bot added the needs:compliance This means the issue will auto-close after 2 hours. label May 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • PR description is missing required template sections. Please use the PR template.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

@NathanKong76 NathanKong76 changed the title feat: add /goal plugin for autonomous task completion feat(opencode): add /goal plugin for autonomous task completion May 28, 2026
@NathanKong76
NathanKong76 force-pushed the feat/native-goal-command branch 2 times, most recently from 26c7fc1 to da8a52c Compare May 28, 2026 09:39
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically closed because it was not updated to meet our contributing guidelines within the 2-hour window.

Feel free to open a new pull request that follows our guidelines.

@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label May 28, 2026
@github-actions github-actions Bot closed this May 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE]: Add native session goals with /goal

3 participants