npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

aizo-node

v0.4.0

Published

爱憎 — preference memory for AI agents: extract, decay, and recall user likes and dislikes

Readme

aizo 爱憎

中文文档

aizo (爱憎, ài zēng, "love and hate") is a lightweight, high-performance preference memory system for AI agents, built entirely in Rust.

It mimics human cognitive memory: rather than storing full conversation transcripts, it continuously extracts, quantifies, decays, and recalls a user's stable preferences, aversions, habits, communication styles, and hard limits from interaction history. The result is a compact, numerically-weighted personality profile that any agent can query in milliseconds.


How it fits together

aizo is designed for two complementary usage loops:

╔══════════════════════════════════════════════════════════════════════╗
║  1. In-session  (reactive — detects specific emotions in real time)  ║
╚══════════════════════════════════════════════════════════════════════╝

   user ──► Claude Code ─────── aizo add ──────────────────┐
                                                           ▼
                             CLAUDE.md ◄── contributes ── local SQLite
                                                      (user preference)


╔══════════════════════════════════════════════════════════════════════╗
║  2. Background  (cron task — batch-analyzes accumulated sessions)    ║
╚══════════════════════════════════════════════════════════════════════╝

   user ──► openclaw ──► sessions ─── aizo analyze ─────────┐
                                                            ▼
   USER.md, SOUL.md, IDENTITY.md … ◄── contributes ── local SQLite
                                                      (user preference)

Loop 1 — In-session: the agent detects a strong preference signal mid-conversation (praise, complaint, explicit rule) and calls aizo add immediately. The updated SQLite profile is then injected into CLAUDE.md (or equivalent context file) so the next session starts with the latest understanding of the user.

Loop 2 — Background: other agents (openclaw, etc.) accumulate session transcripts over time. A scheduled cron job runs aizo analyze to extract implicit preferences the reactive loop may have missed. The enriched profile is then written into richer identity files — USER.md, SOUL.md, IDENTITY.md — that build a persistent, evolving picture of the user across all agents and tools.

The two loops reinforce each other: reactive writes give immediate recall accuracy; batch analysis fills in the gaps and stabilises scores over time.


Core design

session transcript
       │
       ▼
  flash LLM (claude-haiku-4-5)
       │  semantic extraction
       ▼
  structured entries  { category, item, base_score 0–10 }
       │  smooth merge
       ▼
  SQLite (~/.aizo/preferences.db)
       │
       ▼
  effective_weight = s · d(t)^α   (score-modulated decay)
       │  keyword or top-N recall
       ▼
  agent reads profile → personalizes response

Scoring formula

All scoring logic lives in src/scoring/mod.rs. Every preference entry carries three computed fields, derived at read time from its base_score and last_seen timestamp.

Step 1 — Decay coefficient $d(t)$

$$d(t) = \phi + (1 - \phi) \cdot e^{-\lambda t}, \quad \lambda = \frac{\ln 2}{t_{1/2}}$$

where $t$ is days since last_seen, $t_{1/2}$ is the configured half-life, and $\phi$ is the floor.

Step 2 — Score-dependent exponent $\alpha$

$$\alpha = \frac{10 - s}{10}$$

Higher score → smaller $\alpha$ → decay has less effect. A score-10 preference ($\alpha = 0$) is fully decay-resistant; a score-0 entry ($\alpha = 1$) decays at full speed.

Step 3 — Effective weight $w$

$$w = s \cdot d(t)^{\alpha}$$

Expanding into a single expression:

$$\boxed{w = s \cdot \left[\phi + (1-\phi) \cdot e^{-\lambda t}\right]^{\frac{10-s}{10}}}$$

Boundary behaviour

| Score $s$ | $\alpha$ | Decay effect | Interpretation | |---|---|---|---| | 10 | 0.0 | None — $d^0 = 1$ | Core value, never fades | | 7 | 0.3 | Slight | Strong preference, slow fade | | 5 | 0.5 | Moderate | Neutral habit, fades at half speed | | 1 | 0.9 | Near-full | Weak aversion, fades quickly | | 0 | 1.0 | Full | $w = 0$ always — absolute zero |

Entries are never hard-deleted by decay — they sink toward the floor and persist as weak long-term memory. Use --type taboo to surface them explicitly regardless of effective weight.

Scoring scale (0–10)

| Score | Meaning | |---|---| | 0 | Absolute taboo / hard rejection | | 1–3 | Clear dislike / aversion | | 4–6 | Neutral tendency / weak pattern | | 7–9 | Clear preference | | 10 | Strong, consistent, high-priority love |

Score smoothing

When the same entry is seen again across sessions:

new_base_score = old_base_score × 0.4 + incoming_score × 0.6

last_seen is always refreshed, which resets the decay clock.


Installation

From source (Rust ≥ 1.70)

git clone https://github.com/mmmarcinho/aizo
cd aizo
cargo build --release
cp target/release/aizo /usr/local/bin/aizo
export ANTHROPIC_API_KEY=sk-ant-...   # required for 'analyze'

CLI reference

aizo [--db <path>] <COMMAND>

| Command | Description | |---|---| | analyze [file] | Analyze session file or JSON export with flash LLM | | recall [query] [--type …] [--limit N] [--scenario …] | Keyword + score-range recall — primary agent call | | top [N] [--type …] | Top-N entries by effective weight (default 10) | | show | Full profile sorted by effective weight | | add <item> <reason> [--score N] | Manually add or update a preference | | tag <item> <keywords…> | Add or replace keywords on an existing entry | | touch <item…> | Reset decay clock without changing score | | remove <item…> | Hard-remove an entry | | keywords | List all stored keywords with entry counts | | clear | Wipe entire profile and session history | | info | DB path, score distribution, decay settings | | config show | Print decay configuration | | config set-half-life <days> | Set decay half-life | | config set-floor <0.0–1.0> | Set minimum decay floor |

