From 7229b732d1e794bb39955ffff68308d3532edd24 Mon Sep 17 00:00:00 2001 From: Luke Rohenaz Date: Fri, 4 Sep 2026 12:50:36 -0400 Subject: [PATCH 1/2] feat: publish BitPlan as an external agent provider [OPL-4438] --- .claude-plugin/plugin.json | 14 ++++++ .codex-plugin/plugin.json | 28 +++++++++++ .grok-plugin/plugin.json | 14 ++++++ CHANGELOG.md | 13 ++++++ README.md | 14 ++++++ .../.well-known/agent-skills/bitplan/SKILL.md | 20 +++++++- .../.well-known/agent-skills/index.json | 2 +- apps/web/src/app/docs/agents/page.tsx | 7 +++ apps/web/src/lib/agent-pages.test.ts | 46 ++++++++++++++++++- apps/web/src/lib/agent-pages.ts | 4 ++ skills/bitplan/SKILL.md | 20 +++++++- skills/bitplan/agents/openai.yaml | 4 ++ 12 files changed, 181 insertions(+), 5 deletions(-) create mode 100644 .claude-plugin/plugin.json create mode 100644 .codex-plugin/plugin.json create mode 100644 .grok-plugin/plugin.json create mode 100644 skills/bitplan/agents/openai.yaml diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..cdac9b5 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,14 @@ +{ + "name": "bitplan", + "version": "0.2.1", + "description": "Create and share encrypted, versioned HTML plans with a BRC-100 wallet.", + "author": { + "name": "OPL", + "url": "https://github.com/opldotdev" + }, + "homepage": "https://bitplan.dev/docs/agents", + "repository": "https://github.com/opldotdev/bitplan.dev", + "license": "MIT", + "keywords": ["agents", "bitplan", "brc-100", "bsv", "encryption"], + "skills": "./skills/" +} diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json new file mode 100644 index 0000000..085b7b6 --- /dev/null +++ b/.codex-plugin/plugin.json @@ -0,0 +1,28 @@ +{ + "name": "bitplan", + "version": "0.2.1", + "description": "Create and share encrypted, versioned HTML plans with a BRC-100 wallet.", + "author": { + "name": "OPL", + "url": "https://github.com/opldotdev" + }, + "homepage": "https://bitplan.dev/docs/agents", + "repository": "https://github.com/opldotdev/bitplan.dev", + "license": "MIT", + "keywords": ["agents", "bitplan", "brc-100", "bsv", "encryption"], + "skills": "./skills/", + "interface": { + "displayName": "BitPlan", + "shortDescription": "Encrypted plans owned by your wallet.", + "longDescription": "Create, review, host, version, share, and publish encrypted HTML plans through a BRC-100 wallet.", + "developerName": "OPL", + "category": "Productivity", + "capabilities": ["Skills"], + "websiteURL": "https://bitplan.dev", + "defaultPrompt": [ + "Create an encrypted BitPlan for this project.", + "Update my existing BitPlan draft.", + "Share a BitPlan with another wallet." + ] + } +} diff --git a/.grok-plugin/plugin.json b/.grok-plugin/plugin.json new file mode 100644 index 0000000..cdac9b5 --- /dev/null +++ b/.grok-plugin/plugin.json @@ -0,0 +1,14 @@ +{ + "name": "bitplan", + "version": "0.2.1", + "description": "Create and share encrypted, versioned HTML plans with a BRC-100 wallet.", + "author": { + "name": "OPL", + "url": "https://github.com/opldotdev" + }, + "homepage": "https://bitplan.dev/docs/agents", + "repository": "https://github.com/opldotdev/bitplan.dev", + "license": "MIT", + "keywords": ["agents", "bitplan", "brc-100", "bsv", "encryption"], + "skills": "./skills/" +} diff --git a/CHANGELOG.md b/CHANGELOG.md index ddc68ef..a28018c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## Unreleased + +### Added + +- Package the canonical BitPlan skill as a Claude Code, Codex, and Grok plugin + so external catalogs can install it without copying the skill. + +### Changed + +- Document the wallet selection contract: prefer an existing BRC-100 wallet + and do not present the current 1Sat wallet-storage server as a compatible + BitPlan fallback. + ## 0.0.16 — 2026-09-04 ### Added diff --git a/README.md b/README.md index adbafde..bd4d991 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,16 @@ publish them on Bitcoin when they should be permanent. [Open BitPlan](https://bitplan.dev) · [Read the docs](https://bitplan.dev/docs) · [Install the CLI](https://www.npmjs.com/package/bitplan) +Install the agent skill directly from its owning repository: + +```sh +npx skills add opldotdev/bitplan.dev --skill bitplan -g +``` + +The repository also includes native plugin manifests for Claude Code, Codex, +and Grok. Marketplace installations therefore load this canonical skill rather +than a copied version maintained by another plugin. + BitPlan turns a self-contained HTML file into an encrypted plan. BRC-100 is the interface BitPlan uses to ask your wallet to encrypt and decrypt. Hosted drafts store only ciphertext on bitplan.dev and cost no BSV. When a plan is ready, the @@ -106,6 +116,10 @@ Compatibility tests open CLI-produced envelopes with the website implementation. Wallet and network boundaries use mocks, so the automated suite never publishes a transaction. +BitPlan prefers a BRC-100 wallet already installed by the user. A future 1Sat +CLI headless-wallet bridge is tracked separately; today's `1sat serve wallet` +endpoint is a wallet-storage service and is not a BitPlan wallet endpoint. + Contributions are welcome. Start with [CONTRIBUTING.md](CONTRIBUTING.md). ## License diff --git a/apps/web/public/.well-known/agent-skills/bitplan/SKILL.md b/apps/web/public/.well-known/agent-skills/bitplan/SKILL.md index bad4f61..c4f15dc 100644 --- a/apps/web/public/.well-known/agent-skills/bitplan/SKILL.md +++ b/apps/web/public/.well-known/agent-skills/bitplan/SKILL.md @@ -5,11 +5,13 @@ description: > with BitPlan and a BRC-100 wallet. Use when asked to make a BitPlan, publish or update a plan, share one with a person or team, create a private reader link, move a hosted draft on chain, or explain bitplan.dev. +metadata: + version: "0.2.1" --- # BitPlan -**Skill version: 0.2.0** +**Skill version: 0.2.1** BitPlan turns one self-contained HTML file into an encrypted living plan. A BRC-100 wallet owns the keys. A draft can stay hosted as ciphertext while it @@ -19,6 +21,22 @@ wallet interface, not the inscription format. Use `bunx bitplan` or `npx bitplan`. Never install the CLI globally. Run it from the repository the plan belongs to so BitPlan records Git metadata. +## Choose the wallet honestly + +Prefer a compatible BRC-100 wallet the user already has. Check it with +`bunx bitplan auth`; do not silently create, import, or replace a wallet. + +The 1Sat CLI is intended to become the local fallback wallet for agents, but +that application-facing bridge is not released yet. `1sat serve wallet` +currently serves authenticated wallet storage; it is not a drop-in endpoint +for BitPlan's BRC-100 `HTTPWalletJSON` client. Do not point BitPlan at it or +claim the fallback works until the 1Sat headless-wallet acceptance test passes. + +If no compatible wallet is available, explain that BitPlan cannot create or +update an encrypted plan today. Let the calling workflow offer a local file or +an explicitly approved non-BitPlan host. Never weaken BitPlan into a plaintext +or agent-held-key mode to make the command succeed. + ## Check the live product first Before answering what BitPlan supports, read https://bitplan.dev/llms.txt and diff --git a/apps/web/public/.well-known/agent-skills/index.json b/apps/web/public/.well-known/agent-skills/index.json index 71522c9..bf36ce4 100644 --- a/apps/web/public/.well-known/agent-skills/index.json +++ b/apps/web/public/.well-known/agent-skills/index.json @@ -6,7 +6,7 @@ "type": "skill-md", "description": "Create, review, host, publish, update, fetch, and share encrypted HTML plans with a BRC-100 wallet.", "url": "https://bitplan.dev/.well-known/agent-skills/bitplan/SKILL.md", - "digest": "sha256:b8a705b429b0b684b26b4b2222b9ad9a9f0583394188469fbc0da6297fac6ff1" + "digest": "sha256:78c3af794fdba1a5a9a328382d0592a7545ca754b7ed6d1e725cfbac38cc62ce" } ] } diff --git a/apps/web/src/app/docs/agents/page.tsx b/apps/web/src/app/docs/agents/page.tsx index 1672eff..9bdeb70 100644 --- a/apps/web/src/app/docs/agents/page.tsx +++ b/apps/web/src/app/docs/agents/page.tsx @@ -36,6 +36,13 @@ export default function AgentsAndWalletsPage() { The CLI never asks for a mnemonic or private key. The wallet still controls every permission.

