@ghostpaw/affinity 0.4.0 → 0.5.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 CHANGED
@@ -6,101 +6,93 @@
6
6
 
7
7
  **Agent contacts: people, promises and yearly dates, with a radar for who is drifting.**
8
8
 
9
- ```bash
10
- npm install @ghostpaw/affinity
11
- ```
9
+ A local social CRM: contacts, identities, relationships, journal events,
10
+ commitments and recurring dates in one SQLite file. One self-contained binary
11
+ per platform, an MCP server, and a zero-dependency TypeScript library.
12
12
 
13
- A standalone social CRM core for Node.js, built on SQLite.
13
+ ## Install
14
14
 
15
- Affinity treats contacts, identities, relationship mechanics, structural ties,
16
- journal evidence, commitments, recurring dates, attributes, and graph review as
17
- one coherent model instead of separate systems. It ships as a single prebundled
18
- blob with zero runtime dependencies, designed for two audiences at once: human
19
- developers working directly in code, and LLM agents operating through a
20
- structured `soul` / `tools` / `skills` runtime.
15
+ Each line downloads the latest release for one platform, checks it against
16
+ `SHA256SUMS`, puts `ghostpaw-affinity` on your `PATH` and prints the version.
21
17
 
22
- ## MCP server
18
+ **Linux x64**
23
19
 
24
- Every client below starts the same stdio server: `npx -y @ghostpaw/affinity mcp`.
25
- Contacts live in `~/.ghostpaw/affinity.db` unless the `GHOSTPAW_AFFINITY_DB`
26
- environment variable (absolute path) or `--db <path>` says otherwise.
20
+ ```sh
21
+ cd "$(mktemp -d)" && T=linux-x64 && V=$(curl -fsSLI -o /dev/null -w '%{url_effective}' https://github.com/GhostPawJS/affinity/releases/latest | sed 's|.*/v||') && F=ghostpaw-affinity-$V-$T.tar.gz && U=https://github.com/GhostPawJS/affinity/releases/download/v$V && curl -fsSL -O "$U/$F" -O "$U/SHA256SUMS" && grep " $F\$" SHA256SUMS | sha256sum -c - && tar -xzf "$F" ghostpaw-affinity && mkdir -p ~/.local/bin && mv ghostpaw-affinity ~/.local/bin/ && { case ":$PATH:" in *":$HOME/.local/bin:"*) ;; *) echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.profile; export PATH="$HOME/.local/bin:$PATH";; esac; } && ghostpaw-affinity --version
22
+ ```
27
23
 
28
- **Claude Code**
24
+ **Linux arm64**
29
25
 
