Skip to main content
Glama

Hivelore is the enforcement layer inside an AI coding-agent harness. It briefs agents with the team's non-obvious knowledge before they act, then turns each hard-won lesson into a deterministic gate — in MCP, Git hooks, and CI — that blocks the change about to repeat it. Same diff, same verdict, on every machine. Memory is the substrate; the gate is the product.

A capable model already knows generic best practice. What it cannot guess is your team's arbitrary, repo-specific knowledge: that public ids are id + 100000 prefixed AC-, that the status field must be "OK"/"KO", that you never edit an applied migration. Left to itself, a confident agent invents a plausible answer - clean, tested, green, and wrong by policy. Hivelore carries that unguessable knowledge into the task and blocks the change that's about to violate it.

Hivelore's job is not to replace tests, linters, or observability. It makes the repo-specific knowledge those tools cannot infer available, auditable, and enforceable.

npm License Node CI


The problem

AI coding agents are powerful, but they often act with incomplete repo context. Compaction, parallel sessions, agent switches, and stale advisory docs all create the same failure mode: the agent changes code without carrying the team's current decisions into the work.

Most teams work around this with instructions and hope:

  • "Please read our architecture decisions first."

  • "Don't repeat the migration mistake from last sprint."

  • "Remember to capture what you learned."

  • "Don't merge code that invalidates a team decision."

Those rules are easy to skip. Hivelore turns them into repo-native context policy.


Related MCP server: MCP Memory Server

How it works

AI agent ──▶ Hivelore briefing ──▶ code change ──▶ Hivelore policy gate ──▶ merge
                  ▲                                       │
                  └── context breadcrumbs · decisions · gotchas · anchors
  1. hivelore init creates a .ai/ context policy layer in your repo.

  2. Agents start every session with get_briefing — one MCP call that returns small default context plus deeper breadcrumbs ranked by task relevance.

  3. Decisions, gotchas, failed attempts, and session recaps live as Markdown files anchored to the code paths they describe. When code moves, Hivelore detects stale anchors.

  4. hivelore enforce check and CI enforcement block unsafe states: missing briefing, stale critical decisions, an anchored anti-pattern your diff is about to repeat, or uncaptured session knowledge.

Memory is the substrate. Context enforcement is the product promise. AI changes should not enter the codebase without consulting the team's current knowledge.

For the changes prompted by the September 18 client reports, including evidence checks, quieter briefings and completion scoped to a task, see the implementation notes.

Where Hivelore fits in the harness

Harness engineering is about the environment around the model: feedforward guidance before it acts, feedback sensors after it acts, and workflow gates that keep bad states from landing. Hivelore owns the repo-specific context policy part of that harness.

Harness concern

Hivelore role

Feedforward guidance

get_briefing, module context, skills, decisions, gotchas, failed attempts

Feedback and gates

MCP ordering policy, pre_commit_check, Git hooks, CI enforcement, stale-anchor detection

Knowledge lifecycle

Git-native Markdown records, path/symbol anchors, confidence, retirement, linting

Boundaries

Hivelore complements unit/e2e tests, type checks, runtime traces, security scanners, and LLM evals; it does not try to replace them

The narrow positioning is intentional: Hivelore is not a general memory database or an agent dashboard. It is the control layer that helps coding agents act with the validated, non-obvious knowledge of the team.

Scope & boundaries — the three harnesses

Harness engineering regulates three different things about agent-written code. Hivelore deliberately covers two of them and treats the third as out of scope, for now.

Harness dimension

Question it answers

Hivelore today

Maintainability

Is the code clean? (patterns, footguns, conventions)

✅ Covered — executable sensors + anti-pattern gate

Architecture fitness

Does it respect the team's structural decisions?

🟡 Partly — anchored decision/architecture memories + decision-coverage gate

Behaviour

Does the code do the functionally correct thing?

🟡 Bridged — command sensors route your own tests to lessons (see below)

Why no behaviour harness yet. Verifying functional correctness needs an oracle — an independent source of truth for what the code should do — and that oracle problem (plus the trap of an agent grading its own work) is the least-mature part of the field. That territory belongs to your tests, property-based checks, and LLM-evals; Hivelore does not try to replace them. What Hivelore does do is carry the unguessable intent a behaviour test would otherwise have to encode (status must be OK/KO, public ids = id + 100000) as feedforward context and deterministic sensors — a partial, static slice of behaviour control, not a runtime functional oracle.

The bridge exists (v0.33.0): command sensors. A lesson can carry a command instead of a regex — your own test or invariant script. When a diff touches the sensor's paths, the gate executes it and a non-zero exit refuses the commit with the lesson as the message. Hivelore does not invent the oracle (the unsolved problem); it routes the oracle your team already owns to the lesson it protects:

hivelore memory tried \
  --what "refund exceeded the captured amount" \
  --why-failed "prod incident #442 — refunds must clamp to capture" \
  --paths src/payments/ \
  --sensor-command "npx vitest run tests/payments/refund-invariants.spec.ts"
# → validated (the oracle must PASS on the current tree), then enforced at commit + CI
#   Saved team-scoped by default: an enforced lesson must travel to every machine and CI.