Score guide

There is no category field. The base_score is the only dimension that matters:

| Score | Meaning | --type alias | |---|---|---| | 0–1.5 | Hard limit / must never do | taboo | | 1.6–4 | Clear dislike | aversion | | 4–6.5 | Neutral habit or weak pattern | habit | | 6.5–10 | Style / communication preference | style | | 7–10 | Clear preference | preference |

Use --type on recall and top to filter by score range. Comma-separate for multi-type:

aizo recall code --type preference,habit,style,taboo
aizo recall --type taboo               # all hard limits, no keyword needed
aizo top 5 --type preference

Use keywords (--keywords on add, or aizo tag) to add any taxonomy you want.

Examples

# Analyze a session log
aizo analyze ./chat.txt
cat conversation.md | aizo analyze

# Agent recalls preferences before generating
aizo top 5
aizo recall "code style"

# Scenario-aware recall for coding tasks (expands to ~10 coding keywords)
aizo recall --scenario coding --type preference,style,habit,taboo --limit 20

# Type-only recall (no keyword — returns all entries in that score range)
aizo recall --type taboo                        # all hard limits
aizo recall code --type preference --limit 10   # top coding preferences
aizo recall code --type preference,habit --limit 20  # multiple types

# Inspect full profile
aizo show

# Manual entries — score encodes sentiment
aizo add "concise code"     "Always asks for shorter implementations"  --score 9.0
aizo add "verbose comments" "Complained about over-documented code"    --score 1.5
aizo add "emojis in output" "Explicitly said never use emojis"         --score 0.5
aizo add "uses dark mode"   "Mentioned dark theme in every UI session" --score 5.0
aizo add "terse naming"     "Consistently chose short variable names"  --score 8.0

# Add or manage keywords for richer recall
aizo tag "concise code" brevity minimal short lean
aizo tag "verbose comments" verbosity docs comments over-engineering

# Tune decay (default: half-life 30d, floor 0.1)
aizo config set-half-life 14
aizo config set-floor 0.05

# Stats
aizo info

Entry format

{
  "id": 1,
  "item": "concise code",
  "reason": "Always asks for shorter implementations with no fluff.",
  "keywords": ["brevity", "minimal", "short", "lean"],
  "base_score": 9.0,
  "source": "analysis",
  "added_at": "2026-05-07T14:00:00+00:00",
  "last_seen": "2026-05-07T15:30:00+00:00",
  "score_exponent": 0.1,
  "decay_coefficient": 0.87,
  "effective_weight": 7.83
}

Database schema

CREATE TABLE preferences (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    item        TEXT    NOT NULL,
    reason      TEXT    NOT NULL,
    keywords    TEXT    NOT NULL DEFAULT '',    -- comma-separated synonym tags
    base_score  REAL    NOT NULL DEFAULT 5.0,   -- 0-10
    source      TEXT    NOT NULL DEFAULT 'manual',
    added_at    TEXT    NOT NULL,
    last_seen   TEXT    NOT NULL                -- resets decay clock on each reinforcement
);
-- UNIQUE on LOWER(item)

CREATE TABLE decay_config (
    id              INTEGER PRIMARY KEY CHECK(id = 1),
    half_life_days  REAL    NOT NULL DEFAULT 30.0,
    floor           REAL    NOT NULL DEFAULT 0.1
);

CREATE TABLE sessions (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    analyzed_at TEXT    NOT NULL,
    extracted   INTEGER NOT NULL DEFAULT 0
);

Agent integration

Any agent can call aizo as a subprocess — no embedding, no vector index, no runtime:

import subprocess, json

def top_preferences(n: int = 10) -> list[dict]:
    return json.loads(subprocess.check_output(["aizo", "top", str(n), "--json"]))

def recall(query: str) -> list[dict]:
    return json.loads(subprocess.check_output(["aizo", "recall", query, "--json"]))

# Inject into system prompt before generating
prefs = top_preferences(10)
system = f"User preferences:\n{json.dumps(prefs, indent=2)}\n\n{base_system}"

Or configure AIZO_DB_PATH per-project to maintain separate profiles:

export AIZO_DB_PATH=./project-prefs.db
aizo show

Standard Operating Procedure (SOP)

The SOP for how an agent should use aizo is defined as a skill file at skills/aizo-sop.md. Copy it into your agent's skill/instruction directory (e.g. .claude/skills/ for Claude Code) and any agent in that project will automatically follow the protocol.

The skill defines six triggers:

| # | Trigger | aizo call | Timing | |---|---|---|---| | 1 | Session starts | aizo top 20 → format as prose header | Sync, before first reply | | 2 | User shows negative feedback | aizo add … --score 1.5 then aizo recall <topic> | Sync, before corrected reply | | 3 | User praises something | aizo add … --score 9.0 | Async, after reply sent | | 4 | User states an explicit rule | aizo add … --score 0.5 or --score 10 | Sync, immediate | | 5 | About to generate on topic X | aizo recall <X> | Sync, before generation | | 6 | Session ends | aizo analyze <transcript> | Async, background | | 7 | Daily cron job | Agent LLM scans logs → aizo touch confirmed items | Scheduled, background |

Key rules encoded in the skill:

  • Taboos always win over preferences in conflicts
  • analyze is for full sessions, not single messages — it calls an LLM
  • Silence (recall returning nothing) means no data, not neutral preference
  • Never mention aizo to the user — it runs silently

Development

cargo build
cargo build --release
cargo test

License

MIT