New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

@ghostpaw/affinity

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ghostpaw/affinity

Relationship intelligence and social CRM model for Node.js — SQLite, zero dependencies, with a built-in LLM tool facade

Source
npmnpm
Version
0.2.1
Version published
Weekly downloads
0
Maintainers
1
Weekly downloads
 
Created
Source

@ghostpaw/affinity

npm node license dependencies TypeScript

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.

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:

ConceptPurpose
ContactAny tracked entity: person, company, team, service, pet, household, or group
IdentityExact recognition and routing handle such as email, phone, URL, or account id
Social LinkA live relationship track with Rank, Affinity, Trust, cadence, Bond, and state
TieA structural fact such as works_at, belongs_to, reports_to, or kinship
Journal EntryRecorded evidence: interaction, observation, milestone, transaction, or commitment
Date AnchorA recurring yearly date such as a birthday, anniversary, renewal, or memorial
AttributeFlexible metadata and preference layer for contacts and links
Affinity ChartDerived graph view of the active relationship network

The model means each kind of truth has its own home:

What it looks likeWhat it actually is
A person, company, team, service, or householdA Contact
An email address or handleAn Identity
A friendship or business relationship that changes over timeA Social Link
Employment, hierarchy, family, or membershipA 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

Eleven tools shaped around operator intent, not raw storage operations:

ToolWhat it does
search_affinitySearch contacts by natural key or name
review_affinityDashboard-style list and graph review views
inspect_affinity_itemOpen one exact profile or link detail
manage_contactCreate, revise, or change contact lifecycle
merge_contactsMerge duplicate contacts safely
manage_identityAdd, revise, verify, or remove identities
manage_relationshipSeed social links, revise bond/state, manage structural ties
record_eventRecord direct evidence, observations, milestones, or transactions
manage_commitmentRecord or resolve obligations
manage_date_anchorAdd, revise, or remove recurring important dates
manage_attributeSet, 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. soul for posture, tools for actions, skills for workflow guidance.
  • Colocated tests. Every non-type module has a colocated .test.ts file. 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

DocumentAudience
HUMAN.mdHuman developers using the low-level read / write API
LLM.mdAgent builders wiring soul, tools, and skills into LLM systems
docs/README.mdArchitecture overview: model, invariants, mechanics, and source layout
docs/entities/Per-concept manuals with exact inlined public API listings
docs/USECASES.mdLong-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:

GitHub Sponsors

Anonyfox • MIT License

Keywords

affinity

FAQs

Package last updated on 30 Mar 2026

Related posts