cocod 0.0.1

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.
@@ -0,0 +1,37 @@
1
+ name: Publish to npm
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+
8
+ jobs:
9
+ publish:
10
+ if: "!contains(github.event.head_commit.message, '[skip ci]')"
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ contents: write
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ with:
17
+ fetch-depth: 0
18
+ - uses: actions/setup-node@v4
19
+ with:
20
+ node-version: 20
21
+ registry-url: "https://registry.npmjs.org"
22
+ - name: Configure git user
23
+ run: |
24
+ git config user.name "github-actions[bot]"
25
+ git config user.email "github-actions[bot]@users.noreply.github.com"
26
+ - name: Bump version
27
+ run: npm version patch --no-git-tag-version
28
+ - name: Publish to npm
29
+ env:
30
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
31
+ run: npm publish --access public
32
+ - name: Commit version bump
33
+ run: |
34
+ VERSION=$(node -p "require('./package.json').version")
35
+ git add package.json
36
+ git commit -m "chore(release): v$VERSION [skip ci]"
37
+ git push
package/.prettierrc ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "printWidth": 100,
3
+ "tabWidth": 2,
4
+ "useTabs": false,
5
+ "semi": true,
6
+ "singleQuote": false,
7
+ "trailingComma": "all",
8
+ "bracketSpacing": true,
9
+ "arrowParens": "always"
10
+ }
package/AGENTS.md ADDED
@@ -0,0 +1,210 @@
1
+ # AGENTS.md
2
+
3
+ This repository is a small Bun + TypeScript CLI/daemon.
4
+ Agents should optimize for: minimal diffs, strict types, Bun-native APIs, and predictable CLI UX.
5
+
6
+ ## Ground Rules (Repo Policy)
7
+
8
+ - Runtime: Bun (not Node). Prefer Bun APIs over Node/polyfills.
9
+ - Module system: ESM (`"type": "module"` in `package.json`).
10
+ - TypeScript is the linter: `tsc --noEmit` is the primary check.
11
+ - No Cursor/Copilot rule files were found (`.cursor/rules/**`, `.cursorrules`, `.github/copilot-instructions.md`).
12
+ - Also follow `CLAUDE.md` (Bun defaults, preferred APIs, testing conventions).
13
+
14
+ ## Project Shape
15
+
16
+ - `src/index.ts`: entrypoint for the `cocod` binary (shebang: `#!/usr/bin/env bun`).
17
+ - `src/cli.ts` + `src/cli-shared.ts`: Commander-based CLI.
18
+ - `src/daemon.ts`: background daemon implemented with `Bun.serve()` on a UNIX socket.
19
+ - `src/routes.ts`: HTTP route handlers for the daemon (endpoints like /balance, /receive, /init, etc.).
20
+ - `src/utils/`:
21
+ - `state.ts`: DaemonStateManager and wallet state logic
22
+ - `wallet.ts`: Wallet initialization helpers
23
+ - `crypto.ts`: Mnemonic encryption/decryption
24
+ - `config.ts`: Configuration paths, env vars, and types
25
+ - IPC: CLI talks to daemon via `fetch()` with Bun's `RequestInit.unix` option.
26
+
27
+ Key paths/env:
28
+
29
+ - Socket: `COCOD_SOCKET` (default `/tmp/cocod.sock`).
30
+ - PID file: `COCOD_PID` (default `/tmp/cocod.pid`).
31
+ - Wallet config: `~/.config/cocod/config.json` (generated; do not commit).
32
+
33
+ ## Commands
34
+
35
+ All commands run from repo root (`/home/egge/projects/cocod`).
36
+
37
+ ### Install
38
+
39
+ ```sh
40
+ bun install
41
+ ```
42
+
43
+ ### Run the CLI (foreground)
44
+
45
+ - Entrypoint:
46
+
47
+ ```sh
48
+ bun src/index.ts --help
49
+ ```
50
+
51
+ - Via npm-style script (use `--` to pass args):
52
+
53
+ ```sh
54
+ bun run start -- --help
55
+ ```
56
+
57
+ - Common commands:
58
+
59
+ ```sh
60
+ bun src/index.ts balance
61
+ bun src/index.ts ping
62
+ bun src/index.ts mint list
63
+ ```
64
+
65
+ ### Start the daemon
66
+
67
+ The daemon can be started explicitly, but the CLI also auto-starts it when needed.
68
+
69
+ ```sh
70
+ bun run daemon
71
+ ```
72
+
73
+ ### Build / bundle
74
+
75
+ There is no required build step (the CLI runs directly via Bun + TypeScript).
76
+
77
+ - Optional: produce a bundled artifact:
78
+
79
+ ```sh
80
+ bun build src/index.ts --outdir dist --target bun
81
+ ```
82
+
83
+ ### Lint / typecheck
84
+
85
+ This repo currently uses TypeScript as the main lint gate.
86
+
87
+ ```sh
88
+ bun run lint
89
+ ```
90
+
91
+ If you need to run tsc directly:
92
+
93
+ ```sh
94
+ bunx tsc --noEmit
95
+ ```
96
+
97
+ ### Tests
98
+
99
+ There are currently no committed test files, but Bun's test runner is the expected choice.
100
+
101
+ - Run all tests:
102
+
103
+ ```sh
104
+ bun test
105
+ ```
106
+
107
+ - Run a single test file:
108
+
109
+ ```sh
110
+ bun test path/to/file.test.ts
111
+ ```
112
+
113
+ - Run a single test by name (recommended when adding tests):
114
+
115
+ ```sh
116
+ bun test -t "ping returns pong"
117
+ ```
118
+
119
+ Notes:
120
+
121
+ - Prefer test files named `*.test.ts` and colocated near the code they test.
122
+ - Use `import { test, expect } from "bun:test";`.
123
+
124
+ ## Code Style
125
+
126
+ There is no formatter config in this repo. Match existing style and avoid drive-by reformatting.
127
+
128
+ ### Formatting
129
+
130
+ - Indentation: 2 spaces.
131
+ - Quotes: double quotes for strings.
132
+ - Semicolons: use them consistently (match surrounding file).
133
+ - Line length: keep lines reasonably short; wrap long function signatures.
134
+
135
+ ### Imports
136
+
137
+ - Order:
138
+ 1. external packages
139
+ 2. blank line
140
+ 3. local relative imports
141
+ - Prefer `import type { ... }` for type-only imports.
142
+ - Prefer named imports; avoid default imports unless the package is default-first.
143
+ - Keep relative imports extensionless (match current code). Only include `.js` when required by ESM packages.
144
+
145
+ ### Types and strictness
146
+
147
+ `tsconfig.json` enables strict TypeScript plus `noUncheckedIndexedAccess`.
148
+
149
+ - Avoid `any`. Use `unknown` at boundaries and narrow.
150
+ - Validate untrusted inputs (CLI args, request bodies, env vars).
151
+ - When indexing objects, handle `undefined` explicitly (e.g., `balance[mintUrl] || 0`).
152
+ - Prefer explicit return types on exported functions and non-trivial helpers.
153
+ - Use discriminated unions / literal types for protocol-like payloads.
154
+
155
+ ### Naming
156
+
157
+ - Files: kebab-case for multiword modules (e.g., `cli-shared.ts`).
158
+ - Types/interfaces: `PascalCase`.
159
+ - Functions/variables: `camelCase`.
160
+ - Constants: `UPPER_SNAKE_CASE` for configuration-like values.
161
+ - CLI commands: lowercase; nouns/verbs consistent with existing Commander usage.
162
+
163
+ ### Error handling
164
+
165
+ General:
166
+
167
+ - Only `process.exit()` from true CLI entrypoints.
168
+ - Prefer throwing `Error` (or subclasses) from library-ish functions.
169
+ - In `catch`, treat the error as `unknown`; derive a safe message:
170
+ - `error instanceof Error ? error.message : String(error)`.
171
+
172
+ Daemon (`src/daemon.ts`):
173
+
174
+ - Return JSON with either `{ output: string }` or `{ error: string }`.
175
+ - Use proper HTTP status codes for failures (e.g., 400 for bad input, 404 unknown endpoint, 500 unexpected).
176
+ - Do not swallow errors silently; if you intentionally suppress errors (e.g., delete stale files), add a short comment.
177
+
178
+ CLI (`src/cli-shared.ts`):
179
+
180
+ - Print user-facing errors to stderr (`console.error`).
181
+ - Exit with code 1 for expected failures.
182
+ - For daemon connectivity issues, prefer actionable messages (socket path, how to start daemon).
183
+
184
+ ### Bun-specific guidance (from `CLAUDE.md`)
185
+
186
+ - Use `bun <file>` / `bun run <script>` (not `node`, `ts-node`, `npm`).
187
+ - Use `bun test` (not jest/vitest).
188
+ - Use `Bun.serve()` routes/websocket support (not express).
189
+ - Prefer `Bun.file` for file IO; Bun loads `.env` automatically (avoid `dotenv`).
190
+ - Prefer Bun-native DB/network libs where applicable:
191
+ - `bun:sqlite` for SQLite (avoid `better-sqlite3`)
192
+ - `Bun.sql` for Postgres (avoid `pg`)
193
+ - `Bun.redis` for Redis (avoid `ioredis`)
194
+ - built-in `WebSocket` (avoid `ws`)
195
+
196
+ ## Editing Expectations for Agents
197
+
198
+ - Keep diffs surgical; do not reformat unrelated code.
199
+ - Preserve CLI UX and backward compatibility of command names/flags unless explicitly requested.
200
+ - Avoid committing/generated artifacts (e.g., `coco.db`, sockets, pid files, `.env`).
201
+ - When adding new commands/routes:
202
+ - update Commander wiring in `src/cli.ts`
203
+ - add a daemon handler in `src/daemon.ts` (and ensure it returns the `{ output | error }` shape)
204
+ - keep the CLI/daemon contract explicit (method, path, request/response types).
205
+
206
+ ## Quick Debugging Checklist
207
+
208
+ - CLI can't connect: verify `COCOD_SOCKET` matches daemon and the socket exists.
209
+ - Daemon won't start: check for stale `/tmp/cocod.sock` and `/tmp/cocod.pid`.
210
+ - Type errors: run `bun run lint` and fix strictness issues (especially `undefined` from indexing).
package/CLAUDE.md ADDED
@@ -0,0 +1,105 @@
1
+ Default to using Bun instead of Node.js.
2
+
3
+ - Use `bun <file>` instead of `node <file>` or `ts-node <file>`
4
+ - Use `bun test` instead of `jest` or `vitest`
5
+ - Use `bun build <file.html|file.ts|file.css>` instead of `webpack` or `esbuild`
6
+ - Use `bun install` instead of `npm install` or `yarn install` or `pnpm install`
7
+ - Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` or `pnpm run <script>`
8
+ - Use `bunx <package> <command>` instead of `npx <package> <command>`
9
+ - Bun automatically loads .env, so don't use dotenv.
10
+
11
+ ## APIs
12
+
13
+ - `Bun.serve()` supports WebSockets, HTTPS, and routes. Don't use `express`.
14
+ - `bun:sqlite` for SQLite. Don't use `better-sqlite3`.
15
+ - `Bun.redis` for Redis. Don't use `ioredis`.
16
+ - `Bun.sql` for Postgres. Don't use `pg` or `postgres.js`.
17
+ - `WebSocket` is built-in. Don't use `ws`.
18
+ - Prefer `Bun.file` over `node:fs`'s readFile/writeFile
19
+ - Bun.$`ls` instead of execa.
20
+
21
+ ## Testing
22
+
23
+ Use `bun test` to run tests.
24
+
25
+ ```ts#index.test.ts
26
+ import { test, expect } from "bun:test";
27
+
28
+ test("hello world", () => {
29
+ expect(1).toBe(1);
30
+ });
31
+ ```
32
+
33
+ ## Frontend
34
+
35
+ Use HTML imports with `Bun.serve()`. Don't use `vite`. HTML imports fully support React, CSS, Tailwind.
36
+
37
+ Server:
38
+
39
+ ```ts#index.ts
40
+ import index from "./index.html"
41
+
42
+ Bun.serve({
43
+ routes: {
44
+ "/": index,
45
+ "/api/users/:id": {
46
+ GET: (req) => {
47
+ return new Response(JSON.stringify({ id: req.params.id }));
48
+ },
49
+ },
50
+ },
51
+ // optional websocket support
52
+ websocket: {
53
+ open: (ws) => {
54
+ ws.send("Hello, world!");
55
+ },
56
+ message: (ws, message) => {
57
+ ws.send(message);
58
+ },
59
+ close: (ws) => {
60
+ // handle close
61
+ }
62
+ },
63
+ development: {
64
+ hmr: true,
65
+ console: true,
66
+ }
67
+ })
68
+ ```
69
+
70
+ HTML files can import .tsx, .jsx or .js files directly and Bun's bundler will transpile & bundle automatically. `<link>` tags can point to stylesheets and Bun's CSS bundler will bundle.
71
+
72
+ ```html#index.html
73
+ <html>
74
+ <body>
75
+ <h1>Hello, world!</h1>
76
+ <script type="module" src="./frontend.tsx"></script>
77
+ </body>
78
+ </html>
79
+ ```
80
+
81
+ With the following `frontend.tsx`:
82
+
83
+ ```tsx#frontend.tsx
84
+ import React from "react";
85
+ import { createRoot } from "react-dom/client";
86
+
87
+ // import .css files directly and it works
88
+ import './index.css';
89
+
90
+ const root = createRoot(document.body);
91
+
92
+ export default function Frontend() {
93
+ return <h1>Hello, world!</h1>;
94
+ }
95
+
96
+ root.render(<Frontend />);
97
+ ```
98
+
99
+ Then, run index.ts
100
+
101
+ ```sh
102
+ bun --hot ./index.ts
103
+ ```
104
+
105
+ For more information, read the Bun API docs in `node_modules/bun-types/docs/**.mdx`.
package/README.md ADDED
@@ -0,0 +1,179 @@
1
+ # cocod
2
+
3
+ A Cashu wallet CLI and daemon built with Bun and TypeScript.
4
+
5
+ ## Overview
6
+
7
+ `cocod` is a [Cashu](https://cashu.space/) e-cash wallet with a client-daemon architecture. It provides a command-line interface for managing Cashu tokens while a background daemon handles all wallet operations, state management, and mint communication.
8
+
9
+ ### Features
10
+
11
+ - **Wallet Management**: Initialize with BIP39 mnemonics, optional passphrase encryption
12
+ - **Token Operations**: Receive Cashu tokens, check balances across mints
13
+ - **Lightning Integration**: Create BOLT11 invoices to mint new tokens
14
+ - **Nostr Payment Codes**: NPC addresses for receiving payments
15
+ - **Transaction History**: View and paginate wallet history
16
+ - **Real-time Updates**: SSE endpoint for live event streaming
17
+ - **Multi-mint Support**: Add and manage multiple Cashu mints
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ bun install
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ ### Quick Start
28
+
29
+ ```bash
30
+ # Check daemon status
31
+ bun src/index.ts status
32
+
33
+ # Initialize wallet (generates mnemonic automatically)
34
+ bun src/index.ts init
35
+
36
+ # Or initialize with your own mnemonic
37
+ bun src/index.ts init "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
38
+
39
+ # Unlock encrypted wallet (if passphrase was set)
40
+ bun src/index.ts unlock "your-passphrase"
41
+
42
+ # Check balance
43
+ bun src/index.ts balance
44
+ ```
45
+
46
+ ### Available Commands
47
+
48
+ #### Wallet Operations
49
+
50
+ | Command | Description |
51
+ | --------------------- | --------------------------------------------------------------- |
52
+ | `status` | Check daemon and wallet status |
53
+ | `init [mnemonic]` | Initialize wallet (generates mnemonic if not provided) |
54
+ | `unlock <passphrase>` | Unlock encrypted wallet |
55
+ | `balance` | Get wallet balance across all mints |
56
+ | `receive <token>` | Receive a Cashu token |
57
+ | `history` | View wallet history (supports `--offset`, `--limit`, `--watch`) |
58
+
59
+ #### Mint Management
60
+
61
+ | Command | Description |
62
+ | ---------------------- | --------------------------------------- |
63
+ | `mint add <url>` | Add a new mint URL |
64
+ | `mint list` | List configured mints |
65
+ | `mint bolt11 <amount>` | Create Lightning invoice to mint tokens |
66
+
67
+ #### NPC (npub.cash)
68
+
69
+ | Command | Description |
70
+ | ------------- | -------------------------------------- |
71
+ | `npc address` | Get NPC address for receiving payments |
72
+
73
+ #### Daemon Control
74
+
75
+ | Command | Description |
76
+ | -------- | -------------------------------------- |
77
+ | `ping` | Test daemon connectivity |
78
+ | `stop` | Stop the background daemon |
79
+ | `daemon` | Start the background daemon explicitly |
80
+
81
+ ### Examples
82
+
83
+ ```bash
84
+ # Add a mint
85
+ bun src/index.ts mint add https://mint.example.com
86
+
87
+ # Create a Lightning invoice for 1000 sats
88
+ bun src/index.ts mint bolt11 1000
89
+
90
+ # Receive a Cashu token
91
+ bun src/index.ts receive "cashuAeyJ0b2tlbiI6W3sicHJvb2ZzIjpbeyJ..."
92
+
93
+ # View last 10 history entries
94
+ bun src/index.ts history --limit 10
95
+
96
+ # Watch history in real-time
97
+ bun src/index.ts history --watch
98
+ ```
99
+
100
+ ## Architecture
101
+
102
+ ### Client-Daemon Model
103
+
104
+ - **CLI** (`src/cli.ts`): Thin client that sends HTTP requests to the daemon via Unix socket
105
+ - **Daemon** (`src/daemon.ts`): Background service using `Bun.serve()` that handles all wallet operations
106
+
107
+ The CLI automatically starts the daemon if it's not already running.
108
+
109
+ ### IPC Communication
110
+
111
+ Communication happens over a Unix domain socket:
112
+
113
+ - Default: `~/.cocod/cocod.sock`
114
+ - Configurable via `COCOD_SOCKET` environment variable
115
+
116
+ ## Configuration
117
+
118
+ ### Environment Variables
119
+
120
+ | Variable | Default | Description |
121
+ | -------------- | --------------------- | ---------------- |
122
+ | `COCOD_SOCKET` | `~/.cocod/cocod.sock` | Unix socket path |
123
+ | `COCOD_PID` | `~/.cocod/cocod.pid` | PID file path |
124
+
125
+ ### Files
126
+
127
+ - **Config**: `~/.cocod/config.json`
128
+ - **Database**: `./coco.db` (SQLite, auto-generated)
129
+ - **PID file**: Tracks running daemon process
130
+
131
+ ## Development
132
+
133
+ ### Commands
134
+
135
+ ```bash
136
+ # Run CLI
137
+ bun src/index.ts --help
138
+
139
+ # Run with npm-style script
140
+ bun run start -- --help
141
+
142
+ # Start daemon explicitly
143
+ bun run daemon
144
+
145
+ # Type check
146
+ bun run lint
147
+ # or
148
+ bunx tsc --noEmit
149
+
150
+ # Build bundle
151
+ bun build src/index.ts --outdir dist --target bun
152
+ ```
153
+
154
+ ### Project Structure
155
+
156
+ ```
157
+ src/
158
+ ├── index.ts # CLI entrypoint (shebang: #!/usr/bin/env bun)
159
+ ├── cli.ts # Commander-based CLI commands
160
+ ├── cli-shared.ts # IPC utilities
161
+ ├── daemon.ts # Bun.serve() daemon setup
162
+ ├── routes.ts # HTTP route handlers
163
+ └── utils/
164
+ ├── config.ts # Config management
165
+ ├── state.ts # Daemon state machine
166
+ ├── wallet.ts # Wallet initialization
167
+ └── crypto.ts # Mnemonic encryption
168
+ ```
169
+
170
+ ## Dependencies
171
+
172
+ - **Bun**: Runtime and built-in APIs (`Bun.serve()`, `fetch()`, `bun:sqlite`)
173
+ - **Cashu**: `coco-cashu-core`, `coco-cashu-sqlite3`, `coco-cashu-plugin-npc`
174
+ - **CLI**: `commander` for argument parsing
175
+ - **Crypto**: `@scure/bip39` for mnemonics, `nostr-tools` for NPC
176
+
177
+ ## License
178
+
179
+ [Add your license here]
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "cocod",
3
+ "version": "0.0.1",
4
+ "module": "src/index.ts",
5
+ "type": "module",
6
+ "private": false,
7
+ "bin": {
8
+ "cocod": "./src/index.ts"
9
+ },
10
+ "scripts": {
11
+ "start": "bun src/index.ts",
12
+ "daemon": "bun src/index.ts daemon",
13
+ "lint": "tsc --noEmit",
14
+ "format": "prettier --write ."
15
+ },
16
+ "devDependencies": {
17
+ "@types/bun": "latest",
18
+ "prettier": "^3.8.1"
19
+ },
20
+ "peerDependencies": {
21
+ "typescript": "^5"
22
+ },
23
+ "dependencies": {
24
+ "@scure/bip39": "^2.0.1",
25
+ "coco-cashu-core": "^1.1.2-rc.43",
26
+ "coco-cashu-plugin-npc": "^2.2.4",
27
+ "coco-cashu-sqlite3": "^1.1.2-rc.43",
28
+ "commander": "^14.0.2",
29
+ "nostr-tools": "^2.22.1",
30
+ "sqlite3": "^5.1.7"
31
+ }
32
+ }