Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -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/"
}
28 changes: 28 additions & 0 deletions .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -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."
]
}
}
14 changes: 14 additions & 0 deletions .grok-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -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/"
}
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
20 changes: 19 additions & 1 deletion apps/web/public/.well-known/agent-skills/bitplan/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion apps/web/public/.well-known/agent-skills/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
]
}
7 changes: 7 additions & 0 deletions apps/web/src/app/docs/agents/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ export default function AgentsAndWalletsPage() {
The CLI never asks for a mnemonic or private key. The wallet still
controls every permission.
</p>
<p>
Prefer a compatible wallet you already use. The 1Sat CLI is planned as
a local fallback for agent sessions, but its current{" "}
<code>1sat serve wallet</code> command exposes wallet storage rather
than the application-facing endpoint BitPlan needs. Do not configure
it as a BitPlan wallet yet.
</p>
</section>

<section id="phone">
Expand Down
46 changes: 44 additions & 2 deletions apps/web/src/lib/agent-pages.test.ts
Original file line number Diff line number Diff line change
@@ -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");
Expand Down Expand Up @@ -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(
Expand All @@ -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<string>();
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);
});
});
4 changes: 4 additions & 0 deletions apps/web/src/lib/agent-pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 <wallet-identity-key>

For a local team, save contacts and share by team name:
Expand Down Expand Up @@ -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.
Expand Down
8 changes: 7 additions & 1 deletion biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -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" } },
Expand Down
2 changes: 1 addition & 1 deletion docs/templates/plan.html
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down
2 changes: 1 addition & 1 deletion plans/bitplan-agent-keys-and-next-features.html
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down
20 changes: 19 additions & 1 deletion skills/bitplan/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
4 changes: 4 additions & 0 deletions skills/bitplan/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -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."