🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

opencode-ralph-loop

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

opencode-ralph-loop - npm Package Compare versions

Comparing version
1.0.7
to
1.0.8
+15
-1
package.json
{
"name": "opencode-ralph-loop",
"version": "1.0.7",
"version": "1.0.8",
"description": "Minimal Ralph Loop plugin for opencode - auto-continues until task completion",
"main": "src/index.ts",
"type": "module",
"scripts": {
"typecheck": "tsc --noEmit",
"test": "vitest run",
"test:watch": "vitest"
},
"keywords": [

@@ -33,3 +38,12 @@ "opencode",

"node": ">=18.0.0"
},
"peerDependencies": {
"@opencode-ai/plugin": ">=1.0.0"
},
"devDependencies": {
"@opencode-ai/plugin": ">=1.0.0",
"@types/node": "^20.11.0",
"typescript": "^5.4.0",
"vitest": "^4.1.6"
}
}
# opencode-ralph-loop
[![CI](https://github.com/charfeng1/opencode-ralph-loop/actions/workflows/release.yml/badge.svg)](https://github.com/charfeng1/opencode-ralph-loop/actions/workflows/release.yml)
[![npm version](https://img.shields.io/npm/v/opencode-ralph-loop.svg)](https://www.npmjs.com/package/opencode-ralph-loop)
Minimal Ralph Loop plugin for [opencode](https://opencode.ai) - auto-continues until task completion.

@@ -121,2 +124,10 @@

## Contributing
PRs welcome. See [CONTRIBUTING.md](./CONTRIBUTING.md).
## Releases
Auto-published from CI with [npm provenance](https://docs.npmjs.com/generating-provenance-statements) via [OIDC trusted publishing](https://docs.npmjs.com/trusted-publishers) — each tarball is cryptographically linked to the exact commit, no long-lived tokens involved.
## Credits

@@ -123,0 +134,0 @@

+27
-37

@@ -0,2 +1,4 @@

import { tool } from "@opencode-ai/plugin";
import { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync, cpSync } from "fs";
import { homedir } from "os";
import { dirname, join } from "path";

@@ -6,3 +8,3 @@ import { fileURLToPath } from "url";

// Types
interface RalphState {
export interface RalphState {
active: boolean;

@@ -17,4 +19,4 @@ iteration: number;

const STATE_FILENAME = "ralph-loop.local.md";
const OPENCODE_CONFIG_DIR = join(process.env.HOME || "~", ".config/opencode");
const COMPLETION_TAG = /<promise>\s*DONE\s*<\/promise>/is;
const OPENCODE_CONFIG_DIR = join(homedir(), ".config/opencode");
export const COMPLETION_TAG = /<promise>\s*DONE\s*<\/promise>/is;

@@ -83,5 +85,5 @@ // Get plugin root directory

// Parse markdown frontmatter state
function parseState(content: string): RalphState {
const match = content.match(/^---\n([\s\S]*?)\n---/);
// Parse markdown frontmatter state. Regex accepts CRLF for cross-platform state files.
export function parseState(content: string): RalphState {
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
if (!match) return { active: false, iteration: 0, maxIterations: 100 };

@@ -92,3 +94,3 @@

for (const line of frontmatter.split("\n")) {
for (const line of frontmatter.split(/\r?\n/)) {
const [key, ...valueParts] = line.split(":");

@@ -110,3 +112,3 @@ const value = valueParts.join(":").trim();

// Serialize state to markdown frontmatter
function serializeState(state: RalphState): string {
export function serializeState(state: RalphState): string {
const lines = [

@@ -198,21 +200,15 @@ "---",

return {
// Register tools (fallback if skills/commands not available)
// Register tools using the @opencode-ai/plugin SDK format.
// The `args` field (Zod schema shape) is required — opencode calls
// Object.entries(tool.args) internally. Using the old JSON Schema
// `parameters` field left `args` undefined and caused a crash:
// TypeError: Object.entries requires that input parameter not be null or undefined
tool: {
"ralph-loop": {
"ralph-loop": tool({
description: "Start Ralph Loop - auto-continues until task completion. Use: /ralph-loop <task description>",
parameters: {
type: "object",
properties: {
task: {
type: "string",
description: "The task to work on until completion"
},
maxIterations: {
type: "number",
description: "Maximum iterations (default: 100)"
}
},
required: ["task"]
args: {
task: tool.schema.string().describe("The task to work on until completion"),
maxIterations: tool.schema.number().default(100).describe("Maximum iterations (default: 100)"),
},
async execute({ task, maxIterations = 100 }: { task: string; maxIterations?: number }) {
async execute({ task, maxIterations = 100 }) {
const state: RalphState = {

@@ -234,10 +230,7 @@ active: true,

}
},
}),
"cancel-ralph": {
"cancel-ralph": tool({
description: "Cancel active Ralph Loop",
parameters: {
type: "object",
properties: {}
},
args: {},
async execute() {

@@ -252,10 +245,7 @@ const state = readState(directory);

}
},
}),
"help": {
"help": tool({
description: "Show Ralph Loop plugin help",
parameters: {
type: "object",
properties: {}
},
args: {},
async execute() {

@@ -280,3 +270,3 @@ return `# Ralph Loop Help

}
}
})
},

@@ -283,0 +273,0 @@