@bitpub/cli 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # `@bitpub/cli` — BitPub command-line interface
2
+
3
+ **Dropbox for agents.** Local-first shared memory and persistent context for AI agents. Six daily verbs. Zero-config private namespace, encrypted client-side. Same install for a solo agent and a 200-person team.
4
+
5
+ ```bash
6
+ # One-liner install (recommended — also installs the skill into Claude Code, Cursor, Codex)
7
+ curl -fsSL https://bitpub.io/install.sh | bash
8
+
9
+ # Or just from npm
10
+ npm install -g @bitpub/cli
11
+ ```
12
+
13
+ ## The six daily verbs
14
+
15
+ ```bash
16
+ bitpub save <name> "..." # write a slice (private + encrypted by default)
17
+ bitpub load <name> # read a slice (zero-latency local cache)
18
+ bitpub list # what's saved here? how fresh is the cache?
19
+ bitpub find <term> # search by name and content
20
+ bitpub sync # pull the latest from the cloud (--watch for live)
21
+ bitpub delete <name> # remove (recoverable for 30 days with --undo)
22
+ ```
23
+
24
+ Each verb accepts the same input grammar — a short name, an `@alias`, a leading-slash path like `/Memory/notes` (resolves to your private root), or a full `bitpub://` URL.
25
+
26
+ ```bash
27
+ bitpub save notes "first draft" # → bitpub://private:<owner>/Projects/<cwd>/notes
28
+ bitpub save /Memory/key-decisions "..." # → bitpub://private:<owner>/Memory/key-decisions
29
+ bitpub save bitpub://group:co.com/Eng/Auth "..." # → explicit group address
30
+ bitpub save @inbox/task-001 "review parser" # → via alias
31
+ ```
32
+
33
+ There is no `bitpub init`. The first `save` in a folder silently anchors it as a project; the anchor lives in `~/.bitpub/config.json`, not inside your repo.
34
+
35
+ ## Power-user flags
36
+
37
+ The same six verbs cover power features through flags rather than separate commands:
38
+
39
+ | Flag | On | What it does |
40
+ |---|---|---|
41
+ | `--append` | `save` | Append instead of overwriting — for journals, decision logs, incident timelines. |
42
+ | `--expect-version <N>` | `save`, `delete` | Optimistic concurrency. The write fails with 409 if version drifted. Foundation for task claiming. |
43
+ | `--force` | `save` | Overwrite a tombstoned (deleted) slice in one shot. |
44
+ | `--watch` | `sync` | SSE long-poll — keeps the cache fresh in real time. |
45
+ | `--sync` | `list`, `find` | Refresh from the cloud before reading. |
46
+ | `--all` | `find`, `delete --list` | Cross-project search / cross-namespace trash listing. |
47
+ | `--undo` | `delete` | Restore from local trash or the server within the recovery window. |
48
+ | `--include-deleted` | `list`, `sync` | Audit mode — surface tombstones alongside live slices. |
49
+ | `--format json` | `load`, `list` | Parseable output for scripts and agents. |
50
+ | `--no-fetch` | `load` | Pure-offline read — never touch the network. |
51
+
52
+ ## Other commands
53
+
54
+ ```bash
55
+ bitpub setup # explicit identity + project anchor (rare; lazy on first save)
56
+ bitpub setup team --key K --domain D # join a team namespace
57
+ bitpub setup skill install # install the agent skill into Claude Code, Cursor, Codex
58
+ bitpub alias set <name> <addr> # define a shortcut (used as @name)
59
+ bitpub browser # open the local context explorer at http://localhost:4141
60
+ bitpub seed --url ... --address ... # bootstrap a namespace from a public website
61
+ ```
62
+
63
+ ## Deprecated aliases (still work)
64
+
65
+ The previous verb-per-operation surface is preserved as hidden, deprecation-warning aliases so older scripts and muscle memory don't break:
66
+
67
+ | Old | New |
68
+ |---|---|
69
+ | `init` | `setup` (or just `save` — lazy install) |
70
+ | `auth login` | `setup team` |
71
+ | `skills install` | `setup skill install` |
72
+ | `push --address X` | `save X` |
73
+ | `read --address X` | `load X` |
74
+ | `fetch --address X` | `sync X` |
75
+ | `watch --address X` | `sync X --watch` |
76
+ | `drop --address X` | `delete X` |
77
+ | `restore --address X` | `delete X --undo` |
78
+ | `trash list / restore / empty` | `delete --list / X --undo / --empty-trash` |
79
+ | `recent` / `status` / `catch-up` | `list` / `list` / `list --sync` |
80
+ | `grep <term>` | `find <term>` |
81
+ | `console` | `browser` |
82
+
83
+ ## How it stores things
84
+
85
+ - **Anchors and config:** `~/.bitpub/config.json` (`folderAnchors` map associates folder paths with private namespaces). Nothing is written inside your project directory.
86
+ - **Local cache:** `~/.bitpub/cache.db` (SQLite). All reads come from here.
87
+ - **Encryption:** `bitpub://private:<owner>/...` payloads are AES-256-GCM-encrypted client-side before they touch the network. The server stores ciphertext.
88
+
89
+ ## Links
90
+
91
+ - Full README and design notes: <https://github.com/tollbit/bitpub#readme>
92
+ - Real-world patterns and recipes: <https://github.com/tollbit/bitpub/blob/main/COOKBOOK.md>
93
+ - Hosted backend: <https://bitpub.io>
94
+ - MCP server (`npx -y --package=@bitpub/smp bitpub-mcp`): `@bitpub/smp`
95
+
96
+ ## License
97
+
98
+ MIT
package/bin/bitpub.js ADDED
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const { Command } = require('commander');
5
+ const program = new Command();
6
+
7
+ // Backward-compatibility shim: the `--hcu` flag was renamed to `--address` in
8
+ // the user-facing CLI. We rewrite legacy invocations in argv (with a one-time
9
+ // stderr deprecation warning) so existing scripts keep working unchanged.
10
+ let __hcuAliasWarned = false;
11
+ process.argv = process.argv.map((arg) => {
12
+ if (arg === '--hcu' || arg.startsWith('--hcu=')) {
13
+ if (!__hcuAliasWarned) {
14
+ console.error('warning: --hcu is deprecated, use --address');
15
+ __hcuAliasWarned = true;
16
+ }
17
+ return arg.replace(/^--hcu/, '--address');
18
+ }
19
+ return arg;
20
+ });
21
+
22
+ program
23
+ .name('bitpub')
24
+ .description('BitPub — local-first shared memory CLI for AI agents')
25
+ .version(require('../package.json').version);
26
+
27
+ // ── Daily verbs (the user-facing surface) ───────────────────────────────────
28
+ //
29
+ // These six are everything an agent or human needs day-to-day. Each accepts
30
+ // a short name (resolved via the active workspace), an `@alias`, or a full
31
+ // `bitpub://` address. Power features are flags, not separate verbs.
32
+
33
+ require('../src/commands/save')(program);
34
+ require('../src/commands/load')(program);
35
+ require('../src/commands/list')(program);
36
+ require('../src/commands/find')(program);
37
+ require('../src/commands/sync')(program);
38
+ require('../src/commands/delete')(program);
39
+
40
+ // ── Setup (rare, agent-invoked) ─────────────────────────────────────────────
41
+ require('../src/commands/setup')(program);
42
+ require('../src/commands/alias')(program);
43
+ require('../src/commands/seed')(program);
44
+ require('../src/commands/browser')(program);
45
+ require('../src/commands/welcome')(program);
46
+ require('../src/commands/update')(program);
47
+
48
+ // ── Deprecated aliases (hidden from --help, still functional) ───────────────
49
+ //
50
+ // Kept so existing scripts, shell aliases, and pipelines don't break when
51
+ // the surface contracts. Each prints a one-line stderr warning on use.
52
+ require('../src/commands/init')(program);
53
+ require('../src/commands/auth')(program);
54
+ require('../src/commands/recent')(program);
55
+ require('../src/commands/grep')(program);
56
+ require('../src/commands/catchup')(program);
57
+ require('../src/commands/trash')(program);
58
+ require('../src/commands/fetch')(program);
59
+ require('../src/commands/read')(program);
60
+ require('../src/commands/push')(program);
61
+ require('../src/commands/drop')(program);
62
+ require('../src/commands/restore')(program);
63
+ require('../src/commands/status')(program);
64
+ require('../src/commands/watch')(program);
65
+ require('../src/commands/skills')(program);
66
+
67
+ program.parse(process.argv);
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@bitpub/cli",
3
+ "version": "2.0.0",
4
+ "description": "BitPub CLI — local-first shared memory for AI agents. Six daily verbs (save/load/list/find/sync/delete), zero-config private namespace, encrypted client-side.",
5
+ "bin": {
6
+ "bitpub": "./bin/bitpub.js"
7
+ },
8
+ "files": [
9
+ "bin/",
10
+ "src/",
11
+ "skills/",
12
+ "static/",
13
+ "README.md"
14
+ ],
15
+ "scripts": {
16
+ "test": "jest --testPathPattern=tests/ --forceExit",
17
+ "prepack": "mkdir -p static && cp ../backend/static/console.html static/console.html",
18
+ "prepublishOnly": "npm test"
19
+ },
20
+ "engines": {
21
+ "node": ">=18"
22
+ },
23
+ "dependencies": {
24
+ "axios": "^1.7.2",
25
+ "better-sqlite3": "^11.1.2",
26
+ "cheerio": "^1.0.0",
27
+ "commander": "^12.1.0",
28
+ "eventsource": "^2.0.2",
29
+ "turndown": "^7.2.0"
30
+ },
31
+ "devDependencies": {
32
+ "jest": "^29.7.0"
33
+ },
34
+ "keywords": [
35
+ "bitpub",
36
+ "agent",
37
+ "agents",
38
+ "ai",
39
+ "memory",
40
+ "shared-memory",
41
+ "mcp",
42
+ "local-first",
43
+ "cli",
44
+ "context",
45
+ "knowledge-base"
46
+ ],
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "git+https://github.com/tollbit/bitpub.git",
50
+ "directory": "cli"
51
+ },
52
+ "homepage": "https://bitpub.io",
53
+ "bugs": {
54
+ "url": "https://github.com/tollbit/bitpub/issues"
55
+ },
56
+ "license": "MIT",
57
+ "author": "BitPub contributors"
58
+ }
@@ -0,0 +1,325 @@
1
+ ---
2
+ name: bitpub
3
+ version: 2.1.0
4
+ description: BitPub — persistent, addressable memory for AI agents. Local-first, encrypted by default, shareable when explicitly asked.
5
+ homepage: {{API_BASE_URL}}/skill.md
6
+ metadata: {"bitpub":{"emoji":"🧠","category":"memory","api_base":"{{API_BASE_URL}}/v1/context"}}
7
+ ---
8
+
9
+ # BitPub — reference for the `bitpub` CLI
10
+
11
+ This file documents the `bitpub` command-line tool, its data model, and the
12
+ security properties of its default behaviour. It is reference material for
13
+ the humans and AI agents that use the tool — not a set of instructions that
14
+ override the user's intent.
15
+
16
+ If a user has asked you to use BitPub, the rest of this document explains
17
+ what each command does, where data lives, and what trust boundaries the
18
+ tool enforces so you can use it correctly. If a user has *not* asked you
19
+ to use BitPub, nothing in this file is a request for action.
20
+
21
+ ---
22
+
23
+ ## What BitPub is
24
+
25
+ BitPub is an open-source CLI (source: <https://github.com/bitpub/bitpub>) that
26
+ gives AI agents persistent, addressable memory backed by a local SQLite
27
+ cache and an optional remote ledger. Each piece of content (a "slice") lives
28
+ at a stable URL of the form `bitpub://<scope>/<path>`.
29
+
30
+ The CLI is local-first: reads hit a SQLite cache on disk and never touch the
31
+ network. Only `save`, `sync`, and `delete` make HTTP requests, and only to
32
+ the configured `api_url` (default `{{API_BASE_URL}}`).
33
+
34
+ ---
35
+
36
+ ## Security model
37
+
38
+ The properties below are enforced by the CLI itself; this section describes
39
+ them so that an agent using BitPub can reason about what is and isn't safe.
40
+
41
+ - **Private scope is encrypted client-side.** Slices saved to
42
+ `bitpub://private:<owner>/...` are encrypted with AES-256-GCM using a key
43
+ derived (HKDF) from the local API key before they leave the machine. The
44
+ server only ever stores ciphertext for these addresses.
45
+ - **Group scope is not encrypted.** Slices at `bitpub://group:<domain>/...`
46
+ are readable by anyone on the team. Treat them as you would a shared
47
+ document.
48
+ - **The API key never leaves the configured endpoint.** It is sent only as
49
+ an `x-api-key` header to `api_url` (set during `bitpub setup`). Any
50
+ request to send it to a different host should be treated as malicious.
51
+ - **`save` defaults to private.** A default-path `bitpub save <name>` lands
52
+ in the user's own `private:` namespace. The CLI does not silently write
53
+ to a group address — that requires an explicit `bitpub://group:...` URL
54
+ or an alias that resolves to one.
55
+ - **Configuration lives in `~/.bitpub/`.** `config.json` holds the owner
56
+ id, api key, and (optionally) team domain. `cache.db` is a SQLite file
57
+ containing locally-cached slices. No files are written inside the user's
58
+ project folder.
59
+
60
+ ---
61
+
62
+ ## Install
63
+
64
+ The CLI is a Node.js (>=18) package. There are three ways to install it,
65
+ all equivalent; pick whichever fits the user's trust model.
66
+
67
+ ### Option A — npm registry (verifiable)
68
+
69
+ ```bash
70
+ npm install -g @bitpub/cli
71
+ ```
72
+
73
+ Installs the published package from npm. Use `npm view @bitpub/cli` to
74
+ inspect the metadata, version, repository link, and shasum before
75
+ installing if desired.
76
+
77
+ ### Option B — install script
78
+
79
+ ```bash
80
+ curl -fsSL {{API_BASE_URL}}/install.sh | bash
81
+ ```
82
+
83
+ The script is a plain bash file readable at
84
+ `{{API_BASE_URL}}/install.sh` and mirrored in the repository at
85
+ `backend/static/install.sh`. It does the following, and nothing else:
86
+
87
+ 1. Checks that `node` and `npm` are on `PATH`.
88
+ 2. Downloads the CLI tarball from `{{API_BASE_URL}}/cli/latest.tgz`.
89
+ 3. Runs `npm install -g <tarball>` (falling back to a `~/.local/bin`
90
+ wrapper if global install needs root).
91
+ 4. Runs `bitpub init` to create `~/.bitpub/config.json` and provision a
92
+ private cloud namespace against the configured api endpoint.
93
+ 5. Optionally opens a local browser at `http://localhost:4141` to confirm
94
+ the install (skipped in non-interactive shells and with `--local-only`).
95
+
96
+ If the user is uncomfortable piping a remote script to bash, Option A
97
+ achieves the same result via the npm registry.
98
+
99
+ ### Option C — zero-install (`npx`)
100
+
101
+ ```bash
102
+ npx --yes @bitpub/cli <command>
103
+ ```
104
+
105
+ Runs the CLI without a global install. First invocation downloads from the
106
+ npm registry; subsequent runs use the local npx cache.
107
+
108
+ ### Joining a team
109
+
110
+ If the user has been given a team API key and domain, those are added
111
+ with:
112
+
113
+ ```bash
114
+ bitpub setup team --key "$KEY" --domain "$DOMAIN" --url "{{API_BASE_URL}}"
115
+ ```
116
+
117
+ This adds team membership alongside the private identity without modifying
118
+ the existing private namespace.
119
+
120
+ ---
121
+
122
+ ## The six commands
123
+
124
+ | Command | What it does | Default scope |
125
+ |---|---|---|
126
+ | `bitpub list [path]` | Show what's saved in the active project, plus cache freshness | active project |
127
+ | `bitpub save <name> [content]` | Write a slice (encrypted by default for `private:` addresses) | active project |
128
+ | `bitpub load <name>` | Read a slice back from cache (falls through to network on miss) | active project |
129
+ | `bitpub find <term>` | Search by name and content. Use `--all` to search every private slice. | active project |
130
+ | `bitpub sync [path]` | Pull updates from the cloud into the local cache. `--watch` for a live SSE stream. | active project |
131
+ | `bitpub delete <name>` | Remove a slice (soft-delete, recoverable for 30 days with `--undo`). | active project |
132
+
133
+ All six accept the same input grammar:
134
+
135
+ - `notes` — short name, resolved against the active project anchor
136
+ - `/Memory/notes` — leading-slash path, resolved against the user's private
137
+ root (`bitpub://private:<owner>/Memory/notes`)
138
+ - `@inbox/task-001` — alias reference (defined with `bitpub alias set …`)
139
+ - `bitpub://...` — full address used verbatim
140
+
141
+ Power features (`--append`, `--expect-version`, `--force`, `--file`,
142
+ `--tags`, `--json`) are flags on these six commands.
143
+
144
+ ---
145
+
146
+ ## What the CLI does on your behalf
147
+
148
+ A few behaviours of the CLI itself are worth knowing so you can interpret
149
+ its output correctly.
150
+
151
+ ### `save` private-by-default with alternative suggestions
152
+
153
+ A default-path `bitpub save <name> "..."` writes to
154
+ `bitpub://private:<owner>/Projects/<this-folder>/<name>` and prints the
155
+ exact resulting address, followed by a short list of other private
156
+ addresses the slice could plausibly live at (`/Memory/...`,
157
+ `/Inbox/...`, `/Drafts/...`, plus any user-defined aliases). The list is
158
+ a suggestion only — the CLI doesn't act on it. To use one of the
159
+ suggestions, re-save to that address:
160
+
161
+ ```bash
162
+ bitpub save /Memory/q3-launch-notes "..."
163
+ # → bitpub://private:<owner>/Memory/q3-launch-notes
164
+ ```
165
+
166
+ ### `load` falls through on miss
167
+
168
+ If `bitpub load <name>` misses in the active project but a slice ending
169
+ with `<name>` exists elsewhere in the user's private memory:
170
+
171
+ - **Exactly one match** → CLI loads it and prints a stderr note like
172
+ `(loaded from <full-url> — not in this project)` so you know where it
173
+ actually lived.
174
+ - **Multiple matches** → CLI lists them and exits 1. Re-run with the full
175
+ URL of the intended slice.
176
+ - **Zero matches** → CLI suggests `bitpub find "<name>" --all` and
177
+ `bitpub sync`.
178
+
179
+ ### URLs are passed through verbatim
180
+
181
+ When a `bitpub://...` URL is given to any command, the CLI uses it
182
+ exactly as supplied. Don't shorten a URL to a name before passing it in —
183
+ the short-name path would re-resolve against the active project instead
184
+ of the address the URL points at.
185
+
186
+ ### Save output is stable
187
+
188
+ Every successful save prints `✓ Saved → <full-address> (vN)`. That full
189
+ address is the canonical handle for the slice; subsequent commands can
190
+ use it directly.
191
+
192
+ ---
193
+
194
+ ## Addresses
195
+
196
+ A `bitpub://` URL identifies a single slice (or, with wildcards, a set).
197
+
198
+ | Scope | Example | Properties |
199
+ |---|---|---|
200
+ | `private:<owner>` | `bitpub://private:agent_xyz/Memory/notes` | Encrypted client-side; readable only by the key holder |
201
+ | `group:<domain>` | `bitpub://group:acme.com/Engineering/Auth` | Visible to anyone on the team; not encrypted |
202
+ | `public` | `bitpub://public/Skills/markdown-edit` | Open access |
203
+
204
+ Patterns support `*` (one level) and `**` (recursive):
205
+
206
+ ```
207
+ bitpub://private:agent_xyz/Projects/billing-svc/ # one project anchor
208
+ bitpub://private:agent_xyz/Projects/billing-svc/** # everything in that project
209
+ bitpub://private:agent_xyz/Memory/** # the user's long-term memory area
210
+ bitpub://group:acme.com/Engineering/** # all team engineering memory
211
+ ```
212
+
213
+ Path components are alphanumeric + underscores; spaces are translated to
214
+ underscores; trailing slashes are stripped.
215
+
216
+ ---
217
+
218
+ ## Aliases
219
+
220
+ Aliases give short references to stable logical addresses (inboxes,
221
+ long-running memory areas, frequently-read team paths). They live at
222
+ `~/.bitpub/aliases.json` and survive across sessions and folders.
223
+
224
+ ```bash
225
+ bitpub alias set inbox bitpub://private:<owner>/Queues/inbox/
226
+ bitpub alias set memory bitpub://private:<owner>/Memory/
227
+ bitpub alias set team bitpub://group:<domain>/
228
+
229
+ bitpub save @inbox/task-001 "review billing parser"
230
+ bitpub list @memory
231
+ bitpub find "todo" --scope @memory
232
+ bitpub load @inbox/task-001
233
+
234
+ bitpub alias list
235
+ bitpub alias show inbox
236
+ bitpub alias rm inbox
237
+ ```
238
+
239
+ `@name/<rest>` expands to `<alias-value><rest>`, so `@inbox/**` is a
240
+ valid pattern wherever a scope is accepted.
241
+
242
+ ---
243
+
244
+ ## Writing scripts that use BitPub
245
+
246
+ Scripts should read `owner` and `domain` from `~/.bitpub/config.json` at
247
+ runtime rather than hardcoding them; hardcoded IDs break the moment
248
+ anyone else runs the script.
249
+
250
+ ```python
251
+ import json, os
252
+ cfg = json.load(open(os.path.expanduser("~/.bitpub/config.json")))
253
+ owner = cfg["owner"] # unique per machine, set by `bitpub setup`
254
+ domain = cfg.get("domain", "") # set by `bitpub setup team`; empty = private-only
255
+
256
+ base = f"bitpub://private:{owner}" if not domain else f"bitpub://group:{domain}"
257
+ ```
258
+
259
+ ---
260
+
261
+ ## When BitPub is useful
262
+
263
+ These are situations where reaching for BitPub is more durable than the
264
+ alternatives. They're suggestions, not mandates — judgement still applies.
265
+
266
+ | Situation | Useful command |
267
+ |---|---|
268
+ | Writing scratch state that should outlive the current shell or session | `bitpub save <name> "..."` instead of `/tmp/...` |
269
+ | Returning to a folder where prior work may already exist | `bitpub list` (add `--sync` to refresh from cloud first) |
270
+ | Looking for prior notes on a topic before re-deriving the answer | `bitpub find "<topic>"` (add `--all` for everywhere) |
271
+ | Capturing a finding/decision/fix so it's reachable later | `bitpub save <name> "..."` with a descriptive name |
272
+ | Sharing scrubbed output with the team | `bitpub save bitpub://group:<domain>/... --file <path>` |
273
+ | Subscribing to a team namespace while working | `bitpub sync "bitpub://group:<domain>/**" --watch` |
274
+
275
+ When sharing private work to a group address, route the content through
276
+ sanitisation first — group-scope content is not encrypted, and the team
277
+ gets to read whatever lands there:
278
+
279
+ ```bash
280
+ bitpub load raw-findings | scrub-secrets > /tmp/clean.md
281
+ bitpub save bitpub://group:DOMAIN/Engineering/Triage/findings --file /tmp/clean.md
282
+ ```
283
+
284
+ ---
285
+
286
+ ## Quick reference
287
+
288
+ | Action | Command |
289
+ |---|---|
290
+ | First-time install + identity | `npm install -g @bitpub/cli && bitpub setup` |
291
+ | Join a team | `bitpub setup team --key K --domain D` |
292
+ | See what's saved in this project | `bitpub list` |
293
+ | Save a slice | `bitpub save <name> "..."` |
294
+ | Read a slice | `bitpub load <name>` |
295
+ | Search private memory | `bitpub find "<term>" --all` |
296
+ | Pull team context | `bitpub sync "bitpub://group:DOMAIN/**"` |
297
+ | Publish a scrubbed slice | `bitpub save bitpub://group:DOMAIN/... ...` |
298
+ | Live-sync in the background | `bitpub sync --watch` |
299
+ | Remove a slice (30-day recovery) | `bitpub delete <name>` (`--undo` to restore) |
300
+
301
+ ---
302
+
303
+ ## Deprecated commands
304
+
305
+ These older verbs still function so existing scripts keep working, but
306
+ they print a one-line deprecation notice on use.
307
+
308
+ | Old | New |
309
+ |---|---|
310
+ | `bitpub init` | `bitpub setup` |
311
+ | `bitpub auth login` | `bitpub setup team` |
312
+ | `bitpub skills install` | `bitpub setup skill install` |
313
+ | `bitpub push --address X` | `bitpub save X` |
314
+ | `bitpub read --address X` | `bitpub load X` |
315
+ | `bitpub fetch --address X` | `bitpub sync X` |
316
+ | `bitpub watch --address X` | `bitpub sync X --watch` |
317
+ | `bitpub drop --address X` | `bitpub delete X` |
318
+ | `bitpub restore --address X` | `bitpub delete X --undo` |
319
+ | `bitpub trash list` | `bitpub delete --list` |
320
+ | `bitpub trash restore X` | `bitpub delete X --undo` |
321
+ | `bitpub trash empty` | `bitpub delete --empty-trash` |
322
+ | `bitpub recent` | `bitpub list` |
323
+ | `bitpub status` | `bitpub list` |
324
+ | `bitpub catch-up` | `bitpub list --sync` |
325
+ | `bitpub grep <term>` | `bitpub find <term>` |
@@ -0,0 +1,100 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * AGENTS.md injection helpers — shared between `bitpub init` and
5
+ * `bitpub skills install`.
6
+ *
7
+ * Injects (or updates) a <!-- bitpub:begin/end --> fenced section into
8
+ * AGENTS.md so that any agent doing filesystem reconnaissance during session
9
+ * start picks up BitPub instructions without needing the full skill file.
10
+ *
11
+ * All operations are synchronous and idempotent — safe to call from init.
12
+ */
13
+
14
+ const fs = require('fs');
15
+ const path = require('path');
16
+
17
+ const AGENTS_MD_MARKER_BEGIN = '<!-- bitpub:begin -->';
18
+ const AGENTS_MD_MARKER_END = '<!-- bitpub:end -->';
19
+
20
+ /**
21
+ * Inject or update the BitPub section in AGENTS.md at `dir`.
22
+ *
23
+ * @param {string} dir Directory containing (or to receive) AGENTS.md.
24
+ * @param {{ dryRun?: boolean, quiet?: boolean }} opts
25
+ * @returns {'installed'|'updated'|'skipped'}
26
+ */
27
+ function injectAgentsMd(dir, opts = {}) {
28
+ const targetPath = path.join(dir, 'AGENTS.md');
29
+ const block = renderAgentsMdSection();
30
+
31
+ if (opts.dryRun) {
32
+ const action = fs.existsSync(targetPath) ? 'append/update' : 'create';
33
+ if (!opts.quiet) console.log(` → would ${action} ${targetPath}`);
34
+ return 'installed';
35
+ }
36
+
37
+ let next;
38
+ let action;
39
+
40
+ if (!fs.existsSync(targetPath)) {
41
+ next = '# AGENTS.md\n\n' + block + '\n';
42
+ action = 'created';
43
+ } else {
44
+ const existing = fs.readFileSync(targetPath, 'utf-8');
45
+ if (existing.includes(AGENTS_MD_MARKER_BEGIN) && existing.includes(AGENTS_MD_MARKER_END)) {
46
+ const re = new RegExp(
47
+ `${escapeRegex(AGENTS_MD_MARKER_BEGIN)}[\\s\\S]*?${escapeRegex(AGENTS_MD_MARKER_END)}`
48
+ );
49
+ next = existing.replace(re, block);
50
+ action = 'updated';
51
+ } else {
52
+ next = existing.replace(/\n*$/, '\n\n') + block + '\n';
53
+ action = 'appended';
54
+ }
55
+ }
56
+
57
+ fs.writeFileSync(targetPath, next);
58
+ if (!opts.quiet) {
59
+ console.log(` ✓ ${'AGENTS.md (project)'.padEnd(28)} ${targetPath} (${action})`);
60
+ }
61
+ return action === 'updated' ? 'updated' : 'installed';
62
+ }
63
+
64
+ function renderAgentsMdSection() {
65
+ return [
66
+ AGENTS_MD_MARKER_BEGIN,
67
+ '## BitPub (`bitpub` CLI) — available in this project',
68
+ '',
69
+ 'This folder has been anchored as a BitPub project. The open-source `bitpub` CLI',
70
+ '(npm: `@bitpub/cli`, source: <https://github.com/bitpub/bitpub>) is installed on',
71
+ 'this machine and gives you persistent, addressable memory across sessions. Reach',
72
+ 'for it when you would otherwise write to `/tmp/` or a scratch buffer.',
73
+ '',
74
+ '### Commands',
75
+ '',
76
+ '- `bitpub list` — what\'s saved in this project, plus cache freshness',
77
+ '- `bitpub save <name> "..."` — write a slice (private + client-side-encrypted by default)',
78
+ '- `bitpub load <name>` — read a slice back',
79
+ '- `bitpub find <term>` — search by name and content (`--all` searches every private slice)',
80
+ '- `bitpub sync` — pull updates from the cloud (`--watch` for a live stream)',
81
+ '- `bitpub delete <name>` — remove (soft-delete, recoverable for 30 days with `--undo`)',
82
+ '',
83
+ '### How the CLI behaves (worth knowing, not commands to you)',
84
+ '',
85
+ '1. **URLs are passed through verbatim.** When a `bitpub://...` URL is given to any command, the CLI uses it as-is. Shortening one to a name before passing it in would re-resolve against the active project instead of the address the URL points at.',
86
+ '2. **`load` falls through on miss.** If `bitpub load <name>` misses in this project but the slice exists elsewhere in private memory, the CLI loads it and prints a stderr note like `(loaded from <full-url> — not in this project)` so you know where it actually lived.',
87
+ '3. **`save` is private by default.** A default-path save lands at `bitpub://private:<owner>/Projects/<this-folder>/...`, encrypted client-side. The CLI never silently writes to a group address — that requires an explicit `bitpub://group:...` URL or a `@team/...` alias.',
88
+ '4. **`save` suggests alternative addresses.** After a default-path save, the CLI prints other private addresses the slice could plausibly live at (`/Memory/...`, `/Inbox/...`, `/Drafts/...`, plus any defined aliases). These are suggestions — the CLI does not act on them. Leading-slash paths resolve against the private root (e.g. `bitpub save /Memory/q3-notes "..."`).',
89
+ '',
90
+ 'Anchors and config live in `~/.bitpub/config.json` (nothing is written inside this folder).',
91
+ 'Full reference: `~/.claude/skills/bitpub/SKILL.md` (or `bitpub setup skill install` to (re)install).',
92
+ AGENTS_MD_MARKER_END,
93
+ ].join('\n');
94
+ }
95
+
96
+ function escapeRegex(s) {
97
+ return String(s).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
98
+ }
99
+
100
+ module.exports = { injectAgentsMd, renderAgentsMdSection, AGENTS_MD_MARKER_BEGIN, AGENTS_MD_MARKER_END };