Durable autonomous objective loop for OpenCode. Lets AI agents pursue complex, multi-turn tasks across sessions — with iteration guards, state persistence, and automatic continuation.
- Node.js 18 or newer
- npm available on your
PATH - OpenCode installed and configured for the account you use to run setup
Copy this prompt into OpenCode to have it install and verify the plugin for you:
Set up the OpenCode Objective Plugin.
Run this command:
npm install -g git+https://github.com/pdpraful/OpenCode-Objective.git
Then run this verification command:
objective-plugin
If either command fails, stop and show me the exact command and error output.
If setup succeeds, tell me to restart OpenCode and then run /objective help in a project.
npm install -g git+https://github.com/pdpraful/OpenCode-Objective.gitThe repository must be public for the HTTPS install command to work.
The npm install command pulls the package from GitHub and installs the objective-plugin CLI command from the package bin entry:
"bin": {
"objective-plugin": "./setup.js"
}Then run setup:
objective-pluginSetup performs three actions:
- Verifies the Node.js version.
- Creates OpenCode symlinks:
~/.config/opencode/plugin/objective.js~/.config/opencode/command/objective.md
- Merges objective-agent permissions into
~/.config/opencode/opencode.jsonc, settingbash: { "*": "ask" }andexternal_directory: "allow"for projects on external volumes.
Restart OpenCode after install so it reloads the plugin, command, and permission config.
Run one command:
objective-pluginIf setup succeeds, the plugin symlink, command symlink, CLI command, and OpenCode permission block are in place. Restart OpenCode, then open a project and run:
/objective help
Any bash command executed by the objective agent should then use OpenCode's normal approval prompt.
- You type
/objective <task>in OpenCode chat. - The plugin reads the command and saves your objective to
.opencode/objective.jsonbefore the first agent response. - When OpenCode becomes idle, the plugin sends a continuation prompt so the agent keeps working without another message from you.
- The agent finishes by sending
OBJECTIVE_ACHIEVED: <summary>or stops withOBJECTIVE_BLOCKED: <reason>. - The plugin updates the objective state and stops the loop.
OpenCode custom commands are still LLM-backed. The plugin hooks the command lifecycle to create/update durable state; it does not rely on the command template alone.
| Command | Description |
|---|---|
/objective <task> |
Start pursuing a new objective |
/objective <task> --max-iterations 50 |
Set with custom iteration cap |
/objective status |
Show current objective, iteration, and token usage |
/objective pause |
Pause the continuation loop |
/objective resume |
Resume a paused objective |
/objective refresh |
Reset iteration/token counters and resume a non-achieved objective |
/objective clear |
Remove the active objective entirely |
/objective help |
Show command reference |
The plugin exposes three tools the agent uses to manage objective state programmatically:
Set or reset the active objective.
| Arg | Type | Default | Description |
|---|---|---|---|
objective |
string | required | What to achieve — include a verifiable stopping condition |
max_iterations |
number | 100 | Max continuation loops before halting |
Transition the objective status.
| Arg | Type | Description |
|---|---|---|
status |
enum | pursuing · paused · achieved · blocked · iteration-limited |
summary |
string | Note recorded in history (strongly recommended for achieved/blocked) |
Read the current objective state. No arguments.
stateDiagram-v2
state "pursuing" as pursuing
state "paused" as paused
state "achieved" as achieved
state "blocked" as blocked
state "iteration-limited" as iteration_limited
[*] --> pursuing: start objective
pursuing --> paused: pause command
pursuing --> achieved: achievement signal
pursuing --> blocked: blocked signal
pursuing --> iteration_limited: iteration limit
paused --> pursuing: resume or refresh
blocked --> pursuing: refresh command
iteration_limited --> pursuing: refresh command
achieved --> [*]
achievedis terminal — start a new loop withcreate_objectiveor/objective <task>pausedcan continue via/objective resumeor/objective refreshblockedanditeration-limitedcan be restarted with/objective refresh
Each project stores objective state in .opencode/objective.json:
{
"objective": "Build unit tests with 100% coverage",
"status": "pursuing",
"session_id": "ses_...",
"iteration": 3,
"tokens_used": 12400,
"max_iterations": 100,
"created_at": "2026-05-30T10:00:00.000Z",
"updated_at": "2026-05-30T10:05:00.000Z",
"history": []
}The file is project-local (inside .opencode/). Do not commit this runtime state; this repository ignores .opencode/ by default.
- Iteration cap: loop halts after
max_iterationscontinuations. - Iteration limit sets status to
iteration-limitedand stops the loop.
The Objective Plugin can automatically submit continuation prompts while an objective is active. Each continuation can trigger additional model calls in OpenCode and may consume tokens from the configured AI provider.
Token counters shown by the plugin are best-effort operational estimates based on OpenCode message metadata or text-size fallback estimates. They are not a billing ledger and may differ from provider invoices, especially when caching, reasoning tokens, tool calls, retries, or provider-specific accounting are involved.
Use --max-iterations, /objective status, /objective pause, and /objective clear to control usage. By installing or using this plugin, you are responsible for monitoring token consumption, API usage, and any related provider costs.
The Objective Plugin includes safety controls that help prevent infinite loops and pause for your permission gates:
To prevent the plugin from continuing while OpenCode is waiting for your approval or clarification:
- Reactive Gate Tracking: The plugin tracks
permission.asked/permission.updatedandpermission.repliedevents to maintain a list of active gates. It also tracksquestion.asked/question.replied/question.rejectedevents. Auto-continuation is suspended if any permission request or question is pending. - Polling Safety Net: If supported by the client, the plugin also checks
/permissionand/questionREST API endpoints to confirm there are no outstanding requests before resuming the loop. - External Directory Access: The installer configures
permission.external_directory = "allow"specifically for theobjectiveagent so projects on external volumes do not get stuck on directory approval prompts during continuation, without globally relaxing host security.
If no continuation activity is logged for 30 minutes (e.g., due to a disconnected runner or terminal environment), the plugin automatically transitions the objective to paused and triggers a warning notification.
The plugin does not maintain its own command whitelist. Bash approval is delegated to OpenCode:
- Ask Every Time: Setup configures the
objectiveagent withbash: { "*": "ask" }, so shell commands request user approval through the normal host permission flow. - No Plugin-Side Auto-Allow Rules: The plugin does not auto-approve
git,npm, or filesystem commands on its own.
/objective Refactor auth module to use JWT and add tests --max-iterations 50
Plugin creates .opencode/objective.json, injects objective into system prompt, begins loop.
On each idle, the plugin sends:
## Active Objective Check
Current Objective: Refactor auth module to use JWT and add tests
Iteration: 2 | Tokens used: 8400
1. Is the objective achieved? If YES → OBJECTIVE_ACHIEVED: <summary>
2. Are you blocked? If YES → OBJECTIVE_BLOCKED: <reason>
3. Continue working. Execute the next action immediately.
All tests passing. JWT auth fully implemented.
OBJECTIVE_ACHIEVED: Refactored auth to JWT, added 12 tests, all green.
Plugin sets status: achieved, fires success toast, stops loop.
OBJECTIVE_BLOCKED: No access to production database credentials.
The plugin sets status: blocked, shows a warning, and stops the loop. After you resolve the blocker, run:
/objective refresh
objective-plugin uninstallUninstall is idempotent and safe to run more than once. It removes:
~/.config/opencode/plugin/objective.js~/.config/opencode/command/objective.md- the global
objective-pluginCLI command installed by npm - the
agent.objectivepermission block in~/.config/opencode/opencode.jsonc
Restart OpenCode after uninstall.
Uninstall does not remove per-project .opencode/objective.json state files. It also leaves top-level OpenCode permissions, such as permission.external_directory, in place so it does not accidentally revert settings that may be shared with other OpenCode workflows. Review ~/.config/opencode/opencode.jsonc manually if you want to tighten those settings.
MIT License
Copyright (c) 2026 Praful Dusane
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files, to deal in the software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the software, and to permit persons to whom the software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.