diff --git a/README.md b/README.md index 7469fe0..4bfd828 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,20 @@ # Lobster -A Moltbot-native workflow shell: typed (JSON-first) pipelines, jobs, and approval gates. +A OpenClaw-native workflow shell: typed (JSON-first) pipelines, jobs, and approval gates. ## Example of lobster at work -Moltbot or any other AI agent can use `lobster` as a workflow engine and not construct a query every time - thus saving tokens, providing room for determinism, and resumability. +OpenClaw or any other AI agent can use `lobster` as a workflow engine and not construct a query every time - thus saving tokens, providing room for determinism, and resumability. ### Watching a PR that hasn't had changes ``` -node bin/lobster.js "workflows.run --name github.pr.monitor --args-json '{\"repo\":\"moltbot/moltbot\",\"pr\":1152}'" +node bin/lobster.js "workflows.run --name github.pr.monitor --args-json '{\"repo\":\"openclaw/openclaw\",\"pr\":1152}'" [ { "kind": "github.pr.monitor", - "repo": "moltbot/moltbot", + "repo": "openclaw/openclaw", "prNumber": 1152, - "key": "github.pr:moltbot/moltbot#1152", + "key": "github.pr:openclaw/openclaw#1152", "changed": false, "summary": { "changedFields": [], @@ -36,7 +36,7 @@ node bin/lobster.js "workflows.run --name github.pr.monitor --args-json '{\"repo "state": "OPEN", "title": "feat: Add optional lobster plugin tool (typed workflows, approvals/resume)", "updatedAt": "2026-01-18T20:16:56Z", - "url": "https://github.com/moltbot/moltbot/pull/1152" + "url": "https://github.com/openclaw/openclaw/pull/1152" } } ] @@ -44,13 +44,13 @@ node bin/lobster.js "workflows.run --name github.pr.monitor --args-json '{\"repo ### And a PR that has a state change (in this case an approved PR) ``` - node bin/lobster.js "workflows.run --name github.pr.monitor --args-json '{\"repo\":\"moltbot/moltbot\",\"pr\":1200}'" + node bin/lobster.js "workflows.run --name github.pr.monitor --args-json '{\"repo\":\"openclaw/openclaw\",\"pr\":1200}'" [ { "kind": "github.pr.monitor", - "repo": "moltbot/moltbot", + "repo": "openclaw/openclaw", "prNumber": 1200, - "key": "github.pr:moltbot/moltbot#1200", + "key": "github.pr:openclaw/openclaw#1200", "changed": true, "summary": { "changedFields": [ @@ -76,7 +76,7 @@ node bin/lobster.js "workflows.run --name github.pr.monitor --args-json '{\"repo }, "url": { "from": null, - "to": "https://github.com/moltbot/moltbot/pull/1200" + "to": "https://github.com/openclaw/openclaw/pull/1200" }, "state": { "from": null, @@ -124,7 +124,7 @@ node bin/lobster.js "workflows.run --name github.pr.monitor --args-json '{\"repo "state": "MERGED", "title": "feat(tui): add syntax highlighting for code blocks", "updatedAt": "2026-01-19T05:06:09Z", - "url": "https://github.com/moltbot/moltbot/pull/1200" + "url": "https://github.com/openclaw/openclaw/pull/1200" } } ] @@ -136,7 +136,7 @@ node bin/lobster.js "workflows.run --name github.pr.monitor --args-json '{\"repo - Typed pipelines (objects/arrays), not text pipes. - Local-first execution. - No new auth surface: Lobster must not own OAuth/tokens. -- Composable macros that Moltbot can invoke in one step to save tokens. +- Composable macros that OpenClaw can invoke in one step to save tokens. ## Quick start @@ -159,11 +159,11 @@ From this folder: - `exec --stdin raw|json|jsonl`: feed pipeline input into subprocess stdin - `where`, `pick`, `head`: data shaping - `json`, `table`: renderers -- `approve`: approval gate (TTY prompt or `--emit` for Moltbot integration) +- `approve`: approval gate (TTY prompt or `--emit` for OpenClaw integration) ## Next steps -- Moltbot integration: ship as an optional Moltbot plugin tool. +- OpenClaw integration: ship as an optional OpenClaw plugin tool. ## Workflow files diff --git a/VISION.md b/VISION.md index 388b8cb..b052796 100644 --- a/VISION.md +++ b/VISION.md @@ -2,26 +2,26 @@ ## One-liner -**Lobster is safe automation for Clawdbot — workflows that ask before acting.** +**Lobster is safe automation for OpenClaw — workflows that ask before acting.** --- ## What is Lobster? -Lobster is a workflow runtime for Clawdbot. It lets you define multi-step automations that: +Lobster is a workflow runtime for OpenClaw. It lets you define multi-step automations that: - Run deterministically (no LLM re-planning each step) - Halt at checkpoints and ask for approval before side effects - Resume exactly where they left off - Remember what they've already processed -Think of it as **IFTTT/Zapier for Clawdbot, but with human checkpoints**. +Think of it as **IFTTT/Zapier for OpenClaw, but with human checkpoints**. --- ## The Problem Lobster Solves -### Today's workflow in Clawdbot +### Today's workflow in OpenClaw ``` User: "Check my email, draft replies to anything urgent, and send them" @@ -46,7 +46,7 @@ What happens: ### With Lobster ``` -Clawdbot calls: lobster.run("email.triage") +OpenClaw calls: lobster.run("email.triage") What happens: 1. Lobster fetches emails (deterministic) @@ -63,7 +63,7 @@ Tomorrow: Lobster remembers cursor, only processes new emails --- -## Why Lobster Makes Clawdbot Better +## Why Lobster Makes OpenClaw Better | Without Lobster | With Lobster | |-----------------|--------------| @@ -85,7 +85,7 @@ Workflows can persist state: "last processed email ID", "last PR SHA seen", etc. --- -## How Lobster Fits with Clawdbot +## How Lobster Fits with OpenClaw ``` ┌─────────────────────────────────────────────────┐ @@ -95,7 +95,7 @@ Workflows can persist state: "last processed email ID", "last PR SHA seen", etc. │ ▼ ┌─────────────────────────────────────────────────┐ -│ Clawdbot │ +│ OpenClaw │ │ - Understands intent │ │ - Chooses appropriate tool/workflow │ │ - Presents results and approval prompts │ @@ -105,15 +105,15 @@ Workflows can persist state: "last processed email ID", "last PR SHA seen", etc. ┌─────────────────────────────────────────────────┐ │ Lobster │ │ - Executes deterministic pipeline │ -│ - Calls Clawdbot tools (gmail, trello, etc) │ +│ - Calls OpenClaw tools (gmail, trello, etc) │ │ - Halts at approval checkpoints │ │ - Returns structured result + resume token │ └─────────────────────────────────────────────────┘ ``` -**Key insight:** Lobster doesn't replace Clawdbot. It's the execution layer that makes Clawdbot's automations safe and efficient. +**Key insight:** Lobster doesn't replace OpenClaw. It's the execution layer that makes OpenClaw's automations safe and efficient. -- **Clawdbot** = the brain (understands what you want) +- **OpenClaw** = the brain (understands what you want) - **Lobster** = the hands (executes workflows safely) - **Tools/Skills** = the capabilities (gmail, trello, github, etc.) @@ -121,7 +121,7 @@ Workflows can persist state: "last processed email ID", "last PR SHA seen", etc. ## Who Should Use Lobster? -### Average Clawdbot users (invisible benefit) +### Average OpenClaw users (invisible benefit) They don't need to know Lobster exists. They just notice: - "Set up daily email triage" works better - Automations ask before sending/posting @@ -133,7 +133,7 @@ They can: - Write new workflows for their specific needs - Share workflows with the community -### The Clawdbot ecosystem +### The OpenClaw ecosystem - Workflow recipes become a new category of shareable assets - Skills stay simple (just expose APIs) - Lobster handles the orchestration layer @@ -151,21 +151,21 @@ They can: | Temporal | But 80/20 version for personal workflows | **Best analogy for most people:** -> "Lobster is Zapier for Clawdbot, except it asks you before doing anything irreversible." +> "Lobster is Zapier for OpenClaw, except it asks you before doing anything irreversible." --- -## Why Not Build This Into Clawdbot Core? +## Why Not Build This Into OpenClaw Core? It could be. But the plugin architecture is intentional: -1. **Core stays small** — Clawdbot is already complex +1. **Core stays small** — OpenClaw is already complex 2. **Faster iteration** — Lobster can evolve without core releases 3. **Opt-in** — Not everyone needs workflow automation 4. **Community** — Easier to contribute workflows than core changes 5. **Ecosystem proof** — If plugins work for Lobster, they work for other capabilities -Pete (Clawdbot creator) explicitly built the plugin boundary to enable this pattern. Lobster is the first proof that it works. +Pete (OpenClaw creator, formerly Clawdbot) explicitly built the plugin boundary to enable this pattern. Lobster is the first proof that it works. --- @@ -221,9 +221,9 @@ Other automation tools either: - Don't integrate with your AI assistant Lobster is: -- Native to Clawdbot (uses the same tools you already have) +- Native to OpenClaw (uses the same tools you already have) - Safe by default (approvals are a language primitive) -- Invisible when you want (Clawdbot uses it automatically) +- Invisible when you want (OpenClaw uses it automatically) - Customizable when you need (write your own workflows) --- @@ -232,8 +232,8 @@ Lobster is: - **Not a terminal replacement** — You don't switch your shell to Lobster - **Not a general programming language** — It's for workflows, not apps -- **Not trying to replace Clawdbot** — It makes Clawdbot better -- **Not managing your secrets** — Clawdbot handles auth, Lobster orchestrates +- **Not trying to replace OpenClaw** — It makes OpenClaw better +- **Not managing your secrets** — OpenClaw handles auth, Lobster orchestrates --- @@ -241,9 +241,9 @@ Lobster is: | Question | Answer | |----------|--------| -| What is it? | Workflow runtime for Clawdbot | +| What is it? | Workflow runtime for OpenClaw | | One-liner? | Safe automation — workflows that ask before acting | | Why use it? | Cheaper, safer, stateful automations | | Who uses it? | Everyone (invisibly) or power users (directly) | | Why not in core? | Plugin architecture — core stays small, capabilities are extensions | -| Best analogy? | Zapier for Clawdbot, but with approval checkpoints | +| Best analogy? | Zapier for OpenClaw, but with approval checkpoints | diff --git a/package.json b/package.json index 2ba5b15..ab27654 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@clawdbot/lobster", + "name": "@openclaw/lobster", "version": "2026.1.21-1", "description": "Workflow runtime for AI agents - deterministic pipelines with approval gates", "type": "module", @@ -43,16 +43,16 @@ "approval", "pipeline", "lobster", - "clawdbot" + "openclaw" ], "repository": { "type": "git", - "url": "git+https://github.com/clawdbot/lobster.git" + "url": "git+https://github.com/openclaw/lobster.git" }, "bugs": { - "url": "https://github.com/clawdbot/lobster/issues" + "url": "https://github.com/openclaw/lobster/issues" }, - "homepage": "https://github.com/clawdbot/lobster#readme", + "homepage": "https://github.com/openclaw/lobster#readme", "license": "MIT", "dependencies": { "ajv": "^8.17.1", diff --git a/src/cli.ts b/src/cli.ts index 3f78b7a..128c8c5 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -449,7 +449,7 @@ function writeToolEnvelope(payload) { } function helpText() { - return `lobster — Clawdbot-native typed shell\n\n` + + return `lobster — OpenClaw-native typed shell\n\n` + `Usage:\n` + ` lobster ''\n` + ` lobster run --mode tool ''\n` + diff --git a/src/commands/commands_list.ts b/src/commands/commands_list.ts index c76ab0b..218b435 100644 --- a/src/commands/commands_list.ts +++ b/src/commands/commands_list.ts @@ -14,7 +14,7 @@ export const commandsListCommand: LobsterCommand = { `Usage:\n` + ` commands.list\n\n` + `Notes:\n` + - ` - Intended for agents (e.g. Clawdbot) to discover available pipeline stages dynamically.\n` + + ` - Intended for agents (e.g. OpenClaw) to discover available pipeline stages dynamically.\n` + ` - Output includes name/description plus optional metadata (argsSchema/examples/sideEffects) when provided by commands.\n` ); }, diff --git a/src/commands/stdlib/clawd_invoke.ts b/src/commands/stdlib/clawd_invoke.ts index 95b0378..5fd574d 100644 --- a/src/commands/stdlib/clawd_invoke.ts +++ b/src/commands/stdlib/clawd_invoke.ts @@ -1,11 +1,11 @@ export const clawdInvokeCommand = { name: 'clawd.invoke', meta: { - description: 'Call a local Clawdbot tool endpoint', + description: 'Call a local OpenClaw tool endpoint', argsSchema: { type: 'object', properties: { - url: { type: 'string', description: 'Clawdbot control URL (or CLAWD_URL)' }, + url: { type: 'string', description: 'OpenClaw control URL (or CLAWD_URL)' }, token: { type: 'string', description: 'Bearer token (or CLAWD_TOKEN)' }, tool: { type: 'string', description: 'Tool name (e.g. message, cron, github, etc.)' }, action: { type: 'string', description: 'Tool action' }, @@ -21,7 +21,7 @@ export const clawdInvokeCommand = { sideEffects: ['calls_clawd_tool'], }, help() { - return `clawd.invoke — call a local Clawdbot tool endpoint\n\n` + + return `clawd.invoke — call a local OpenClaw tool endpoint\n\n` + `Usage:\n` + ` clawd.invoke --tool message --action send --args-json '{"provider":"telegram","to":"...","message":"..."}'\n` + ` clawd.invoke --tool message --action send --args-json '{...}' --dry-run\n` + diff --git a/src/commands/stdlib/email_triage.ts b/src/commands/stdlib/email_triage.ts index 570ce4c..9517938 100644 --- a/src/commands/stdlib/email_triage.ts +++ b/src/commands/stdlib/email_triage.ts @@ -233,7 +233,7 @@ export const emailTriageCommand = { } const model = String(args.model ?? '').trim(); - // Model is optional when running under Clawdbot (llm_task.invoke will use Clawdbot defaults). + // Model is optional when running under OpenClaw (llm_task.invoke will use OpenClaw defaults). if (!ctx?.registry) throw new Error('email.triage (LLM mode) requires ctx.registry'); const llmCmd = ctx.registry.get('llm_task.invoke'); diff --git a/src/commands/stdlib/llm_task_invoke.ts b/src/commands/stdlib/llm_task_invoke.ts index 86ece36..17ef059 100644 --- a/src/commands/stdlib/llm_task_invoke.ts +++ b/src/commands/stdlib/llm_task_invoke.ts @@ -26,7 +26,7 @@ const payloadSchema = { type: 'object', properties: { prompt: { type: 'string', minLength: 1 }, - // In direct mode, the remote likely requires model; in CLAWD mode, Clawdbot can default. + // In direct mode, the remote likely requires model; in CLAWD mode, OpenClaw can default. model: { type: 'string', minLength: 1 }, artifacts: { type: 'array', items: artifactSchema }, artifactHashes: { type: 'array', items: { type: 'string', minLength: 10 } }, @@ -151,7 +151,7 @@ type Transport = 'clawd'; export const llmTaskInvokeCommand = { name: 'llm_task.invoke', meta: { - description: 'Call Clawdbot llm-task tool with typed payloads and caching', + description: 'Call OpenClaw llm-task tool with typed payloads and caching', argsSchema: { type: 'object', properties: { @@ -160,7 +160,7 @@ export const llmTaskInvokeCommand = { description: 'Bearer token (or CLAWD_TOKEN). Optional if unauthenticated.', }, prompt: { type: 'string', description: 'Primary prompt / instructions' }, - model: { type: 'string', description: 'Model identifier (optional; Clawdbot default will be used if omitted in CLAWD mode)' }, + model: { type: 'string', description: 'Model identifier (optional; OpenClaw default will be used if omitted in CLAWD mode)' }, 'artifacts-json': { type: 'string', description: 'JSON array of artifacts to send' }, 'metadata-json': { type: 'string', description: 'JSON object of metadata to include' }, 'output-schema': { type: 'string', description: 'JSON schema LLM output must satisfy' }, @@ -179,14 +179,14 @@ export const llmTaskInvokeCommand = { }, help() { return ( - `llm_task.invoke — call Clawdbot llm-task tool with caching and schema validation\n\n` + + `llm_task.invoke — call OpenClaw llm-task tool with caching and schema validation\n\n` + `Usage:\n` + ` llm_task.invoke --prompt 'Write summary'\n` + ` llm_task.invoke --model claude-3-sonnet --prompt 'Write summary'\n` + ` cat artifacts.json | llm_task.invoke --prompt 'Score each item'\n` + ` ... | llm_task.invoke --prompt 'Plan next steps' --output-schema '{"type":"object"}'\n\n` + `Config:\n` + - ` - Requires CLAWD_URL (Clawdbot gateway).\n` + + ` - Requires CLAWD_URL (OpenClaw gateway).\n` + ` - Optional CLAWD_TOKEN for auth.\n\n` + `Features:\n` + ` - Typed payload validation before invoking tool.\n` + @@ -200,14 +200,14 @@ export const llmTaskInvokeCommand = { const clawdUrl = String(env.CLAWD_URL ?? '').trim(); const transport: Transport = 'clawd'; if (!clawdUrl) { - throw new Error('llm_task.invoke requires CLAWD_URL (run via Clawdbot gateway)'); + throw new Error('llm_task.invoke requires CLAWD_URL (run via OpenClaw gateway)'); } const prompt = extractPrompt(args); if (!prompt) throw new Error('llm_task.invoke requires --prompt or positional text'); const model = String(args.model ?? env.LLM_TASK_MODEL ?? '').trim(); - // Model is optional in Clawdbot mode (Clawdbot llm-task tool can use its default model). + // Model is optional in OpenClaw mode (OpenClaw llm-task tool can use its default model). const schemaVersion = args['schema-version'] ? String(args['schema-version']).trim() @@ -425,7 +425,7 @@ function computeCacheKey({ }) { const payload = { prompt, - // If model is omitted (Clawdbot default), keep caching stable but explicit. + // If model is omitted (OpenClaw default), keep caching stable but explicit. model: model || 'clawd-default', schemaVersion, artifactHashes, @@ -464,7 +464,7 @@ async function invokeRemoteViaClawd({ endpoint, token, payload }: { endpoint: UR throw new Error('Response was not JSON'); } - // Clawdbot tool router envelope: { ok, result, error } + // OpenClaw tool router envelope: { ok, result, error } if (parsed && typeof parsed === 'object' && !Array.isArray(parsed) && 'ok' in parsed) { if (parsed.ok !== true) { const msg = parsed?.error?.message ?? 'Unknown error'; diff --git a/src/commands/workflows/workflows_list.ts b/src/commands/workflows/workflows_list.ts index fb4983f..ca1d421 100644 --- a/src/commands/workflows/workflows_list.ts +++ b/src/commands/workflows/workflows_list.ts @@ -8,7 +8,7 @@ export const workflowsListCommand = { sideEffects: [], }, help() { - return `workflows.list — list available Lobster workflows\n\nUsage:\n workflows.list\n\nNotes:\n - Intended for Clawdbot to discover workflows dynamically.\n`; + return `workflows.list — list available Lobster workflows\n\nUsage:\n workflows.list\n\nNotes:\n - Intended for OpenClaw to discover workflows dynamically.\n`; }, async run({ input }) { // Drain input. diff --git a/src/commands/workflows/workflows_run.ts b/src/commands/workflows/workflows_run.ts index cd01b84..0b5dd6f 100644 --- a/src/commands/workflows/workflows_run.ts +++ b/src/commands/workflows/workflows_run.ts @@ -26,7 +26,7 @@ export const workflowsRunCommand = { sideEffects: [], }, help() { - return `workflows.run — run a named Lobster workflow\n\nUsage:\n workflows.run --name [--args-json '{...}']\n\nExample:\n workflows.run --name github.pr.monitor.notify --args-json '{"repo":"clawdbot/clawdbot","pr":1152}'\n`; + return `workflows.run — run a named Lobster workflow\n\nUsage:\n workflows.run --name [--args-json '{...}']\n\nExample:\n workflows.run --name github.pr.monitor.notify --args-json '{"repo":"openclaw/openclaw","pr":1152}'\n`; }, async run({ input, args, ctx }) { // Drain input. diff --git a/src/recipes/index.ts b/src/recipes/index.ts index 4156274..538bee5 100644 --- a/src/recipes/index.ts +++ b/src/recipes/index.ts @@ -1,7 +1,7 @@ /** * Recipe entrypoints. * - * Core Lobster intentionally keeps only Clawdbot-first recipes here. + * Core Lobster intentionally keeps only OpenClaw-first recipes here. */ export * from "./github/index.js"; diff --git a/src/workflows/registry.ts b/src/workflows/registry.ts index 67bf36a..cf9f186 100644 --- a/src/workflows/registry.ts +++ b/src/workflows/registry.ts @@ -5,7 +5,7 @@ export const workflowRegistry = { argsSchema: { type: 'object', properties: { - repo: { type: 'string', description: 'owner/repo (e.g. clawdbot/clawdbot)' }, + repo: { type: 'string', description: 'owner/repo (e.g. openclaw/openclaw)' }, pr: { type: 'number', description: 'Pull request number' }, key: { type: 'string', description: 'Optional state key override.' }, changesOnly: { type: 'boolean', description: 'If true, suppress output when unchanged.' }, @@ -15,7 +15,7 @@ export const workflowRegistry = { }, examples: [ { - args: { repo: 'clawdbot/clawdbot', pr: 1152 }, + args: { repo: 'openclaw/openclaw', pr: 1152 }, description: 'Monitor a PR and report when it changes.', }, ], @@ -27,7 +27,7 @@ export const workflowRegistry = { argsSchema: { type: 'object', properties: { - repo: { type: 'string', description: 'owner/repo (e.g. clawdbot/clawdbot)' }, + repo: { type: 'string', description: 'owner/repo (e.g. openclaw/openclaw)' }, pr: { type: 'number', description: 'Pull request number' }, key: { type: 'string', description: 'Optional state key override.' }, }, @@ -35,7 +35,7 @@ export const workflowRegistry = { }, examples: [ { - args: { repo: 'clawdbot/clawdbot', pr: 1152 }, + args: { repo: 'openclaw/openclaw', pr: 1152 }, description: 'Emit "PR updated" message only when changed.', }, ], diff --git a/test/email_triage.test.ts b/test/email_triage.test.ts index b6a30dc..324b1b0 100644 --- a/test/email_triage.test.ts +++ b/test/email_triage.test.ts @@ -139,7 +139,7 @@ test("email.triage --llm uses llm_task.invoke to draft replies (and can emit dra bodyLog.push(parsed); res.writeHead(200, { "content-type": "application/json" }); - // Clawdbot tool router envelope -> llm-task tool envelope + // OpenClaw tool router envelope -> llm-task tool envelope res.end( JSON.stringify({ ok: true, diff --git a/test/llm_task_invoke.test.ts b/test/llm_task_invoke.test.ts index 4a9728a..61cd82c 100644 --- a/test/llm_task_invoke.test.ts +++ b/test/llm_task_invoke.test.ts @@ -308,7 +308,7 @@ test('llm_task.invoke uses CLAWD_URL (/tools/invoke) without requiring --url/--m const parsed = JSON.parse(buf || '{}'); bodyLog.push(parsed); - // This is the Clawdbot tool router envelope. + // This is the OpenClaw tool router envelope. res.writeHead(200, { 'content-type': 'application/json' }); res.end( JSON.stringify({