Rules that keep it honest: opt-in per repo (enforcement.runCommandSensors: true — it executes repo-authored commands), a proposal whose oracle fails on the presumed-correct tree is rejected, an oracle that is still a pending stub cannot arm a block sensor, and an unrunnable command (not found, timeout) warns but never blocks — a broken harness must not masquerade as a failing test. Commands run with a scrubbed environment (test-runner basics only — no cloud credentials or tokens). And you can make the guarantee demonstrable: --red-ref <pre-fix-commit> replays the incident in a scratch worktree and requires the oracle to FAIL there — the sensor then records red_proven: true, shown in the prevention receipt. A crash is not a RED: if the oracle errors before reaching its assertion on the incident state (the guarded code doesn't exist yet, an import or syntax error, "no tests found"), the replay reports red-unrunnable and refuses to claim proof. Full behaviour verification (test generation, LLM evals) remains your test suite's job.

Since v0.43.0, prove-RED is mandatory for a blocking shell/test sensor: an oracle without a reproducible incident state remains warn. CI can also set commandSensorUnrunnable: "block" so a missing required oracle fails as a broken harness, and sensorWeakeningGate: "block" so protection cannot be silently demoted or removed.

The on-ramp (v0.36.0): scaffold the test from the incident. A command sensor needs a test to route — so Hivelore generates the skeleton from the lesson. hivelore sensors scaffold <memory-id> (or the scaffold_test MCP tool, so agents do it in-session) detects your test framework (vitest / jest / pytest / go), writes a pending test carrying the incident's provenance in its header, and prints the exact sensors propose --kind test line to arm it. It never arms a sensor itself (propose_sensor stays the sole validated writer); the stub stays pending so the suite is green until you write the assertion. In a monorepo, the framework and location come from the package that owns the lesson's anchor paths (a lesson under packages/api/ scaffolds into packages/api/tests/…), not the repo root — and a lesson that spans several packages scaffolds one pending test per owning package, all armed by a single sensor whose oracle chains their run commands. A scaffold left pending or never armed is an open loop: doctor and enforce finish nudge it (post-incident-test-unarmed) until the oracle is routed.

Pass the incident and the stub writes itself around the fix (v0.46.0). Add --red-ref <pre-fix-commit> and the scaffold names the symbols the fix (red_ref..HEAD) actually touched and pre-fills the example around them — import { refund } …, expect(refund(/* incident input */)).toBe(/* post-fix expected */) instead of a blank subjectUnderTest(). It stays a pending, commented stub (no live import, suite stays green) — a deterministic head-start, never an LLM guessing your assertion.

hivelore sensors scaffold 2026-07-03-attempt-refund-exceeds-capture --red-ref <pre-fix-commit>
# → tests/incidents/refund-exceeds-capture.test.ts (pending; names the touched symbols from the fix)
#   then: fill the assertion → run it → arm it with the printed propose command.

Lower the cost of expressing the invariant (v0.48.0): --style. The behaviour harness leaves the oracle to you — so the scaffold offers the two deterministic ways to make that cheaper (no LLM guessing your assertion):

  • --style property — a fast-check / Hypothesis skeleton: state the invariant once (refund(a, b) ≤ b) and it is checked over many generated inputs.

  • --style differential --reference <impl> — state no invariant at all: assert the subject agrees with a reference implementation (a legacy version, a second impl) for all generated inputs.

hivelore sensors scaffold <lesson> --red-ref <pre-fix-commit> --style property
hivelore sensors scaffold <lesson> --style differential --reference ../legacy/refund

Both stay pending, commented stubs (the suite stays green) and arm through the same validated prove-RED path once you fill them in.

Measure the behaviour harness (v0.45.0). hivelore doctor reports, per main code area, how much of the behaviour surface is guarded: Behaviour harness: X/N area(s) guarded by a behavioural oracle (K armed, P red-proven) — so the branch's progress is visible, not guesswork. The human stats receipt prints the same line as a footer. Since v0.47.0 the finding closes the loop to action: for each uncovered area it prints the exact hivelore sensors scaffold <lesson> --red-ref <pre-fix-commit> command in its Suggested commands (or a memory tried … then scaffold line when no lesson exists yet).

See STABILITY.md for the frozen 1.0 surface and CONTRIBUTING.md to extend Hivelore.

Executable memory sensors

Some gotcha and attempt memories can now carry a sensor block: a deterministic guardrail that scans the diff. Three shapes, one validation doctrine (silent on correct code, fires on the mistake):

  • regex — matched on added lines; the simple, dependency-free default.

  • ast — an ast-grep structural pattern (stripe.paymentIntents.create($$$) with absent: idempotencyKey): comments and string literals can never false-positive, and "X without Y" is expressed on the call itself. Needs the optional @ast-grep/napi engine — without it the sensor is unrunnable (warn, never block).

  • shell/test — a command routing your own test as the oracle (the behaviour bridge, below).

  • checklist — a required verification, not a pattern: when a change touches the scoped paths, the gate prints the step to perform ("run the GPU browser check of the PDF viewer — headless CI cannot see this failure"). At block severity the commit message must carry Hivelore-Checked: <memory-id> — the author's explicit statement that it was done. This is the guard for knowledge no code pattern can express: a caveat that only shows up on a device, a rollout step, a manual migration check.

Sensors turn a documented lesson into a repeatable feedback signal, independent of embeddings or model judgment. Autogenerated sensors start as warn; humans promote vetted ones to block. The doctrine is also enforced against inversion: a block pattern that matches the lesson's own recommended fix (its Instead, use: snippet) is refused (fires-on-correct) — it would block the correct code and never the mistake.

hivelore sensors list
hivelore sensors check                          # scans git diff --cached
hivelore sensors propose <lesson> --kind checklist --paths 'config/security/**' \
  --message 'Run the GPU browser check of the PDF viewer'   # a required verification
hivelore sensors propose <lesson> --from-fix <pre-fix-ref>   # MINE the pattern from the fix diff
hivelore sensors promote <id> --yes             # promote a vetted sensor to block
hivelore sensors export --format grep

Cheaper arming (--from-fix). Authoring a discriminating regex is the main cost between a documented lesson and an enforced one — so let the fix write it. sensors propose --from-fix <pre-fix-ref> mines the pattern from the fix diff: the line the fix removed is the mistake (pattern), the line it added is the correct marker (absent). You confirm a candidate instead of authoring a regex — and it still passes the full validation (silent-on-current, fires-on-bad, not-inverted) before it can block.


Install

npm install -g @hivelore/cli
# Optional: local semantic search (downloads ~110MB model once)
npm install -g @hivelore/embeddings

Verify the complete integration

Run hivelore agent check --exercise --json to exercise MCP briefing, targeted hook context, and a validated sensor against good and bad code in an isolated temporary repository. It also reports first-edit latency and ten-sample median/p95 timings for reads, repeated edits and shell calls. This is a synthetic installation proof, not a productivity benchmark. New projects default to local task completion and draft capture; existing policies remain intact. See the audit fixes and upgrade guide.

After upgrading, run hivelore agent setup --no-global to repair managed legacy Git hooks, then restart your AI client. A successful fresh handshake does not upgrade a running conversation. hivelore agent check --json lists known live MCP versions and remaining migration work. Legacy CI workflows receive a .candidate replacement for review; custom hook commands are preserved.

Complete policies and traceable outcomes

Short applicable policies are injected before edits. When a policy cannot fit, the hook emits an explicit instruction not delivered pointer instead of silently dropping its exceptions. Partial briefings do not count as complete consultation. Use mem_get with the hook’s session_id, or hivelore memory get <id> --session-id <session>, to read and credit the whole policy.

mem_feedback is available in the default MCP profile. Report applied/rejected, or corrected/verified with a commit, test-report or incident reference. An optional catch_id links feedback to an interception listed by hivelore stats outcomes. Linked verification requires a preceding correction. Reports distinguish declared outcomes from a subsequent observed silent sensor check; they do not authenticate references or infer bugs avoided/time saved.

Benchmark reports require at least 10 distinct tasks × 3 repetitions, comparable model, checkout, budget and prompt metadata, independent evaluation attestations, and matching protocol.json/run.json manifests to qualify as decision-ready. Repeating one task or removing an arm cannot satisfy a prepared protocol. This grade describes evidence completeness, not proven superiority or authenticated execution.

The 60-second proof — watch a lesson stop a commit

This is the exact flow shown in the demo above.

Memory tools remember; Hivelore's difference is that a remembered lesson can refuse the commit that repeats it. Try it on any git repo:

hivelore init -y                     # .ai/ layer + git hooks + bridges for the agents you actually use (detected)

# 1. Capture a failed approach (agents do this via the mem_tried MCP tool)
hivelore memory tried \
  --what "importing moment.js" \
  --why-failed "bundle bloat — team standard is date-fns" \
  --instead "date-fns" --paths src/
#    → prints the new memory id, e.g. 2026-07-02-attempt-importing-momentjs

# 2. Give the lesson teeth: a validated, deterministic guardrail
hivelore sensors propose 2026-07-02-attempt-importing-momentjs \
  --pattern "from ['\"]moment['\"]" --severity block
#    Hivelore validates it first: silent on your current code, fires on the mistake.

# 3. Reintroduce the mistake — the commit is refused
echo "import moment from 'moment';" >> src/dates.ts
git add . && git commit -m "add date helper"
#    🛡️  A documented lesson refused this commit — about the change you just made:
#        • 2026-07-02-attempt-importing-momentjs (src/dates.ts)  use date-fns
#          import moment from 'moment';

Same diff, same answer, on every machine and in CI — the gate is deterministic by design. Everything lives as reviewable Markdown in .ai/, versioned with your code. rm -rf .ai undoes it all.


Quick start

1. Initialize your project

cd my-project
hivelore init          # Creates .ai/, bridge files, MCP config, hooks, CI template

hivelore init now also runs agent setup. It writes project-level MCP configs, records the best available mode, and asks before changing user-level client configs. In non-interactive shells it skips global config and tells you how to finish setup.

2. Connect your AI client

Claude Code (~/.claude.json):

{
  "mcpServers": {
    "hivelore": {
      "command": "hivelore",
      "args": ["mcp", "--stdio", "--root", "/absolute/path/to/my-project"]
    }
  }
}

Cursor (~/.cursor/mcp.json):

{
  "mcpServers": {
    "hivelore": {
      "command": "hivelore",
      "args": ["mcp", "--stdio", "--root", "/absolute/path/to/my-project"]
    }
  }
}

VS Code:

code --add-mcp '{"name":"hivelore","command":"hivelore","args":["mcp","--stdio","--root","/path/to/project"]}'

3. Bootstrap your project context

In your AI client, invoke the bootstrap_project MCP prompt. The agent analyzes your codebase and writes .ai/project-context.md automatically.

4. Start work through Hivelore

Every session starts with one call:

get_briefing(task: "add a Stripe payment integration", files: ["src/payments/PaymentService.ts"])

The agent gets project context + relevant module contexts + ranked context breadcrumbs in one shot — no more grepping to rediscover what the team already knows.

For CLI agents without native MCP, wrap them:

hivelore run -- claude --dangerously-skip-permissions -p "$(cat task.md)"

Check the selected mode any time:

hivelore agent status
hivelore agent check          # initialize the server and discover its tools
hivelore agent setup          # re-run setup later
hivelore agent setup --yes    # approve user-level MCP config without prompting

Setup migrates obsolete haive MCP commands, including Codex user configuration, and preserves other servers and JSONC comments. It supports Claude Code, Cursor, VS Code, Windsurf, Codex, and detected Gemini CLI/Roo Code configurations. Restart the client after setup, then call get_briefing in a new session: a successful server check does not prove that an existing session has access. See MCP connection troubleshooting.

5. Gate commits and pull requests

hivelore enforce install       # Installs Git hooks + CI enforcement template
hivelore enforce status        # Current enforcement posture
hivelore enforce check --stage pre-commit  # Scan the staged change
hivelore enforce ci            # CI entrypoint (exits 1 on violations)

One knob decides what refuses: enforcement.posture.

posture

what refuses

advisory

nothing — everything is reported. For adopting Hivelore on a repo mid-flight

balanced (default)

deterministic, code-bound findings only: block sensors, anchored anti-patterns, stale anchors on files you touched, artifact hygiene

strict

the above, plus the process gates (briefing, recap, decision coverage, bootstrap) at the sharing points — pre-push and CI

mode, processGate and humanCommits are the individual switches a posture sets; pin one explicitly to override the posture for that switch alone. hivelore doctor always prints the effective posture and any overrides, so what the gate will do is never a guess.

One rule is not a posture knob and is not negotiable: process gates never refuse a local commit, at any posture. Blocking them on every pre-commit is what trains the --no-verify reflex on cold repos. A passing commit-time gate prints one line; --verbose shows every check. If a git hook was left broken by an old install, hivelore doctor --fix regenerates it.

When something does refuse, it names the line.

🛡️  A documented lesson refused this commit — about the change you just made:
    • 2026-07-02-attempt-importing-momentjs (src/dates.ts)  use date-fns, not moment
      import moment from 'moment';

One lesson, one line, with the file and the offending source. No composite score of any kind: the gate reports what refused the change and what to do about it, and stays silent otherwise.


CLI at a glance — the golden path

hivelore --help shows only the commands you use day to day. Everything else (review, import, diagnostics, benchmarks) is one hivelore --advanced --help away — the focused surface is deliberate, not a missing feature.

Exhaustive command manual: packages/cli/README.md documents every command with its flags and examples. It is the reference; this page is the concepts. Each claim lives in exactly one of the two.

Stage

Command

What it does

Set up

hivelore init

Create .ai/, bridge files, MCP config, hooks, CI

hivelore doctor

Check the install is healthy

hivelore agent setup

Wire your AI client (MCP, hooks)

Before editing

hivelore briefing

Feedforward context — the CLI mirror of get_briefing

Capture knowledge

hivelore memory save

Record a decision / convention / gotcha

hivelore memory tried

Record a failed approach so it isn't repeated

(passive)

Session failures observed by the hooks are auto-distilled into proposed drafts at session end — review with memory list --status proposed; they never self-validate and never carry sensors

Retrieve

hivelore memory search · get

Find, then read a record

Feedback

hivelore sensors check

Scan the diff against documented lessons

Gate

hivelore enforce finish

Exit gate before you call the task done

Sync

hivelore sync

Re-check stale anchors, refresh bridge files

Close

hivelore session end

Save a recap for the next session

One vocabulary across CLI and MCP. The memory verbs mirror the MCP tool names, so an agent learns them once: hivelore memory save/search/get/delete ↔ mem_save/mem_search/mem_get/mem_delete (the older add/query/show/rm still work as aliases).


Audit your agent rules in 10 seconds — no install, no init

Most repositories now tell their agents what to do in CLAUDE.md, AGENTS.md or .cursor/rules. Compliance with prose is probabilistic, and studies of public instruction files find only a small fraction of their rules backed by any real control. rules audit reads your instruction files and tells you which rules are enforced, which are mechanically checkable but unenforced, and which are legitimately judgment — read-only, on any repository:

npx @hivelore/cli rules audit
#   25 rules — 12 enforced by a gate · 6 checkable but unenforced · 7 judgment
#   Enforceable coverage: 67% of the rules a machine could check are actually checked.
#   CLAUDE.md:55  NEVER run `npm publish` from an agent.   signals: code token, command

Each checkable rule is one sensors propose away from being refused by the gate instead of hoped for. --fail-under <pct> turns it into a CI check.

Is it preventing mistakes, or performing ceremony?

hivelore report harness answers with counts, case by case: every sensor with its runs, catches, live hivelore:allow waivers and last hit (and the ones never evaluated); the most-surfaced memories and whether anyone reported applying them; validated memories never surfaced in 60 days (archive candidates); anchors that no longer exist; decisions past their expires_when date. Nothing is inferred — no "time saved", no unverifiable totals.

Try it on your repo (5 minutes, reversible)

Want to evaluate Hivelore on a real codebase that isn't a toy? It is non-destructive — everything it writes lives under .ai/ plus a few bridge files, all removable.

cd your-project
npm install -g @hivelore/cli
hivelore init -y            # seeds stack packs + git-history scars; writes .ai/ and bridges
hivelore briefing --task "the change you're about to make" --files path/to/file
hivelore doctor             # health + coverage report
hivelore sensors check      # scan your staged diff against documented lessons
hivelore eval --fail-under 50   # retrieval + sensor quality on your own corpus

To remove everything Hivelore added: rm -rf .ai CLAUDE.md AGENTS.md GEMINI.md .cursorrules .clinerules .continuerules .windsurfrules .rules CONVENTIONS.md .github/copilot-instructions.md and drop the .github/workflows/hivelore-*.yml files. Feedback from a repo that isn't ours is the most valuable thing you can send — please open an issue with what worked and what didn't.

What Hivelore enforces

Gate

What it checks

First-agent bootstrap

On a cold corpus, the first agent is asked to fill the knowledge layer: a filled project-context, a module context per component, an anchored memory per main code area, and a sensor per main code area. The trigger is corpus state — once the baseline exists the gate is silent for every later agent. Reports by default; refuses at posture: "strict"

Briefing loaded

Agent loaded fresh context breadcrumbs before editing. Reports by default

Decision coverage

Changed files are covered by relevant anchored decisions in the last briefing. Reports by default

Anti-pattern matching

Anti-patterns relevant to the diff are surfaced at the gate; a validated block sensor that fires on the added lines blocks the commit. Hardness is tunable via enforcement.antiPatternGate (off · review · anchored (default) · strict)

Gate-surface integrity

A diff that weakens a sensor (block→warn demotion, changed/removed oracle, broadened suppression, deleted block-sensor memory) is surfaced for review (sensor-weakened) — the gate lives in .ai/, so weakening it must never sail through unmentioned

Stale anchors

Memories anchored to deleted/moved paths block — but only when the anchor is on a file this change touches. Stale anchors elsewhere are corpus maintenance, reported as a warning

Session recap

Agent captured what changed and what remains before closing. Reports by default

CI enforcement

Required check blocks merge on any gate failure

What "block" means here. The gate spends its refusals only where it has deterministic, code-bound evidence: a validated sensor firing on the added lines, an anchored anti-pattern, a stale anchor on a file you touched — same diff, same answer, on every machine and in CI. Anchor, literal-token, and semantic matches (however strong) are surfaced for review, never blocked: relevance signals vary across environments and co-occurrence is not reintroduction. propose_sensor is the path from a captured lesson to a blocking guardrail.

The process gates report; they do not refuse. Since v0.55.0, "you did not load a briefing" and "you did not write a session recap" are requests, not verdicts on your diff. The reason is empirical: a field report had two pushes refused carrying tested code with a green quality gate and zero violations — every penalty was a process one, none was about the code. The next thing a developer learns is --no-verify, which costs them the whole gate, sensors included, and a gate that gets bypassed protects nothing. Set enforcement.posture: "strict" if you want the workflow enforced too.


Cold start — value in session one

hivelore init can seed from signals the repo already has, and every seed passes a quality floor so cold-start never ships generic, guessable advice.

Stack packs are opt-in since v0.55.0 (--stack auto). Seeding them by default filled a new corpus with advice nobody wrote for the repo, and the first briefing of a real session read thin · must_read=0 useful=0 background=3 — all three being stack-pack platitudes occupying the briefing without teaching anything. An empty corpus is more honest: it says plainly that it needs filling. Git-history seeding stays on in autopilot, because a revert in your history is your scar.

Source

What it seeds

Quality gate

Stack packs (--stack auto, opt-in)

Detected-framework traps (Next/Nest/Prisma/Flask/Rails/Tailwind/Docker… 20+ packs), with block sensors where high-signal

specificity floor — generic advice is dropped, audited in CI

Git history (--seed, on by default)

Draft memories from revert/hotfix/workaround commits — your repo's real scars

noise-subject denylist (merge/bump/deps/wip/format dropped)

Scanner findings (hivelore ingest)

SonarQube / SARIF / ESLint / npm audit findings as proposed, anchored memories with sensors

auto-fixable stylistic rules dropped (incl. Sonar numeric keys); --include-stylistic to keep

hivelore init                                   # Initialize + seed from git history
hivelore init --stack auto                      # ...and add starter packs for the detected stack
hivelore ingest --from sonar issues.json --min-severity major
hivelore ingest --from eslint report.json
hivelore ingest --from sarif report.sarif --dry-run   # Preview without writing

Ingested and git-seeded memories land as proposed (warn-only sensors). Review them with hivelore memory list --status proposed; promote vetted sensors to block with hivelore sensors promote.


.ai/ directory layout

your-project/
├── .ai/
│   ├── project-context.md          # Shared project overview
│   ├── modules/                    # Per-component context files
│   │   ├── backend/context.md
│   │   └── frontend/context.md
│   ├── memories/
│   │   ├── personal/               # Private — gitignored
│   │   ├── team/                   # Shared — committed to git
│   │   └── module/<name>/          # Module-scoped memories
│   ├── code-map.json               # Symbol index — deterministic, safe to commit
│   ├── .runtime/                   # Local session state — gitignored
│   └── .cache/                     # Indexes, churn, telemetry — gitignored
├── CLAUDE.md                       # Auto-generated bridge (Claude Code)
├── AGENTS.md / GEMINI.md / …       # …and 10 more native bridges (see below)
└── .github/
    ├── copilot-instructions.md     # Auto-generated bridge for Copilot
    └── workflows/
        ├── hivelore-sync.yml       # Anchor verification on merge
        └── hivelore-enforcement.yml # Required policy gate

Native bridges — meet every agent where it is

For CLI/IDE agents without MCP, hivelore init generates native config files from the same corpus, so the team's memories and block sensors travel to whatever agent a developer uses — not just an empty template, the enforcement edge too. hivelore sync keeps them fresh; never hand-edit them (regenerate with hivelore bridges sync).

Agent

File

Agent

File

Claude Code

CLAUDE.md

Cline

.clinerules

Cursor

.cursor/rules/haive-memories.mdc

Windsurf

.windsurfrules

Codex / generic

AGENTS.md

Continue

.continuerules

GitHub Copilot

.github/copilot-instructions.md

Cody

.sourcegraph/cody-rules.md

Gemini CLI

GEMINI.md

Zed

.rules

Aider

CONVENTIONS.md

Roo

.roo/rules/haive.md

hivelore bridges list                 # Show target status
hivelore bridges sync --all           # Regenerate every native bridge
hivelore init --bridge-targets cursor,copilot   # Or scope to specific agents

Context policy records

Type

Description

decision

Architectural or design choices the team has locked in

gotcha

Non-obvious constraints, known footguns, subtle invariants

convention

Naming, patterns, style rules specific to this codebase

attempt

Failed approaches — so agents don't repeat them

architecture

Component boundaries, interfaces, data flow

All records can be anchored to file paths and symbol names. When anchored code changes, Hivelore flags the record as potentially stale.


MCP tools reference

Default profile — the tools agents actually use:

Tool

Description

get_briefing

⭐ Ranked team policy for a task and the files you will edit — each memory as a one-line rule, must_read only when anchored to a passed file

mem_get

Fetch one record in full after a briefing

mem_save

Save repo policy knowledge (decision, gotcha, convention, attempt, architecture) — with a one-line rule and an optional doc source

mem_update

Amend an existing record in place — anchors, rule, source, body

mem_tried

Record a failed approach so future agents do not repeat it (optionally arming a sensor in the same call)

propose_sensor

⭐ Turn a captured lesson into a validated guardrail: a regex/AST pattern, a command oracle, or a checklist — a required verification whenever a change touches given paths

pre_commit_check

Diff against known gotchas, decisions, and stale anchors

report_friction

Record friction with Hivelore itself, locally. Never sends anything — a human reviews with hivelore report and decides what becomes an issue

Maintenance profile (HIVELORE_TOOL_PROFILE=maintenance) adds, among others:

Tool

Description

mem_search

Full-text or semantic search across context records

mem_relevant_to

Ranked context records for a task when project context is already loaded

mem_feedback

Report applied/rejected or referenced corrected/verified outcomes; optionally link a sensor catch

mem_verify

Check anchor freshness, detect stale records

code_map

Look up symbols without manual grep when code-map is indexed

code_search

Semantic search over exported symbols (needs @hivelore/embeddings + hivelore index code-search)

scaffold_test

Generate a pending post-incident test from a lesson + the sensors propose --kind test line to arm it (monorepo-aware)

mem_session_end

Save end-of-session recap for the next agent (the SessionEnd hook already does this)

MCP profiles keep the product focused:

  • HIVELORE_TOOL_PROFILE=enforcement (default): the eight tools above. Fewer tools, fewer wrong choices.

  • HIVELORE_TOOL_PROFILE=maintenance: corpus review, lifecycle, distillation, search, code-map/code-search, and project-context maintenance.

  • HAIVE_TOOL_PROFILE=experimental / full: legacy aliases for maintenance (the experimental diagnostics were removed in v0.32.0 — months of usage showed a single call across all of them).


MCP prompts reference

Prompt

Description

post_task

⭐ Post-task checklist — capture learnings before closing every session

bootstrap_repo

⭐ First-agent bootstrap — fills the whole knowledge layer the bootstrap gate requires (project-context, module contexts, anchored memories, a validated sensor per main area). Tailors a concrete checklist from the current corpus state and drives bootstrap_project_save → mem_save → propose_sensor until ready

bootstrap_project

Analyze the codebase and write .ai/project-context.md


Packages

Package

Install

Description

@hivelore/cli

npm i -g @hivelore/cli

Main product: init, enforce, run agents, briefing, memory, sync, CI/Git hooks

@hivelore/mcp

bundled into @hivelore/cli

Policy-aware MCP server

@hivelore/core

dependency

Types, schema, anchors, policy primitives, token budgets

@hivelore/embeddings

npm i -g @hivelore/embeddings

Optional: local semantic ranking (bge-small-en-v1.5, fully offline)

Also in this repo: a VS Code extension (surfaces memories inline + a Strategic Cockpit over the CLI's observability) and a GitHub Action (posts relevant team memories as a PR comment so reviewers and agents never miss a non-obvious constraint).

The PR loop. Review feedback is team truth in the making: reply /hivelore remember <rule> on any review thread and the Action acknowledges it with the exact persist command; or run hivelore ingest --from github-pr <number> to turn a PR's human review instructions ("never…", "always…", "prefer X instead") into proposed, file-anchored memories — each one a candidate for sensors propose, which is the step no inferential review bot can take. With persist-review-learnings enabled (default), the Action creates a dedicated branch and PR containing the proposed memory; when repository write permission is unavailable, it falls back to the local ingest command. Top-level PR comments and review-thread replies follow the same path.

Structural sensors. sensors propose --kind ast accepts either a concise --pattern or a full ast-grep --rule <json> (inside/has/not/all/any). JavaScript/TypeScript are built in; Python, Go, Rust, and Java are optional language packages shipped with the CLI. Rules still pass Hivelore's silent-on-current/fires-on-bad validation before they can block. Nested relational rules are not recursive by default: add "stopBy":"end" when has or inside must search every descendant, for example {"has":{"kind":"interpolation","stopBy":"end"}}.


Adaptive briefing

A briefing only earns its place when it carries unguessable knowledge, so get_briefing returns briefing_value: "high" | "low". When nothing team-specific matches the files/task, the auto-generated project context is trimmed to a one-line note (config: adaptiveBriefing, default on) — so Hivelore surfaces deeper context only when it actually knows something the model doesn't.

Anchors are weighted by how much they actually discriminate

An anchor match is the strongest ranking signal there is — when the anchor is specific. On a file every commit touches it is almost none. Measured on this repo: package.json is touched by 106 of 149 commits, so every lesson anchored to it declared itself must_read on every release commit. The median commit had 34 memories claiming the top rank for 8 slots, and which 8 surfaced was arbitrary.

Since v0.57.0 a match is weighted by how rare the matched path is — plain IDF, applied to anchors. An anchor touched by more than 35% of recent commits needs corroboration (a strong semantic hit or a symbol match) before it outranks everything, and specificity breaks ties within a tier. Measured over 25 real commits, briefing slots spent on a low-information anchor fell from 17% to 4%.

Churn is one cached git log, invalidated by HEAD. Too small a sample — a shallow clone, a young repo — is reported as unknown and ranks exactly as before, never as "everything is common".

hivelore doctor reports memory-broad-anchors, naming the memories that claim nearly every change and the share of commits each anchor covers. The fix is always additive: give the lesson the precise path it is really about.


CLI reference

# Setup
hivelore init [--with-ci] [--no-bridges]         # Initialize .ai/ + bridge files + seed from git history
hivelore init --stack auto                       # Opt in to generic starter packs for the detected stack
hivelore init --bridge-targets <all|csv>         # Scope generated bridges to specific agents
hivelore enforce install                         # Install Git hooks + CI enforcement
hivelore enforce status                          # Enforcement posture report
hivelore bridges list/sync [--all]               # Inspect / regenerate native agent bridges
hivelore index code                              # Build .ai/code-map.json
hivelore index code --status [--json]            # Report code-map / code-search index freshness

# Daily use
hivelore briefing [--task <text>] [--files] [--json]   # Print context + relevant memories
hivelore run -- <agent command>                  # Wrap any CLI agent in Hivelore session
hivelore enforce check [--stage pre-commit]      # Policy gate
hivelore enforce ci                              # CI entrypoint
hivelore enforce finish                          # Final agent-exit gate: commit/push, version/tag, CI, npm + GitHub Release
hivelore coverage [--source git|agent|both]      # Find changed files no memory covers
hivelore sync [--since <ref>] [--embed]          # Verify anchors + auto-promote
hivelore sensors list/check/export/promote       # Operate executable memory sensors
hivelore sensors propose <id> --pattern <re>     # Turn a lesson into a VALIDATED guardrail
hivelore report list|submit|dismiss              # Friction agents hit with Hivelore itself

# Memory
hivelore memory save --type <type> --body "<text>" [--paths <csv>]  # Save a memory (anchor to files)
hivelore memory list [--scope] [--status]        # List memories
hivelore memory search <text>                    # Full-text / semantic search
hivelore memory get <id>                         # Read one record
hivelore memory approve [<id>|--all]             # Mark as validated
hivelore memory promote <id>                     # personal → team
hivelore memory tried [--sensor-pattern <re>]    # Record a failed approach (one-shot guardrail)
hivelore memory conflicts [<a> <b>] [--yes]      # List conflict candidates / resolve one pair
hivelore memory verify [--update] [--json]       # Check anchor freshness
hivelore memory import --from <file> [--changelog]  # Import docs or a CHANGELOG as memories
hivelore memory seed [stack|--git]               # Re-seed stack packs / git-history scars

# Cold start (seed from existing signals)
hivelore ingest --from sonar|sarif|eslint|npm-audit <file>  # Scanner findings → anchored memories
hivelore ingest --from <fmt> <file> --dry-run    # Preview without writing

# Indexes (symbol map + semantic search)
hivelore index code [--status]                   # Build .ai/code-map.json / report freshness
hivelore index memories                          # Build the semantic index (first run: ~110MB model)
hivelore index query <text>                      # Semantic search over memories

# Release protocol
hivelore release bump <patch|minor|major>        # Lockstep version bump + CHANGELOG scaffold
hivelore release tag                             # Tag vX.Y.Z at HEAD, push branch + tag
hivelore release ship                            # After the bump commit: pull --rebase → tag+push → poll CI

# Diagnostics
hivelore doctor                                  # Analyze setup, emit recommendations
hivelore eval --fail-under 80                    # Retrieval + sensor quality gate
hivelore eval --semantic-ranking                 # Real embeddings lane (requires index)
hivelore selftest                                # Self-test MCP tools (latency + payloads)

hivelore eval auto-synthesizes retrieval cases from anchored memories and, when present, also loads .ai/eval/spec.json for labeled retrieval/sensor cases. This repo uses that file to keep executable memory sensors in CI, so a broken guardrail is caught before release. Committed regression baselines use only versioned team/module memories and deterministic anchor/lexical ranking; local usage counters, personal memories, and optional embedding caches cannot make a baseline pass locally but fail in a clean CI clone. Semantic search remains exercised by the embeddings/search test suites and by a separate --semantic-ranking CI lane backed by .ai/eval/semantic-baseline.json. That lane fails closed when the package or index is unavailable.

hivelore doctor reports local setup drift that can make agents misdiagnose the repo: missing pnpm, stale workspace dist artifacts, global CLI/MCP version skew, outdated code-search indexes, and low memory-anchor coverage.


Multi-component projects

For projects with multiple components (frontend/backend/microservices), create one module context per component. get_briefing auto-loads the relevant module context based on the files being edited.

mkdir -p .ai/modules/backend .ai/modules/frontend

cat > .ai/modules/backend/context.md << 'EOF'
# Module: backend
- Spring Boot, Java 17, PostgreSQL
- Always filter by tenantId in every repository query
- Never modify existing Flyway migrations — create V{N+1}__desc.sql
EOF

cat > .ai/modules/frontend/context.md << 'EOF'
# Module: frontend
- React 19, TypeScript, TanStack Query v5
- All API calls go through hooks in features/<domain>/api/
- Env vars must start with VITE_ to be exposed to the client
EOF

Development

git clone https://github.com/Doucs91/hivelore.git
cd Hivelore
pnpm install
pnpm -r build    # Build all packages
pnpm -r test     # Run tests

Requires Node 20 LTS+, pnpm 9+.


Contributing

Issues and PRs are welcome. Please open an issue before starting significant work so we can align on direction.


License

Apache 2.0 — see LICENSE.

Available Tools

16 tools
code_mapA

Look up where symbols (classes, functions, interfaces) are defined in the codebase.

USE INSTEAD OF grepping when you need to find where something lives. Requires hivelore index code to have been run (done automatically in autopilot mode).

TIP: include symbols in get_briefing directly for auto-lookup at session start.

PARAMETERS: symbol — name or partial name to search (e.g. 'PaymentService') file — filter by file path substring max_files — cap on results (default 40)

RETURNS: { available: bool, files: [{ path, exports: [{ name, kind, line, description }] }] } If available: false → run hivelore index code first.

NameRequiredDescriptionDefault
fileNoFilter to files whose path contains this substring
pathsNoFilter to files under any of these path prefixes (e.g. ['packages/mcp/src/tools/', 'src/auth/']). OR-joined with `file` substring; useful to get a focused view of one module.
symbolNoFilter to files exporting a symbol whose name contains this substring
max_filesNoCap on returned files (hard limit, applied after token budget)
max_tokensNoApproximate token budget for the response. When the matching set exceeds it, files are ranked by export density (exports per LOC) and the highest-signal ones are kept first. Omit to disable budgeting (legacy behavior).
get_briefingA

⭐ DEFAULT-FIRST for coding agents on any repo where hivelore init ran: call this BEFORE changing source or project config for the current goal (unless the developer explicitly opts out). One-shot onboarding: everything relevant in a single call under a token budget.

PROGRESSIVE DISCLOSURE — after this, drill down only if needed: mem_relevant_to / mem_search (compact lists) → mem_get (full body + anchors).

RETURNS (in order of priority): 0. action_required — ⚠️ HANDLE THIS FIRST if non-empty (see protocol below)

  1. last_session — recap of the previous session (goal, what was done, next steps)

  2. project_context — .ai/project-context.md (auto-generated from code-map if template)

  3. module_contexts — relevant .ai/modules//context.md based on files being edited

  4. memories — ranked team memories relevant to your task

  5. symbol_locations — file:line:kind for any requested symbols (no grep needed)

  6. setup_warnings — actionable warnings if setup is incomplete

  7. decay_warnings — memories not read in >90 days (consider reviewing)

⚠️ ACTION_REQUIRED PROTOCOL — MANDATORY: If action_required[] is non-empty, STOP and for each item:

  1. Show the developer the exact developer_message field verbatim

  2. Wait for explicit human confirmation ('yes', 'go ahead', 'oui', etc.)

  3. Only then proceed with any code changes NEVER act autonomously on cross-repo breaking changes, dep bumps, or contract diffs.

KEY PARAMETERS: task — what you are about to do (1–2 sentences) — ALWAYS provide this files — files you are about to edit — surfaces anchored memories symbols — symbol names to look up in the code-map (e.g. ['PaymentService']) format — 'full' (default) | 'compact' (1-line) | 'actions' (bullet-first excerpts) budget_preset — 'quick' | 'balanced' | 'deep' — scales max_tokens/memories/module contexts

EXAMPLE USAGE: get_briefing({ task: 'add a Stripe payment integration', files: ['src/payments/'], symbols: ['PaymentService'] })

CONFIDENCE LEVELS in memories: authoritative — human-validated, tested evidence with recent verification trusted — validated; freshness decays since verification, not retrieval low — proposed, hypothesis, or aging evidence; reads do not prove truth unverified — draft (unverified: true flag set)

Replaces 4–5 separate tool calls. Prefer this first; use mem_search / mem_get only for follow-up.

NameRequiredDescriptionDefault
taskNoWhat you are about to do, in 1–2 sentences. Used to rank relevant memories semantically.
filesNoProject-relative file paths the agent is currently looking at or about to edit
trackNoIncrement read_count on returned memories
formatNoOutput format: 'full' returns memory bodies (honors token budget via truncation); 'compact' returns a 1-line summary per memory (call mem_get for detail); 'actions' squeezes bodies to actionable bullet lines — fewer tokens vs full.full
symbolsNoSymbol names to look up in the code-map (e.g. ['PaymentService', 'TenantFilter']). Returns the file(s) exporting each symbol so agents don't need to grep. Requires `hivelore index code` to have been run.
semanticNoUse semantic ranking when a task is provided (requires `hivelore embeddings index`).
max_tokensNoApproximate token budget for the entire briefing. Each section is allocated a share and truncated to fit.
session_idNoStable harness session ID; isolates consultation and context delivery.
max_memoriesNoCap on memories surfaced regardless of token budget
budget_presetNoShortcut token budget: 'quick' minimizes tokens/skip module CONTEXT slices; 'balanced' mirrors historical defaults; 'deep' uses a larger briefing. When set, overrides max_tokens, max_memories, and include_module_contexts.
context_resetNoSet after compaction to restore context without resetting task attribution.
deterministicNoIgnore machine-local usage/impact signals so repeated evaluations rank the shared corpus reproducibly.
include_staleNoInclude stale memories (excluded by default — they may be outdated)
memory_scopesNoRestrict the candidate corpus to selected scopes. Omit to include every scope.
min_semantic_scoreNoFloor for semantic-only memory hits (cosine). The default (0) is not 'keep everything': on a corpus large enough to characterize a distribution, an adaptive floor at the corpus mean+½σ is applied so the undifferentiated mass of weak hits is trimmed while the top hit is always kept. Set an explicit value to raise the bar further; it never lowers the adaptive one. Has no effect on memories matched via anchor/module/literal — those are always kept.
dedupe_project_contextNoToken saver (default ON): skip re-emitting the project-context body if an identical copy was already sent within the last few minutes this session (the agent still has it). Set false to always include it.
include_module_contextsNoInclude the `.ai/modules/<name>/context.md` slices inferred from `files` (default ON). Set false to keep the briefing to project context + memories. Overridden by `budget_preset` when that is set.
include_project_contextNoInclude the `.ai/project-context.md` body (default ON). Set false when the agent already has the project overview and you only want the module/memory layers — see `dedupe_project_context` for the automatic, session-aware version of the same saving.
mem_feedbackA

Record whether a memory actually HELPED — the closed-loop utility signal.

USE right after a memory changed (or failed to change) what you did:

  • outcome='applied' → the memory steered your work (strong positive signal)

  • outcome='rejected' → it was wrong/outdated/unhelpful (negative signal)

A read only means a memory was surfaced; 'applied' is a reported utility signal, not independently verified proof. This powers hivelore memory impact (impact tiers + prune candidates) and future ranking.

PARAMETERS: id — full memory id the feedback is about outcome — applied | rejected | corrected | verified reference — required for corrected/verified; reported commit or test-report reference catch_id — optional recorded catch identity; linked verified requires a prior correction reason — why it was rejected (optional, stored on the usage record)

RETURNS: { ok, id, outcome, usage:{read_count,applied_count,rejected_count}, impact:{score,tier,signals} }

NameRequiredDescriptionDefault
idYesFull memory id the feedback is about
reasonNoWhy it was rejected (stored on the memory's usage record). Only used for outcome='rejected'.
outcomeYes'applied' = this memory changed what you did (strong positive utility signal); 'rejected' = it was wrong/outdated/unhelpful (negative signal, blocks auto-promotion).
catch_idNoCatch identity from stats outcomes; verified requires a prior linked correction
referenceNoRequired for corrected/verified: commit, test report or incident reference (reported, not authenticated)
session_idNo
mem_getA

Fetch a single memory by its full id with all details.

USE WHEN get_briefing / mem_relevant_to / mem_search returned a compact hit and you need the full body, or when you know the exact id of a memory.

PARAMETERS: id — full memory id (e.g. '2026-04-28-gotcha-flyway-strict-no-ddl')

RETURNS: { id, type, scope, status, confidence, body, anchor, tags, usage }

NameRequiredDescriptionDefault
idYesMemory id to fetch
session_idNoHook session id to credit this complete read to
mem_relevant_toA

One-shot ranked memories for a task — use instead of get_briefing when project context is already loaded and you only want the relevant memory layer.

Second step in progressive disclosure (after get_briefing): narrow here, then mem_get for full text.

Reuses the same ranking pipeline (anchor / module / literal / semantic) but skips project_context, modules, action_required, etc.

PARAMETERS: task — 1–2 sentences describing what you are about to do (required) files — files you'll edit (surfaces anchored memories) limit — cap on returned memories (default 8) min_semantic_score — drop weak semantic hits below this cosine (default 0.25) format — 'full' | 'compact' | 'actions' (inherits get_briefing memory framing)

RETURNS: { task, search_mode, memories: [...], hints?: [...], empty?: true }

NameRequiredDescriptionDefault
taskYesWhat you are about to do, in 1–2 sentences. Used to rank relevant memories.
filesNoOptional: files you are about to edit — surfaces anchored memories.
limitNoCap on returned memories.
formatNo'compact' = id + 1-line summary; 'full' = complete bodies; 'actions' = bullet-first excerpts.full
min_semantic_scoreNoDrop weakly-related semantic hits below this cosine threshold.
mem_saveA

Save a piece of knowledge as a persistent memory that survives across AI sessions.

USE THIS WHEN you discover something worth remembering for future sessions:

  • A project convention (how things are done here)

  • An architectural decision and its rationale

  • A gotcha or non-obvious behavior that surprised you

  • A domain term and what it means in this codebase

DO NOT USE for failed approaches → use mem_tried instead (better structure). For reactive code discoveries during exploration, prefer a compact gotcha via mem_save.

PARAMETERS: type — convention | decision | gotcha | architecture | glossary | attempt slug — short kebab-case id (e.g. 'flyway-no-modify-existing') body — Markdown content with the full knowledge scope — team (shared with all devs) | personal (private) | module (component-scoped) paths — anchor to source files for staleness detection (STRONGLY recommended) topic — stable key for upsert: if a memory with same topic+scope exists, update it in-place

RETURNS: { id, scope, file_path, action: 'created'|'updated', warning?, invalid_paths? } WARNING: if paths point to non-existent files, they will be immediately stale after hivelore sync. DEDUP: identical body content within the same scope is rejected — use mem_update to modify.

NameRequiredDescriptionDefault
bodyYesMarkdown body of the memory
slugYesShort human-readable identifier — becomes part of the filename
tagsNoTags for filtering
typeYesKind of memory being saved. Use 'skill' for reusable procedures/playbooks agents should follow for recurring tasks (feedforward harness guide). Use 'attempt' for failed approaches (auto-validated). Use 'session_recap' via mem_session_end instead.
pathsNoAnchor paths (file paths this memory references)
scopeNoVisibility scope: personal | team | module. When omitted, falls back to defaultScope in haive.config.json (default: personal).
topicNoStable key for this memory. If a memory with the same topic already exists in this scope, it is updated in-place (revision_count++). Use for knowledge that evolves over time.
authorNoAuthor handle or email
checksNo
commitNoAnchor commit SHA (for staleness detection later)
domainNoDomain (e.g. transactions, billing)
moduleNoModule name (required when scope=module)
symbolsNoAnchor symbols (function/class names this memory references)
evidenceNo
lifecycleNoDoes this describe code that EXISTS now, or a decision not yet built? 'applied' (default) = reflected in the code; 'planned' = decided but NOT yet implemented (surfaced distinctly so agents don't write code against it as if it were real); 'abandoned' = rejected, kept so it isn't re-tried.
activationNoOnly for type='skill'. Progressive-disclosure triggers: the skill is surfaced ONLY when a keyword matches the task or a glob matches the edited files (or always=true). Omit to keep the skill always-eligible.
supersedesNo
mem_session_endA

Save an end-of-session recap so the NEXT session starts with fresh context.

CALL THIS before closing any significant working session. In autopilot mode, the MCP server saves a minimal recap automatically on exit — but calling this manually produces a richer, more useful recap.

HOW IT WORKS: uses topic-upsert — one recap per scope is kept and updated in-place (revision_count increments). get_briefing surfaces the latest recap at the very top of the next session's briefing, before project context.

PARAMETERS: goal — what you were trying to accomplish (1–2 sentences) accomplished — what was actually done (bullet list recommended) discoveries — bugs, surprises, missing knowledge found during this session files_touched — key files read or modified (used as anchor for staleness) next_steps — what should happen in the next session or for a teammate scope — personal (default) | team

RETURNS: { id, scope, action: 'created'|'updated', revision_count }

NameRequiredDescriptionDefault
goalYesWhat you were trying to accomplish this session (1–2 sentences)
scopeNoVisibility: personal = private to you, team = shared with the teampersonal
moduleNoModule name (required when scope=module)
next_stepsNoWhat should happen next (for the next session or a teammate)
session_idNoTask session to checkpoint independently of the rolling recap.
discoveriesNoAny bugs, inconsistencies, surprises, or missing knowledge found during this session. Empty if nothing surprising was found.
accomplishedYesWhat was actually done — bullet list recommended
files_touchedNoKey files that were read or modified — used as anchor paths
mem_triedA

Record a FAILED approach so future agents don't repeat the same mistake.

USE THIS IMMEDIATELY when you try something and it doesn't work. This is the most valuable type of negative knowledge — it saves hours of debugging for future agents working on the same codebase.

Auto-validated (no approval cycle). Surfaced FIRST in future get_briefing calls so it's impossible to miss.

PARAMETERS: what — short title of what you tried (e.g. 'importing X with ESM dynamic import') why_failed — the exact error or reason it failed instead — what to do instead (the correct approach) scope — team (default) | personal paths — source files where the issue lives

RETURNS: { id, file_path, action: 'created' }

NameRequiredDescriptionDefault
tagsNoTags for filtering
whatYesBrief description of the approach that was tried
pathsNoAnchor file paths this applies to
scopeNoVisibility scope. Defaults to personal — EXCEPT when a one-shot `sensor` is attached: an enforced lesson is team truth (the sensor must travel to every machine and CI), so it defaults to team. Pass scope explicitly to override.
authorNoAuthor handle or email
moduleNoModule name (required when scope=module)
sensorNoONE-SHOT loop close: validate and attach a sensor in the same call (equivalent to a follow-up propose_sensor). Validated against HEAD — silent on current code, fires on the bad example. If rejected, the attempt is still saved and the verdict tells you how to revise.
insteadNoWhat to use or do instead (recommended alternative)
why_failedYesWhy it failed or why it should NOT be used
mem_updateA

Update the body, tags, or anchor of an existing memory in-place.

USE WHEN a memory exists but its content has become outdated or incomplete. This preserves the memory's id, usage history, and read_count.

For evolving memories that you will update repeatedly, use mem_save with a topic key instead (topic-upsert pattern).

PARAMETERS: id — full memory id to update body — new Markdown content (replaces existing body) tags — new tag list (replaces existing tags) paths — new anchor paths (replaces existing paths) symbols — new anchor symbols (replaces existing symbols)

RETURNS: { id, file_path, updated_fields: string[] }

NameRequiredDescriptionDefault
idYesId of the memory to update
bodyNoNew Markdown body — replaces the existing body
tagsNoNew tags array — fully replaces existing tags
pathsNoNew anchor paths — fully replaces existing anchor.paths
authorNoNew author handle or email
checksNo
commitNoNew anchor commit SHA
domainNoNew domain label
symbolsNoNew anchor symbols — fully replaces existing anchor.symbols
evidenceNo
supersedesNo
mem_verifyA

Check whether memory anchor paths and symbols still exist in the current code.

USE WHEN you want to know if a specific memory is still valid after a refactor, or to check all memories for staleness (hivelore sync does this automatically).

PARAMETERS: id — check a single memory (omit to check all) update — write 'stale' or 'validated' status back to disk

RETURNS: { results: [{ id, status: 'fresh'|'stale'|'anchorless', reason? }] } Stale means the anchored file/symbol no longer exists at that path. Anchorless means the memory has no paths/symbols — staleness is undetectable.

NameRequiredDescriptionDefault
idNoIf set, verify only this memory id
updateNoWrite the resulting status back to disk (status=stale or validated)
pre_commit_checkA

One-shot 'should I block this commit?' check. Combines three signals, all run internally by this one call — you do not invoke them separately:

  1. anti_patterns_check — known gotchas/attempts that match the diff

  2. mem_for_files — conventions/decisions anchored to touched files

  3. mem_verify — memories whose anchors are stale (knowledge may be wrong)

This is the COMBINED diff-scan layer — sensors, anti-patterns and stale anchors in a single call. hivelore enforce check is the git-hook gate that runs the same combination at commit time.

USE FROM A GIT HOOK or before finalizing a non-trivial change.

PARAMETERS: diff — raw unified diff text (e.g. git diff --cached) paths — affected file paths (project-relative) block_on — 'any' | 'high-confidence' (default) | 'never' semantic — use embeddings in anti_patterns_check (default true)

RETURNS: { should_block, summary, warnings, relevant_memories, stale_anchors }

NameRequiredDescriptionDefault
diffNoRaw unified diff text to scan. If omitted, only `paths` is used. When called from a pre-commit hook, pipe the output of `git diff --cached`.
pathsNoProject-relative paths affected by the change. At least one of `diff` or `paths` should be provided.
block_onNoWhen to set should_block=true: 'any' = any warning blocks; 'high-confidence' = only warnings from authoritative/trusted memories block; 'never' = report only, never block.high-confidence
semanticNoEnable semantic search in anti_patterns_check (requires embeddings index).
anchored_blocksNoWhen true, ALSO block a high-confidence anti-pattern (attempt/gotcha) that is anchored to a touched file AND corroborated by the diff (literal token overlap, or semantic >= 0.45) — not just very strong semantic matches. Powers the 'anchored' enforcement gate. Config/docs-only commits are still downgraded. Default false preserves the soft, semantic-only blocking behavior.
propose_sensorA

Propose a discriminating sensor for a gotcha/attempt — YOU write the pattern (you understand the code), Hivelore validates it before trusting it to block. This is how a captured lesson becomes a RELIABLE block instead of an advisory note.

USE THIS right after mem_tried / mem_save on a gotcha whose mistake is detectable in code, to upgrade the auto-suggested (warn) sensor into a precise, promotable one.

Write a pattern that matches the FAULTY usage, and — crucially — an absent regex for the CORRECT-usage marker so it fires on the bug only, not every call (e.g. pattern=the API call, absent=the required option).

VALIDATION (a block proposal is accepted ONLY if): the pattern is not brittle, stays SILENT on the current (correct) anchored code, and FIRES on the bad example. A rejected proposal is NOT written — the returned reason/guidance tells you how to revise; then call propose_sensor again.

PARAMETERS: memory_id — the gotcha/attempt to protect pattern — regex matching the faulty usage absent — regex for the correct-usage marker (makes it discriminate) — strongly recommended bad_example— a snippet that SHOULD match (else examples are read from the lesson) severity — 'block' (default) | 'warn'

RETURNS: { accepted, reason?, guidance?, self_check, file_path? }

NameRequiredDescriptionDefault
kindNoregex = pattern matched on added diff lines (default; comments are stripped before matching, but string literals are NOT — so a regex can still target a bad literal in a string). ast = an ast-grep STRUCTURAL pattern (e.g. 'stripe.paymentIntents.create($$$)') matched on the AST of changed files — comments AND strings can never false-positive, so PREFER ast for a parseable language (JS/TS, Python, Go, Java, Rust, …) when the @ast-grep/napi engine is available; `absent` is a sub-pattern that must be missing INSIDE the match (requires that optional engine). shell|test = a COMMAND the gate runs when the diff touches the sensor's paths — routes the team's own oracle (an existing test, an invariant script) to this lesson. Command sensors only execute where enforcement.runCommandSensors=true.regex
ruleNokind=ast: full ast-grep Rule object (kind/inside/has/not/all/any/etc.). May be used alone or combined with pattern.
flagsNoOptional regex flags (e.g. 'i' for case-insensitive).
pathsNoOverride scope paths. Defaults to the memory's anchor paths.
absentNoRegex for the CORRECT-usage marker (e.g. 'idempotencyKey'). When it appears in the window around a match, the catch is suppressed — this is what makes the sensor discriminate the faulty call from the correct one. STRONGLY recommended for 'X without Y' lessons.
commandNokind=shell|test: command to execute (e.g. 'npx vitest run tests/payments/refund.spec.ts'). Non-zero exit = the lesson fires.
excludeNoGlob-ish paths the sensor must NOT fire on, even inside `paths`. Set this for a PRODUCTION-ONLY lesson so it skips test doubles/fixtures — e.g. exclude ['**/*.test.*','**/*.spec.*','**/__tests__/**','**/*.stories.*','**/*.d.ts']. Leave empty for a lesson that IS about tests (it should still fire there). Documentation files (.md/.rst/…) are already skipped automatically.
messageNoLLM-facing fix message shown when it fires. Defaults to one derived from the lesson.
patternNokind=regex: regex matching the faulty usage; kind=ast: optional structural pattern (may be combined with `rule`).
red_refNokind=shell|test: prove the oracle actually catches the incident. A git ref (commit/branch) of the PRE-FIX state; validation replays it in a scratch worktree and requires the command to FAIL there (RED) in addition to passing on the current tree (GREEN). On success the sensor records red_proven: true — 'the test demonstrably catches the incident', shown in the prevention receipt.
replaceNoSet true to DELIBERATELY replace a sensor already hand-authored on this memory. Without it, a second proposal onto a memory that already carries a validated sensor is REFUSED — otherwise the second call silently destroys the first while still answering accepted:true. One memory holds one sensor; use a separate memory for a second, distinct symptom.
incidentNoProvenance: the real incident this sensor guards — a ticket/prod ref ('prod #442', 'INC-1029', '2026-06 refund overcharge'). Turns 'a test failed' into 'this reproduces the incident the test exists to prevent'. Surfaced in the block message and the prevention receipt. Strongly recommended for command/test sensors routed from a post-incident test.
languageNokind=ast: explicit built-in/dynamic language name for non-standard file extensions.
severityNoblock = hard-fail the gate (accepted ONLY if it passes self-validation). warn = advisory.block
memory_idYesId of the gotcha/attempt memory this sensor protects.
timeout_msNokind=shell|test: max runtime before the executor kills the command (default 120000).
bad_exampleNoA code snippet that SHOULD match — proves the sensor catches the mistake. If omitted, examples are read from the lesson body.
require_presentNokind=regex: make this a REQUIRED-PRESENCE invariant instead of a forbidden-pattern one. `pattern` then names a line that must REMAIN in the anchored file; the sensor FIRES when a change REMOVES it. Use for 'do not delete this critical line' lessons a diff-of-added-lines sensor cannot see. Validated by requiring the pattern to be PRESENT in the current anchored code (there must be something to guard).
report_frictionA

Tell Hivelore's maintainer that HIVELORE ITSELF got in your way — a bug in a Hivelore tool, a misleading message, wrong docs, or an improvement idea.

USE THIS WHEN the friction is with Hivelore, not with the project you are working on:

  • a Hivelore tool or command errored, or did something other than what it documented

  • a message or return value misled you into a wrong action

  • the docs/description for a tool were wrong, missing, or contradictory

  • you can see a concrete improvement to how a Hivelore tool behaves

DO NOT USE for anything about the project's own code → that is mem_tried (a failed approach) or mem_save (a gotcha/convention). This tool is only for feedback ON THE TOOLING.

STAYS LOCAL. Nothing is published: the report is appended to a machine-local journal under .ai/.runtime/ and a human reviews it with hivelore report list before anything reaches a public tracker. Never put secrets or customer code in a report.

EVIDENCE BAR: kind='bug' REQUIRES a runnable repro. Without one the report is still kept, but filed as 'suggestion' — an unreproducible bug claim cannot be acted on.

DEDUPLICATED: reports are fingerprinted on kind+surface+summary. If you get back already_reported=true, the point is already made — do not rephrase and send it again. The occurrence count is what ranks it for the maintainer.

PARAMETERS: kind — bug | suggestion | docs | confusing surface — the Hivelore tool or command involved (e.g. 'mem_save', 'enforce check') summary — one specific line stating the problem (this is the dedup key) expected — what you expected Hivelore to do observed — what it actually did (exact message or output) repro — a command/tool call that reproduces it, runnable as-is (required for 'bug')

RETURNS: { ok, kind, fingerprint, occurrences, already_reported, notice? }

NameRequiredDescriptionDefault
kindYes'bug' = Hivelore did the wrong thing (REQUIRES `repro`; without one it is filed as a suggestion); 'suggestion' = an improvement idea; 'docs' = the documentation was wrong or missing; 'confusing' = it worked but the output/naming misled you.
reproNoThe command or tool call that reproduces it, runnable as-is. Required to file a 'bug'.
summaryYesOne line stating the problem, as specifically as you can. This is the dedup key.
surfaceYesThe Hivelore surface involved — an MCP tool or CLI command, e.g. 'mem_save', 'enforce check', 'sensors propose'. Used to group reports, so name the tool, not the file.
expectedNoWhat you expected Hivelore to do.
observedNoWhat it actually did — the exact message or output.
scaffold_testA

Generate a PENDING post-incident test from a lesson (attempt/gotcha) — the on-ramp to a command sensor. A command sensor routes YOUR test as its oracle, but someone has to write it; this writes the skeleton so you only fill in the assertion.

USE THIS right after mem_tried when the mistake is behavioural (a regex can't express it): it writes a stub carrying the incident's provenance and returns the exact sensors propose --kind test command to arm it.

It DOES NOT arm a sensor — propose_sensor stays the sole validated writer, and the stub is left PENDING (todo/skip) so the suite stays green until you write the assertion. Monorepo-aware: the framework and location come from the package that owns the lesson's anchor paths.

PARAMETERS: memory_id — the attempt/gotcha to scaffold from framework — vitest | jest | pytest | gotest (auto-detected when omitted) out_path — override the test file path (repo-relative) write — write the file (default true); false returns the content for preview

RETURNS: { ok, path, run_command, propose_command, content, written, already_exists, notice }

NameRequiredDescriptionDefault
styleNoTest shape (default 'example'): 'property' states the invariant once and checks it over many generated inputs (fast-check/Hypothesis); 'differential' asserts the subject agrees with a `reference` implementation for all inputs. Both lower the cost of expressing the invariant.
writeNoWrite the file to disk (default). false = return the content for preview without writing.
red_refNoPre-fix incident commit/ref. When set, the scaffold names the symbols the fix (<red_ref>..HEAD) touched within the lesson's anchor scope and pre-fills the example around them, so the assertion is a targeted edit rather than a blank page. A bad ref falls back to the generic template.
out_pathNoOverride the generated test file path (repo-relative).
frameworkNoTest framework. Auto-detected from the package that owns the lesson's anchor paths when omitted.
memory_idYesId of the attempt/gotcha lesson to scaffold a post-incident test from.
referenceNoRequired for style='differential': import specifier of the reference implementation to compare against.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 6 tool updatesv0.65.0
    • Changedget_briefing4 fields changed
      • addedInput schema / properties / context_reset
        Added value: +{
        +  "description": "Set after compaction to restore context without resetting task attribution.",
        +  "type": "boolean"
        +}
      • removedInput schema / properties / max_memories / exclusiveMinimum
        Removed value: -0
      • addedInput schema / properties / max_memories / minimum
        Added value: +0
      • addedInput schema / properties / session_id
        Added value: +{
        +  "description": "Stable harness session ID; isolates consultation and context delivery.",
        +  "type": "string"
        +}
    • Addedmem_feedback
    • Changedmem_get1 field changed
      • addedInput schema / properties / session_id
        Added value: +{
        +  "description": "Hook session id to credit this complete read to",
        +  "type": "string"
        +}
    • Changedmem_save3 fields changed
      • addedInput schema / properties / checks
        Added value: +{
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "contains": {
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "excludes": {
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "path": {
        +        "minLength": 1,
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "path"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / evidence
        Added value: +{
        +  "enum": [
        +    "hypothesis",
        +    "observed",
        +    "reproduced",
        +    "tested"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / supersedes
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
    • Changedmem_session_end1 field changed
      • addedInput schema / properties / session_id
        Added value: +{
        +  "description": "Task session to checkpoint independently of the rolling recap.",
        +  "type": "string"
        +}
    • Changedmem_update3 fields changed
      • addedInput schema / properties / checks
        Added value: +{
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "contains": {
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "excludes": {
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "path": {
        +        "minLength": 1,
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "path"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / evidence
        Added value: +{
        +  "enum": [
        +    "hypothesis",
        +    "observed",
        +    "reproduced",
        +    "tested"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / supersedes
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
  2. 1 tool updatev0.62.0
    • Changedpropose_sensor2 fields changed
      • addedInput schema / properties / exclude
        Added value: +{
        +  "default": [],
        +  "description": "Glob-ish paths the sensor must NOT fire on, even inside `paths`. Set this for a PRODUCTION-ONLY lesson so it skips test doubles/fixtures — e.g. exclude ['**/*.test.*','**/*.spec.*','**/__tests__/**','**/*.stories.*','**/*.d.ts']. Leave empty for a lesson that IS about tests (it should still fire there). Documentation files (.md/.rst/…) are already skipped automatically.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • changedInput schema / properties / kind / description
        Previous value: -"regex = pattern matched on added diff lines (default). ast = an ast-grep STRUCTURAL pattern (e.g. 'stripe.paymentIntents.create($$$)') matched on the AST of changed files — comments and strings can never false-positive; `absent` is a sub-pattern that must be missing INSIDE the match (requires the optional @ast-grep/napi engine). shell|test = a COMMAND the gate runs when the diff touches the sensor's paths — routes the team's own oracle (an existing test, an invariant script) to this lesson. Command sensors only execute where enforcement.runCommandSensors=true."New value: +"regex = pattern matched on added diff lines (default; comments are stripped before matching, but string literals are NOT — so a regex can still target a bad literal in a string). ast = an ast-grep STRUCTURAL pattern (e.g. 'stripe.paymentIntents.create($$$)') matched on the AST of changed files — comments AND strings can never false-positive, so PREFER ast for a parseable language (JS/TS, Python, Go, Java, Rust, …) when the @ast-grep/napi engine is available; `absent` is a sub-pattern that must be missing INSIDE the match (requires that optional engine). shell|test = a COMMAND the gate runs when the diff touches the sensor's paths — routes the team's own oracle (an existing test, an invariant script) to this lesson. Command sensors only execute where enforcement.runCommandSensors=true."
  3. 1 tool updatev0.57.8
    • Changedget_briefing1 field changed
      • changedInput schema / properties / min_semantic_score / description
        Previous value: -"Drop semantic-only memory hits whose cosine score is below this threshold. Useful to avoid weakly-related noise when the task is short or the corpus is broad. Has no effect on memories matched via anchor/module/literal — those are always kept. Try 0.25–0.4 for stricter matching."New value: +"Floor for semantic-only memory hits (cosine). The default (0) is not 'keep everything': on a corpus large enough to characterize a distribution, an adaptive floor at the corpus mean+½σ is applied so the undifferentiated mass of weak hits is trimmed while the top hit is always kept. Set an explicit value to raise the bar further; it never lowers the adaptive one. Has no effect on memories matched via anchor/module/literal — those are always kept."
  4. 2 tool updatesv0.57.7
    • Changedmem_save1 field changed
      • addedInput schema / properties / lifecycle
        Added value: +{
        +  "description": "Does this describe code that EXISTS now, or a decision not yet built? 'applied' (default) = reflected in the code; 'planned' = decided but NOT yet implemented (surfaced distinctly so agents don't write code against it as if it were real); 'abandoned' = rejected, kept so it isn't re-tried.",
        +  "enum": [
        +    "applied",
        +    "planned",
        +    "abandoned"
        +  ],
        +  "type": "string"
        +}
    • Changedpropose_sensor2 fields changed
      • addedInput schema / properties / replace
        Added value: +{
        +  "default": false,
        +  "description": "Set true to DELIBERATELY replace a sensor already hand-authored on this memory. Without it, a second proposal onto a memory that already carries a validated sensor is REFUSED — otherwise the second call silently destroys the first while still answering accepted:true. One memory holds one sensor; use a separate memory for a second, distinct symptom.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / require_present
        Added value: +{
        +  "default": false,
        +  "description": "kind=regex: make this a REQUIRED-PRESENCE invariant instead of a forbidden-pattern one. `pattern` then names a line that must REMAIN in the anchored file; the sensor FIRES when a change REMOVES it. Use for 'do not delete this critical line' lessons a diff-of-added-lines sensor cannot see. Validated by requiring the pattern to be PRESENT in the current anchored code (there must be something to guard).",
        +  "type": "boolean"
        +}
  5. 2 tool updatesv0.1.1
    • Addedmem_update
    • Addedreport_friction
  6. 13 tool updatesv0.1.0
    • First observedcode_map
    • First observedcode_search
    • First observedget_briefing
    • First observedmem_get
    • First observedmem_relevant_to
    • First observedmem_save
    • First observedmem_search
    • First observedmem_session_end
    • First observedmem_tried
    • First observedmem_verify
    • First observedpre_commit_check
    • First observedpropose_sensor
    • First observedscaffold_test

TDQS

A4/5.0

Scored across 16 tools

Disambiguation4/5

The core retrieval tools (get_briefing, mem_relevant_to, mem_search, mem_get) overlap in purpose, but the descriptions explicitly stage them via progressive disclosure and state when to prefer each. mem_save vs mem_tried, code_map vs code_search, and propose_sensor vs scaffold_test are clearly differentiated. Only minor residual ambiguity remains in the memory-retrieval cluster.

Naming Consistency4/5

A clear mem_* family (mem_save, mem_get, mem_update, mem_verify, mem_search, etc.) and a code_* family (code_map, code_search) give strong internal consistency, with verb_noun style elsewhere. A few standalone names (get_briefing, pre_commit_check, report_friction) break the prefix grouping, but everything stays readable.

Tool Count4/5

16 tools is at the upper edge of a comfortable set, spanning memory CRUD, code intelligence, validation, sensors, and feedback. Most tools earn their place, though report_friction and the sensor pair lean toward feature sprawl for a memory server. Slightly heavy but defensible.

Completeness4/5

Strong lifecycle coverage: create (mem_save/mem_tried), read (mem_get/mem_search/get_briefing), update (mem_update), verify (mem_verify), feedback, session recap, sensors, and pre-commit gating. The notable gap is the absence of any explicit delete/archive/forget operation, and no list-all primitive, but these are minor.

Maintenance

ActivityActive
ResponsivenessNo recent community issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Gives AI coding assistants persistent memory, safety controls, and project awareness by tracking coding sessions, protecting critical files from modifications, and managing approval workflows with automatic changelog generation.
    19
    16 npm
    MIT
  • F
    license
    A
    quality
    D
    maintenance
    Provides real-time policy enforcement for AI coding agents by intercepting and validating their actions against organizational standards like naming conventions, security policies, and compliance rules before execution. Prevents violations through immediate feedback and auto-correction suggestions.
    5
    -