30
- ```bash
31
- claude mcp add ghostpaw-affinity -- npx -y @ghostpaw/affinity mcp
26
+ ```sh
27
+ cd "$(mktemp -d)" && T=linux-arm64 && V=$(curl -fsSLI -o /dev/null -w '%{url_effective}' https://github.com/GhostPawJS/affinity/releases/latest | sed 's|.*/v||') && F=ghostpaw-affinity-$V-$T.tar.gz && U=https://github.com/GhostPawJS/affinity/releases/download/v$V && curl -fsSL -O "$U/$F" -O "$U/SHA256SUMS" && grep " $F\$" SHA256SUMS | sha256sum -c - && tar -xzf "$F" ghostpaw-affinity && mkdir -p ~/.local/bin && mv ghostpaw-affinity ~/.local/bin/ && { case ":$PATH:" in *":$HOME/.local/bin:"*) ;; *) echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.profile; export PATH="$HOME/.local/bin:$PATH";; esac; } && ghostpaw-affinity --version
32
28
  ```
33
29
 
34
- or as a plugin, which also installs the skill:
30
+ **macOS Apple silicon**
35
31
 
36
- ```bash
37
- /plugin marketplace add GhostPawJS/affinity
38
- /plugin install ghostpaw-affinity@ghostpaw-affinity
32
+ ```sh
33
+ cd "$(mktemp -d)" && T=darwin-arm64 && V=$(curl -fsSLI -o /dev/null -w '%{url_effective}' https://github.com/GhostPawJS/affinity/releases/latest | sed 's|.*/v||') && F=ghostpaw-affinity-$V-$T.tar.gz && U=https://github.com/GhostPawJS/affinity/releases/download/v$V && curl -fsSL -O "$U/$F" -O "$U/SHA256SUMS" && grep " $F\$" SHA256SUMS | shasum -a 256 -c - && tar -xzf "$F" ghostpaw-affinity && sudo mkdir -p /usr/local/bin && sudo mv ghostpaw-affinity /usr/local/bin/ && ghostpaw-affinity --version
39
34
  ```
40
35
 
41
- **Codex CLI** (`~/.affinity/config.toml`)
36
+ **macOS Intel**
42
37
 
43
- ```toml
44
- [mcp_servers.ghostpaw-affinity]
45
- command = "npx"
46
- args = ["-y", "@ghostpaw/affinity", "mcp"]
38
+ ```sh
39
+ cd "$(mktemp -d)" && T=darwin-x64 && V=$(curl -fsSLI -o /dev/null -w '%{url_effective}' https://github.com/GhostPawJS/affinity/releases/latest | sed 's|.*/v||') && F=ghostpaw-affinity-$V-$T.tar.gz && U=https://github.com/GhostPawJS/affinity/releases/download/v$V && curl -fsSL -O "$U/$F" -O "$U/SHA256SUMS" && grep " $F\$" SHA256SUMS | shasum -a 256 -c - && tar -xzf "$F" ghostpaw-affinity && sudo mkdir -p /usr/local/bin && sudo mv ghostpaw-affinity /usr/local/bin/ && ghostpaw-affinity --version
47
40
  ```
48
41
 
49
- **Cursor** (`.cursor/mcp.json`), **Claude Desktop** (`claude_desktop_config.json`)
50
- or a project `.mcp.json`:
42
+ **Windows x64 (PowerShell)**
51
43
 
52
- ```json
53
- {
54
- "mcpServers": {
55
- "ghostpaw-affinity": {
56
- "command": "npx",
57
- "args": ["-y", "@ghostpaw/affinity", "mcp"]
58
- }
59
- }
60
- }
44
+ ```powershell
45
+ $r='GhostPawJS/affinity'; $v=(irm "https://api.github.com/repos/$r/releases/latest").tag_name; $f="ghostpaw-affinity-$($v.TrimStart('v'))-windows-x64.zip"; $u="https://github.com/$r/releases/download/$v"; $t=(New-Item -ItemType Directory (Join-Path $env:TEMP ([guid]::NewGuid()))).FullName; iwr "$u/$f" -OutFile "$t\$f" -UseBasicParsing; iwr "$u/SHA256SUMS" -OutFile "$t\SHA256SUMS" -UseBasicParsing; $want=((Get-Content "$t\SHA256SUMS" | Where-Object { $_ -like "* $f" }) -split '\s+')[0]; if (-not $want -or (Get-FileHash "$t\$f" -Algorithm SHA256).Hash -ne $want) { throw "checksum mismatch for $f" }; $d=Join-Path $env:LOCALAPPDATA 'Programs\ghostpaw\bin'; Expand-Archive "$t\$f" $t -Force; New-Item -ItemType Directory -Force $d | Out-Null; Copy-Item "$t\ghostpaw-affinity.exe" $d -Force; $p=[Environment]::GetEnvironmentVariable('Path','User'); if (";$p;" -notlike "*;$d;*") { [Environment]::SetEnvironmentVariable('Path',"$p;$d",'User') }; $env:Path="$d;$env:Path"; ghostpaw-affinity --version
61
46
  ```
62
47
 
63
- Claude Desktop users can also install `server.mcpb` from the
64
- [latest GitHub release](https://github.com/GhostPawJS/affinity/releases/latest).
65
- A Dockerfile is included for container hosts:
66
- `docker build -t ghostpaw-affinity . && docker run -i --rm -v affinity:/data ghostpaw-affinity`.
48
+ Linux installs to `~/.local/bin` (added to `~/.profile` if missing), macOS to
49
+ `/usr/local/bin` (asks for sudo), Windows to `%LOCALAPPDATA%\Programs\ghostpaw\bin`
50
+ (added to the user `PATH`; open a new terminal afterwards).
67
51
 
68
- The server speaks MCP 2026-07-28 (stateless, `server/discover`) and the
69
- initialize-based revisions 2025-11-25, 2025-06-18, 2025-03-26 and 2024-11-05.
70
-
71
- ### CLI
52
+ Then:
72
53
 
73
- ```bash
74
- npx -y @ghostpaw/affinity tools
75
- npx -y @ghostpaw/affinity call manage_contact '{"action":"create","input":{"name":"Sam","kind":"human"}}'
76
- npx -y @ghostpaw/affinity call search_affinity '{"query":"Sam"}'
54
+ ```sh
55
+ ghostpaw-affinity contact create '{"name":"Sam","kind":"human"}'
56
+ ghostpaw-affinity search sam
57
+ ghostpaw-affinity skill # cheat sheet and tool reference
77
58
  ```
78
59
 
79
- Install globally for the `ghostpaw-affinity` binary: `npm i -g @ghostpaw/affinity`.
80
- `ghostpaw-affinity mcp` starts the stdio server.
60
+ Contacts live in `~/.ghostpaw/affinity.db` unless `--db <path>` or the
61
+ `GHOSTPAW_AFFINITY_DB` environment variable says otherwise; relative paths
62
+ resolve against the current directory.
81
63
 
82
- ### Agent Skill
64
+ A session with the linux-x64 binary against a fresh database:
83
65
 
84
- `SKILL.md` (repo root) and `skills/affinity/SKILL.md` follow the
85
- [Agent Skills](https://agentskills.io) format and ship in the npm package.
86
- Copy `skills/affinity/` into your agent's skills folder, or print it:
87
-
88
- ```bash
89
- npx -y @ghostpaw/affinity skill > SKILL.md
90
- ```
66
+ ![ghostpaw-affinity session: version, contact create, identity add, event and commitment record, search, review commitments.open and show contact_profile](https://raw.githubusercontent.com/GhostPawJS/affinity/main/docs/assets/cli.png)
91
67
 
92
- ## Install
68
+ The same session as an [animated GIF](https://raw.githubusercontent.com/GhostPawJS/affinity/main/docs/assets/cli.gif).
93
69
 
70
+ ### npx / npm (for npm-based environments)
94
71
 
95
- The [npm package](https://www.npmjs.com/package/@ghostpaw/affinity) requires Node 24+:
72
+ The [npm package](https://www.npmjs.com/package/@ghostpaw/affinity) needs Node 24+
73
+ and has zero runtime dependencies:
96
74
 
97
75
  ```sh
98
- npm install -g @ghostpaw/affinity
99
76
  npx -y @ghostpaw/affinity --help
77
+ npm install -g @ghostpaw/affinity # provides ghostpaw-affinity
78
+ ```
79
+
80
+ ### Library (for harnesses)
81
+
82
+ ```sh
83
+ npm install @ghostpaw/affinity
100
84
  ```
101
85
 
102
- Standalone binaries are available from [GitHub Releases](https://github.com/GhostPawJS/affinity/releases)
103
- for linux-x64, linux-arm64, darwin-arm64, darwin-x64 and windows-x64.
86
+ ```ts
87
+ import { DatabaseSync } from "node:sqlite";
88
+ import { initAffinityTables, read, write, tools } from "@ghostpaw/affinity";
89
+ ```
90
+
91
+ See [Quick Start](#quick-start) and [docs/LLM.md](docs/LLM.md) for the tool facade.
92
+
93
+ ### Other installers and verification
94
+
95
+ Interactive installers (also verify `SHA256SUMS`):
104
96
 
105
97
  ```sh
106
98
  curl -fsSL https://raw.githubusercontent.com/GhostPawJS/affinity/main/install.sh | sh
@@ -110,8 +102,6 @@ curl -fsSL https://raw.githubusercontent.com/GhostPawJS/affinity/main/install.sh
110
102
  irm https://raw.githubusercontent.com/GhostPawJS/affinity/main/install.ps1 | iex
111
103
  ```
112
104
 
113
- Other release installers:
114
-
115
105
  ```sh
116
106
  mise use -g github:GhostPawJS/affinity
117
107
  ubi --project GhostPawJS/affinity --exe ghostpaw-affinity --in ~/.local/bin
@@ -149,8 +139,8 @@ packages:
149
139
  - name: ghostpaw-affinity
150
140
  ```
151
141
 
152
- Install scripts verify SHA256SUMS. To verify a downloaded archive's
153
- [build attestation](https://cli.github.com/manual/gh_attestation_verify):
142
+ `SHA256SUMS` covers every archive and `server.mcpb`. To verify a downloaded
143
+ archive's [build attestation](https://cli.github.com/manual/gh_attestation_verify):
154
144
 
155
145
  ```sh
156
146
  gh attestation verify <archive> -R GhostPawJS/affinity
@@ -163,20 +153,99 @@ download on macOS, remove quarantine with
163
153
  Linux binaries require glibc 2.28+; use npx on Alpine.
164
154
  See the [binary build workflow](.github/workflows/release-binaries.yml).
165
155
 
166
- <!-- sizes -->
156
+ Each archive is roughly 40-46 MB (the binary embeds the Node runtime, 105-150 MB
157
+ unpacked); the npm package is about 2 MB unpacked. Every release, including the
158
+ one-liners above, is installed and run on ubuntu-24.04, macos-15 and
159
+ windows-2025 by the [install check](.github/workflows/install-check.yml).
167
160
 
168
- The install check runs on ubuntu-24.04, macos-15 and windows-2025.
161
+ ## MCP server
162
+
163
+ Every client below starts the same stdio server: `ghostpaw-affinity mcp`.
164
+ Without the binary, use `npx -y @ghostpaw/affinity mcp` as the command instead.
165
+
166
+ **Claude Code**
167
+
168
+ ```bash
169
+ claude mcp add ghostpaw-affinity -- ghostpaw-affinity mcp
170
+ ```
171
+
172
+ or as a plugin, which also installs the skill:
173
+
174
+ ```bash
175
+ /plugin marketplace add GhostPawJS/affinity
176
+ /plugin install ghostpaw-affinity@ghostpaw-affinity
177
+ ```
178
+
179
+ **Codex CLI** (`~/.codex/config.toml`)
180
+
181
+ ```toml
182
+ [mcp_servers.ghostpaw-affinity]
183
+ command = "ghostpaw-affinity"
184
+ args = ["mcp"]
185
+ ```
186
+
187
+ **Cursor** (`.cursor/mcp.json`), **Claude Desktop** (`claude_desktop_config.json`)
188
+ or a project `.mcp.json`:
189
+
190
+ ```json
191
+ {
192
+ "mcpServers": {
193
+ "ghostpaw-affinity": {
194
+ "command": "ghostpaw-affinity",
195
+ "args": ["mcp"]
196
+ }
197
+ }
198
+ }
199
+ ```
200
+
201
+ Claude Desktop users can also install `server.mcpb` from the
202
+ [latest GitHub release](https://github.com/GhostPawJS/affinity/releases/latest).
203
+ A Dockerfile is included for container hosts:
204
+ `docker build -t ghostpaw-affinity . && docker run -i --rm -v affinity:/data ghostpaw-affinity`.
205
+
206
+ The server speaks MCP 2026-07-28 (stateless, `server/discover`) and the
207
+ initialize-based revisions 2025-11-25, 2025-06-18, 2025-03-26 and 2024-11-05.
208
+
209
+ ### Agent Skill
210
+
211
+ `SKILL.md` (repo root) and `skills/affinity/SKILL.md` follow the
212
+ [Agent Skills](https://agentskills.io) format and ship in the npm package.
213
+ Copy `skills/affinity/` into your agent's skills folder, or print it:
214
+
215
+ ```bash
216
+ ghostpaw-affinity skill > SKILL.md
217
+ ghostpaw-affinity skill --list # workflow guides
218
+ ghostpaw-affinity skill bootstrap-and-cold-start
219
+ ```
169
220
 
170
221
  ## CLI
171
222
 
223
+ ```sh
224
+ export GHOSTPAW_AFFINITY_DB=~/crm/affinity.db # or --db <path>
225
+ ghostpaw-affinity contact create '{"name":"Fox","kind":"human","bootstrapOwner":true}'
226
+ ghostpaw-affinity search "jana" # names, identities, tags, attributes, roles, events
227
+ ghostpaw-affinity contact create '{"name":"Jana Petersen","kind":"human"}'
228
+ ghostpaw-affinity identity add --contact '{"contactId":2}' --input '{"type":"email","value":"jana@example.com"}'
229
+ ghostpaw-affinity event record --kind interaction --input '{"type":"conversation","occurredAt":"today","summary":"Call re pilot","significance":6,"participants":[{"contactId":2,"role":"recipient","directionality":"mutual"}]}'
230
+ ghostpaw-affinity commitment record --input '{"commitmentType":"promise","occurredAt":"today","dueAt":"+3d","summary":"Send proposal","significance":6,"participants":[{"contactId":2,"role":"recipient"}]}'
231
+ ghostpaw-affinity attribute set --target '{"kind":"contact","contact":{"contactId":2}}' --name tag:gastro --value null
232
+ ghostpaw-affinity review contacts.list --tag gastro
233
+ ghostpaw-affinity review contacts.list --attribute pipeline_stage=proposal
234
+ ghostpaw-affinity review commitments.open # overdue promises are flagged
235
+ ghostpaw-affinity review links.radar # who is drifting, with reasons
236
+ ghostpaw-affinity show contact_profile --contact '{"contactId":2}'
237
+ ghostpaw-affinity contact export --contact '{"contactId":2}' # omit --contact for the whole database
238
+ ghostpaw-affinity contact delete --contact '{"contactId":2}' --confirm
239
+ ```
240
+
241
+ `ghostpaw-affinity skill` prints the full cheat sheet; `skill --list` and
242
+ `skill <guide>` print the workflow guides.
243
+
172
244
  ```text
173
- ghostpaw-affinity search <query>
174
- ghostpaw-affinity review <view>
245
+ ghostpaw-affinity search <query> [--tag T] [--attribute name[=value]]
246
+ ghostpaw-affinity review <view> [--tag T] [--attribute name[=value]]
175
247
  ghostpaw-affinity show <owner_profile|contact_profile|link> [--contact JSON --link JSON]
176
- ghostpaw-affinity contact create <input-json>
177
- ghostpaw-affinity contact revise <contact-json> --patch JSON
178
- ghostpaw-affinity contact lifecycle <contact-json> <lifecycleState>
179
- ghostpaw-affinity contact merge [flags]
248
+ ghostpaw-affinity contact create|revise|lifecycle|export|delete|merge
180
249
  ghostpaw-affinity identity add|revise|verify|remove [flags]
181
250
  ghostpaw-affinity relationship add|bond|state|tie|untie [flags]
182
251
  ghostpaw-affinity commitment record|resolve [flags]
@@ -187,44 +256,50 @@ ghostpaw-affinity duplicate dismiss|undismiss [flags]
187
256
  ghostpaw-affinity mcp|skill|tools|describe|call|completions|version|help
188
257
  ```
189
258
 
190
- There are 27 domain commands. `review` accepts the existing view names,
259
+ There are 29 domain commands. `review` accepts the existing view names,
191
260
  including `contacts.list`, `contacts.duplicates` and `dates.upcoming`.
192
261
  `show` selects an inspection kind; contact and link locators are JSON objects.
193
- Use `help contact` or `contact create --help` for schema-derived help.
194
- Nested payloads use JSON or `@path` to read a file.
262
+ Use `help contact` or `contact create --help` for schema-derived help; a
263
+ mistyped command suggests the closest one. Nested payloads use JSON or `@path`
264
+ to read a file; repeated array flags accept JSON objects
265
+ (`--entries '{"name":"a","value":"x"}'`) or one JSON array.
266
+
267
+ Every time field accepts epoch milliseconds, ISO 8601 with `Z` or an offset,
268
+ `YYYY-MM-DD`, `DD.MM.YYYY` (CLI), `today`, `tomorrow`, `yesterday` and signed day offsets
269
+ such as `+3d` or `-2d`. On the CLI, date-only values use local time (midnight,
270
+ or end of day for `dueAt`); through MCP and the tool facade they use UTC.
195
271
 
196
272
  Global flags: `--db <path>`, `--json`, `--quiet`, `--compact`,
197
273
  `--help`/`-h`, `--version`/`-V`/`-v`, `--no-color`.
198
- `NO_COLOR` is accepted; output uses no terminal colors.
199
- Noun-verb commands print the full tool result as JSON with `--json` or piped
200
- stdout. Terminal output shows the summary and payload. `--quiet` suppresses
201
- stdout. `--compact` removes JSON indentation.
202
- Array flags repeat; kebab-case flags map to schema properties.
203
- `--` ends flags. A positional `-`, or piped stdin with no input flags, reads a
204
- JSON object. Explicit flags override stdin fields.
274
+ `NO_COLOR` is accepted. In a terminal, commands print a readable summary with
275
+ names and dates. With `--json` or piped stdout they print the tool result as
276
+ JSON with ISO date siblings and floats rounded to three decimals; `--compact`
277
+ removes indentation and empty receipt arrays. `--quiet` suppresses stdout.
278
+ Writes list what changed in `data.changes`, and creates warn about likely
279
+ duplicates. Kebab-case flags map to schema properties. `--` ends flags.
280
+ A positional `-`, or piped stdin when no other arguments are given, reads a
281
+ JSON object (`echo '{"name":"Sam","kind":"human"}' | ghostpaw-affinity contact create`).
282
+ Explicit flags override stdin fields.
205
283
  Database selection uses `--db`, `GHOSTPAW_AFFINITY_DB`, then
206
- `~/.ghostpaw/affinity.db`. These commands work offline.
284
+ `~/.ghostpaw/affinity.db`; relative paths resolve against the current
285
+ directory, and `--help` shows the resolved path. A new database is reported on
286
+ stderr. These commands work offline.
207
287
 
208
- | Exit | Noun-verb result |
288
+ | Exit | Result |
209
289
  |---|---|
210
290
  | 0 | Success, including no_op |
211
- | 1 | Tool error |
212
- | 2 | Usage or schema error |
291
+ | 1 | Other tool error |
292
+ | 2 | Usage, schema or invalid input |
213
293
  | 3 | Clarification needed or not found |
214
- | 4 | Conflict or version mismatch |
294
+ | 4 | Conflict, already resolved or version mismatch |
215
295
  | 70 | Internal error |
216
296
 
217
297
  Errors go to stderr. With `--json`, errors also print to stdout.
218
- Legacy `tools [--json]`, `describe <tool>`, `call <tool> [JSON|-]` and
219
- `<tool_name> --parameter value` retain their output and exit codes.
298
+ `--version` names the variant: `affinity 0.5.0 (binary, linux-x64)`,
299
+ `(npm)` or `(library)`. Legacy `tools [--json]`, `describe <tool>`,
300
+ `call <tool> [JSON|-]` and `<tool_name> --parameter value` remain available.
220
301
  `completions bash|zsh|fish` prints shell scripts.
221
302
 
222
- ```sh
223
- ghostpaw-affinity contact create '{"name":"Sam","kind":"human"}' --db /tmp/affinity-example.db --json
224
- ghostpaw-affinity search Sam --db /tmp/affinity-example.db --json
225
- ghostpaw-affinity review contacts.list --db /tmp/affinity-example.db --json
226
- ```
227
-
228
303
  ## Quick Start
229
304
 
230
305
  ```ts