+

+ Prefer a compatible wallet you already use. The 1Sat CLI is planned as + a local fallback for agent sessions, but its current{" "} + 1sat serve wallet command exposes wallet storage rather + than the application-facing endpoint BitPlan needs. Do not configure + it as a BitPlan wallet yet. +

diff --git a/apps/web/src/lib/agent-pages.test.ts b/apps/web/src/lib/agent-pages.test.ts index 27fde6a..ce0a951 100644 --- a/apps/web/src/lib/agent-pages.test.ts +++ b/apps/web/src/lib/agent-pages.test.ts @@ -1,11 +1,17 @@ import { describe, expect, test } from "bun:test"; import { createHash } from "node:crypto"; import { readFile } from "node:fs/promises"; +import { dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; import { GET as getRobots } from "@/app/robots.txt/route"; import { LLMS_TXT, markdownForPath, markdownNotFound } from "./agent-pages"; +const SEMVER = /^\d+\.\d+\.\d+$/; +const SKILL_METADATA_VERSION = /\nmetadata:\n\s+version: ["']([^"']+)["']/; +const SKILL_VISIBLE_VERSION = /\*\*Skill version: ([^*]+)\*\*/; + describe("agent pages", () => { test("home and docs have markdown", () => { expect(markdownForPath("/")).toContain("npx bitplan"); @@ -52,22 +58,27 @@ describe("agent pages", () => { test("agent discovery files describe real BitPlan capabilities", async () => { const publicRoot = new URL("../../public/.well-known/", import.meta.url); - const skill = await readFile( + const publishedSkill = await readFile( new URL("agent-skills/bitplan/SKILL.md", publicRoot), "utf8" ); + const canonicalSkill = await readFile( + new URL("../../../../skills/bitplan/SKILL.md", import.meta.url), + "utf8" + ); const index = JSON.parse( await readFile(new URL("agent-skills/index.json", publicRoot), "utf8") ) as { $schema: string; skills: Array<{ digest: string }> }; const catalog = JSON.parse( await readFile(new URL("ai-catalog.json", publicRoot), "utf8") ) as { entries: Array<{ data?: unknown; url?: unknown }> }; - const digest = createHash("sha256").update(skill).digest("hex"); + const digest = createHash("sha256").update(canonicalSkill).digest("hex"); expect(index.$schema).toBe( "https://schemas.agentskills.io/discovery/0.2.0/schema.json" ); expect(index.skills[0].digest).toBe(`sha256:${digest}`); + expect(publishedSkill).toBe(canonicalSkill); expect(catalog.entries).toHaveLength(2); expect( catalog.entries.every( @@ -83,4 +94,35 @@ describe("agent pages", () => { "Agentmap: https://bitplan.dev/.well-known/ai-catalog.json" ); }); + + test("cross-harness plugin manifests expose the canonical skill", async () => { + const repoRoot = resolve( + dirname(fileURLToPath(import.meta.url)), + "../../../.." + ); + const versions = new Set(); + const canonicalSkill = await readFile( + resolve(repoRoot, "skills/bitplan/SKILL.md"), + "utf8" + ); + const metadataVersion = canonicalSkill.match(SKILL_METADATA_VERSION)?.[1]; + const visibleVersion = canonicalSkill.match(SKILL_VISIBLE_VERSION)?.[1]; + const manifests = await Promise.all( + [".claude-plugin", ".codex-plugin", ".grok-plugin"].map( + async (directory) => + JSON.parse( + await readFile(resolve(repoRoot, directory, "plugin.json"), "utf8") + ) as { name: string; skills: string; version: string } + ) + ); + for (const manifest of manifests) { + expect(manifest.name).toBe("bitplan"); + expect(manifest.skills).toBe("./skills/"); + expect(manifest.version).toMatch(SEMVER); + versions.add(manifest.version); + } + expect(versions.size).toBe(1); + expect(metadataVersion).toBe(manifests[0].version); + expect(visibleVersion).toBe(manifests[0].version); + }); }); diff --git a/apps/web/src/lib/agent-pages.ts b/apps/web/src/lib/agent-pages.ts index c67707c..829ffc1 100644 --- a/apps/web/src/lib/agent-pages.ts +++ b/apps/web/src/lib/agent-pages.ts @@ -56,6 +56,8 @@ A coding agent uses the BitPlan CLI. The CLI calls a BRC-100 wallet on the same Never give an agent a wallet mnemonic or private key. To read new plans with another wallet, save its public identity as a default reader: +Prefer a compatible BRC-100 wallet the user already has. The planned 1Sat CLI fallback is not available yet: \`1sat serve wallet\` currently serves wallet storage, not the application-facing BRC-100 endpoint BitPlan needs. Do not point BitPlan at it. + npx bitplan config --share-with For a local team, save contacts and share by team name: @@ -150,6 +152,8 @@ Use BitPlan when a user wants to draft, publish, version, share, or read an encr Do not use BitPlan as a general file host, a server-side notes app, or a substitute for a BRC-100 wallet. +Prefer an existing compatible wallet. Do not claim that \`1sat serve wallet\` is a working BitPlan fallback; the application-facing 1Sat CLI wallet bridge is still planned. + ## Terms - BRC-100 is the interface BitPlan uses to talk to a wallet. It is not an inscription format. diff --git a/skills/bitplan/SKILL.md b/skills/bitplan/SKILL.md index bad4f61..c4f15dc 100644 --- a/skills/bitplan/SKILL.md +++ b/skills/bitplan/SKILL.md @@ -5,11 +5,13 @@ description: > with BitPlan and a BRC-100 wallet. Use when asked to make a BitPlan, publish or update a plan, share one with a person or team, create a private reader link, move a hosted draft on chain, or explain bitplan.dev. +metadata: + version: "0.2.1" --- # BitPlan -**Skill version: 0.2.0** +**Skill version: 0.2.1** BitPlan turns one self-contained HTML file into an encrypted living plan. A BRC-100 wallet owns the keys. A draft can stay hosted as ciphertext while it @@ -19,6 +21,22 @@ wallet interface, not the inscription format. Use `bunx bitplan` or `npx bitplan`. Never install the CLI globally. Run it from the repository the plan belongs to so BitPlan records Git metadata. +## Choose the wallet honestly + +Prefer a compatible BRC-100 wallet the user already has. Check it with +`bunx bitplan auth`; do not silently create, import, or replace a wallet. + +The 1Sat CLI is intended to become the local fallback wallet for agents, but +that application-facing bridge is not released yet. `1sat serve wallet` +currently serves authenticated wallet storage; it is not a drop-in endpoint +for BitPlan's BRC-100 `HTTPWalletJSON` client. Do not point BitPlan at it or +claim the fallback works until the 1Sat headless-wallet acceptance test passes. + +If no compatible wallet is available, explain that BitPlan cannot create or +update an encrypted plan today. Let the calling workflow offer a local file or +an explicitly approved non-BitPlan host. Never weaken BitPlan into a plaintext +or agent-held-key mode to make the command succeed. + ## Check the live product first Before answering what BitPlan supports, read https://bitplan.dev/llms.txt and diff --git a/skills/bitplan/agents/openai.yaml b/skills/bitplan/agents/openai.yaml new file mode 100644 index 0000000..5d57a88 --- /dev/null +++ b/skills/bitplan/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "BitPlan" + short_description: "Create encrypted plans with your wallet" + default_prompt: "Use $bitplan to create or update an encrypted, versioned plan with my BRC-100 wallet." From fbf53fd385d48531775f1b638e1846f99f511a9c Mon Sep 17 00:00:00 2001 From: Luke Rohenaz Date: Fri, 4 Sep 2026 12:55:20 -0400 Subject: [PATCH 2/2] chore: restore root lint gate --- biome.json | 8 +++++++- docs/templates/plan.html | 2 +- plans/bitplan-agent-keys-and-next-features.html | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/biome.json b/biome.json index e57d16c..bc6d669 100644 --- a/biome.json +++ b/biome.json @@ -2,7 +2,13 @@ "$schema": "https://biomejs.dev/schemas/2.5.11/schema.json", "vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true }, "files": { - "includes": ["**", "!**/node_modules", "!**/dist", "!apps/web"] + "includes": [ + "**", + "!**/node_modules", + "!**/dist", + "!apps/web", + "!.claude/linear-sync.json" + ] }, "formatter": { "enabled": true, "indentStyle": "tab", "indentWidth": 2 }, "linter": { "enabled": true, "rules": { "preset": "recommended" } }, diff --git a/docs/templates/plan.html b/docs/templates/plan.html index 31b85b0..62d113a 100644 --- a/docs/templates/plan.html +++ b/docs/templates/plan.html @@ -48,7 +48,7 @@ /* Response block. Fills in from the radios with CSS alone, so it works with scripts off. */ .response { margin-top: 1.5rem; } - .btn { display: inline-block; padding: 10px 16px; border-radius: 8px; background: var(--accent); color: #fff; font-weight: 700; cursor: pointer; border: 0; font: inherit; } + .btn { display: inline-block; padding: 10px 16px; border-radius: 8px; background: var(--accent); color: #fff; cursor: pointer; border: 0; font: inherit; font-weight: 700; } .response pre { margin-top: 12px; user-select: all; -webkit-user-select: all; white-space: pre-wrap; } .hint { font-size: .88rem; color: var(--muted); margin: 6px 0 0; } .ans { display: none; } diff --git a/plans/bitplan-agent-keys-and-next-features.html b/plans/bitplan-agent-keys-and-next-features.html index 51caef4..34e595d 100644 --- a/plans/bitplan-agent-keys-and-next-features.html +++ b/plans/bitplan-agent-keys-and-next-features.html @@ -50,7 +50,7 @@ .opt .rec { color: var(--accent); font-weight: 700; } .notes { width: 100%; min-height: 80px; margin-top: 8px; padding: 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg); color: var(--fg); font: inherit; font-size: .92rem; resize: vertical; box-sizing: border-box; } .response { margin-top: 1.5rem; } - .response .btn { display: inline-block; padding: 10px 16px; border-radius: 8px; background: var(--accent); color: #fff; font-weight: 700; cursor: pointer; border: 0; font: inherit; } + .response .btn { display: inline-block; padding: 10px 16px; border-radius: 8px; background: var(--accent); color: #fff; cursor: pointer; border: 0; font: inherit; font-weight: 700; } .response pre { margin-top: 12px; user-select: all; -webkit-user-select: all; white-space: pre-wrap; } .response .hint { font-size: .88rem; color: var(--muted); margin: 6px 0 0; } .ans { display: none; }