GhostPaw Affinity
Local relationship model and social CRM for contacts, relationships, evidence, and commitments.
التثبيت
أضف هذا إلى إعدادات MCP في عميلك (Claude Desktop: claude_desktop_config.json، وCursor: .cursor/mcp.json، ويستخدم VS Code وغيره الصيغة نفسها «mcpServers»).
@ghostpaw/affinityclaude mcp add ghostpaw-affinity -e 'GHOSTPAW_AFFINITY_DB=<GHOSTPAW_AFFINITY_DB>' -- npx -y @ghostpaw/affinity@0.4.0 mcp
{
"mcpServers": {
"ghostpaw-affinity": {
"command": "npx",
"args": [
"-y",
"@ghostpaw/affinity@0.4.0",
"mcp"
],
"env": {
"GHOSTPAW_AFFINITY_DB": "<GHOSTPAW_AFFINITY_DB>"
}
}
}
}
متغيرات البيئة
GHOSTPAW_AFFINITY_DBSQLite database path (default: ~/.ghostpaw/affinity.db)
التوثيق
مأخوذ من ملف README للمشروع على GitHub ويُحدَّث أسبوعيًا. تفتح الروابط على GitHub.
المحتويات
@ghostpaw/affinity
A standalone social CRM core for Node.js, built on SQLite.
Affinity treats contacts, identities, relationship mechanics, structural ties,
journal evidence, commitments, recurring dates, attributes, and graph review as
one coherent model instead of separate systems. It ships as a single prebundled
blob with zero runtime dependencies, designed for two audiences at once: human
developers working directly in code, and LLM agents operating through a
structured soul / tools / skills runtime.
MCP server
Every client below starts the same stdio server: npx -y @ghostpaw/affinity mcp.
Contacts live in ~/.ghostpaw/affinity.db unless the GHOSTPAW_AFFINITY_DB
environment variable (absolute path) or --db <path> says otherwise.
Claude Code
claude mcp add ghostpaw-affinity -- npx -y @ghostpaw/affinity mcp
or as a plugin, which also installs the skill:
/plugin marketplace add GhostPawJS/affinity
/plugin install ghostpaw-affinity@ghostpaw-affinity
Codex CLI (~/.affinity/config.toml)
[mcp_servers.ghostpaw-affinity]
command = "npx"
args = ["-y", "@ghostpaw/affinity", "mcp"]
Cursor (.cursor/mcp.json), Claude Desktop (claude_desktop_config.json)
or a project .mcp.json:
{
"mcpServers": {
"ghostpaw-affinity": {
"command": "npx",
"args": ["-y", "@ghostpaw/affinity", "mcp"]
}
}
}
Claude Desktop users can also install server.mcpb from the
latest GitHub release.
A Dockerfile is included for container hosts:
docker build -t ghostpaw-affinity . && docker run -i --rm -v affinity:/data ghostpaw-affinity.
The server speaks MCP 2026-07-28 (stateless, server/discover) and the
initialize-based revisions 2025-11-25, 2025-06-18, 2025-03-26 and 2024-11-05.
CLI
npx -y @ghostpaw/affinity tools
npx -y @ghostpaw/affinity call manage_contact '{"action":"create","input":{"name":"Sam","kind":"human"}}'
npx -y @ghostpaw/affinity call search_affinity '{"query":"Sam"}'
Install globally for the ghostpaw-affinity binary: npm i -g @ghostpaw/affinity.
ghostpaw-affinity mcp starts the stdio server.
Agent Skill
SKILL.md (repo root) and skills/affinity/SKILL.md follow the
Agent Skills format and ship in the npm package.
Copy skills/affinity/ into your agent's skills folder, or print it:
npx -y @ghostpaw/affinity skill > SKILL.md
Install
npm install @ghostpaw/affinity
Requires Node.js 24+ (uses the built-in node:sqlite module).
Quick Start
import { DatabaseSync } from "node:sqlite";
import { initAffinityTables, read, write } from "@ghostpaw/affinity";
const db = new DatabaseSync(":memory:");
db.exec("PRAGMA foreign_keys = ON");
initAffinityTables(db);
const { primary: owner } = write.createContact(db, {
name: "Mika",
kind: "human",
bootstrapOwner: true,
});
const { primary: ada } = write.createContact(db, {
name: "Ada Lovelace",
kind: "human",
});
write.addIdentity(db, ada.id, {
type: "email",
value: "ada@example.com",
});
write.recordInteraction(db, {
type: "conversation",
occurredAt: Date.now(),
summary: "Coffee together",
significance: 6,
participants: [
{ contactId: owner.id, role: "actor", directionality: "mutual" },
{ contactId: ada.id, role: "recipient", directionality: "mutual" },
],
});
const profile = read.getContactProfile(db, ada.id);
const radar = read.listRadar(db);
The Model
Eight concepts, strict separation of concerns:
| Concept | Purpose |
|---|---|
| Contact | Any tracked entity: person, company, team, service, pet, household, or group |
| Identity | Exact recognition and routing handle such as email, phone, URL, or account id |
| Social Link | A live relationship track with Rank, Affinity, Trust, cadence, Bond, and state |
| Tie | A structural fact such as works_at, belongs_to, reports_to, or kinship |
| Journal Entry | Recorded evidence: interaction, observation, milestone, transaction, or commitment |
| Date Anchor | A recurring yearly date such as a birthday, anniversary, renewal, or memorial |
| Attribute | Flexible metadata and preference layer for contacts and links |
| Affinity Chart | Derived graph view of the active relationship network |
The model means each kind of truth has its own home:
| What it looks like | What it actually is |
|---|---|
| A person, company, team, service, or household | A Contact |
| An email address or handle | An Identity |
| A friendship or business relationship that changes over time | A Social Link |
| Employment, hierarchy, family, or membership | A Tie |
| “We talked yesterday” | A Journal entry |
| “I promised to send the recap” | A commitment-shaped Journal entry |
| “Their birthday is important every year” | A Date Anchor |
State is derived, not hand-toggled. Rank, hidden Affinity, Trust movement, Moments, drift, readiness, and graph bridge significance are computed from evidence and explicit structural truth, not caller-written status flags.
Two Audiences
Human developers
Use the read and write namespaces for direct-code access to the domain:
import { read, write } from "@ghostpaw/affinity";
write.createContact(db, { name: "Ada", kind: "human" });
write.addIdentity(db, contactId, { type: "email", value: "ada@example.com" });
write.recordInteraction(db, {
type: "support",
occurredAt: now,
summary: "Helped prepare for a difficult meeting",
significance: 7,
participants: [
{ contactId: ownerId, role: "actor", directionality: "mutual" },
{ contactId, role: "recipient", directionality: "mutual" },
],
});
const profile = read.getContactProfile(db, contactId);
const radar = read.listRadar(db);
See HUMAN.md for the full direct-code guide with modeling boundaries and worked examples.
LLM agents
Use the tools, skills, and soul namespaces for a structured runtime
surface designed to minimize LLM cognitive load:
import { tools, skills, soul } from "@ghostpaw/affinity";
const allTools = tools.affinityTools;
const searchTool = tools.getAffinityToolByName("search_affinity")!;
const result = searchTool.handler(db, { query: "email:ada@example.com" });
const allSkills = skills.affinitySkills;
const prompt = soul.renderAffinitySoulPromptFoundation();
Every tool returns a discriminated result with outcome: "success" | "no_op" |
"needs_clarification" | "error", structured entities, next-step hints, and
actionable recovery signals.
See LLM.md for the full AI-facing guide covering soul, tools, and skills.
Tools
Twelve tools shaped around operator intent, not raw storage operations:
| Tool | What it does |
|---|---|
search_affinity | Search contacts by natural key or name |
review_affinity | Dashboard-style list and graph review views |
inspect_affinity_item | Open one exact profile or link detail |
manage_contact | Create, revise, or change contact lifecycle |
merge_contacts | Merge duplicate contacts safely |
manage_duplicate_dismissal | Dismiss or restore a suspected duplicate pair |
manage_identity | Add, revise, verify, or remove identities |
manage_relationship | Seed social links, revise bond/state, manage structural ties |
record_event | Record direct evidence, observations, milestones, or transactions |
manage_commitment | Record or resolve obligations |
manage_date_anchor | Add, revise, or remove recurring important dates |
manage_attribute | Set, unset, or replace contact/link metadata |
Each tool exports runtime metadata, JSON-Schema-compatible inputs, and structured outputs so harnesses can wire them without parsing vague prose.
Key Properties
- Zero runtime dependencies. Only
node:sqlite(built into Node 24+). - Single prebundled blob. One ESM + one CJS entry in
dist/. No subpath exports, no code splitting. - Pure SQLite storage. CHECK-constrained state, trigger-maintained support
tables, and deterministic derived reads. Bring your own
DatabaseSync. - Derived mechanics. Rank, hidden Affinity, Trust, cadence, Moments, Radar, and bridge significance are computed from evidence and structure, never directly caller-set.
- Intention-shaped writes.
createContact,setStructuralTie,recordInteraction,recordCommitment,addDateAnchor,mergeContacts: operations that say what happened or what truth changed, not generic CRUD. - Additive AI runtime.
soulfor posture,toolsfor actions,skillsfor workflow guidance. - Colocated tests. Every non-type module has a colocated
.test.tsfile. The documented behavior is backed by executable coverage.
Package Surface
import {
initAffinityTables, // schema setup
read, // all query functions
write, // all mutation functions
tools, // LLM tool definitions + registry
skills, // LLM workflow skills + registry
soul, // thinking foundation for system prompts
} from "@ghostpaw/affinity";
All domain and runtime types are also available at the root for TypeScript consumers:
import type {
AffinityDb,
ContactKind,
LinkState,
ContactProfileRecord,
AffinityChartRecord,
AffinityToolDefinition,
AffinitySkill,
AffinitySoul,
} from "@ghostpaw/affinity";
Documentation
| Document | Audience |
|---|---|
| HUMAN.md | Human developers using the low-level read / write API |
| LLM.md | Agent builders wiring soul, tools, and skills into LLM systems |
| docs/README.md | Architecture overview: model, invariants, mechanics, and source layout |
| docs/entities/ | Per-concept manuals with exact inlined public API listings |
| docs/USECASES.md | Long-form lifecycle narratives across personal, business, and AI-memory angles |
Development
npm install
npm test # node:test runner
npm run typecheck # tsc --noEmit
npm run lint # biome check
npm run build # ESM + CJS + declarations via tsup
The repo is pinned to Node 24.14.0 via .nvmrc / .node-version /
.tool-versions / mise.toml / Volta. Use whichever version manager you
prefer.
Support
If this package helps your project, consider sponsoring its maintenance:
الأسئلة الشائعة
ما هو GhostPaw Affinity؟
Local relationship model and social CRM for contacts, relationships, evidence, and commitments.
كيف أثبّت GhostPaw Affinity؟
يعمل على جهازك. في Claude Code: claude mcp add ghostpaw-affinity -e 'GHOSTPAW_AFFINITY_DB=<GHOSTPAW_AFFINITY_DB>' -- npx -y @ghostpaw/affinity@0.4.0 mcp. وفي العملاء الآخرين، الصق إعداد JSON من هذه الصفحة في إعدادات MCP الخاصة بهم.
هل يحتاج GhostPaw Affinity إلى مفتاح API؟
لا يذكر إدراجه في السجل أي مفتاح أو سر إلزامي. قد تتطلب بعض الميزات حسابًا لدى الخدمة التي يتصل بها.
هل GhostPaw Affinity مفتوح المصدر؟
نعم. شيفرته متاحة على GitHub بترخيص MIT.
من يصون GhostPaw Affinity؟
ينشره GhostPawJS. يدرجه AI.tn لكنه لا يصونه ولا يوصي به.
من سجل MCP الرسمي. الإدراج ليس توصية: راجع شيفرة الخادم وصلاحياته قبل منحه الوصول إلى بياناتك.