@vortex-os/base
v0.18.41
Published
Base entry point for VortEX — a Multi-Agent Personal AI Work OS framework
Maintainers
Readme
@vortex-os/base
__ __ _ _____ __
\ \ / ___ _ _| |_| __\ \/ /
\ V / _ | '_| _| _| > <
\_/\___|_| \__|___/_/\_\
Vortex absorbs context · EX executes itBase entry point for VortEX — a Multi-Agent Personal AI Work OS framework.
@vortex-os/base bundles the framework's 14 internal workspaces (core utilities, slash-command runtime, memory store, daily-log store, decision-log store, runbook store, link-rewriter, index-generator, data-linter, report-generator, two catalog modules, the proactive-curator proposal engine, and the session-rituals plugin) into a single installable package. Install once, get the whole framework.
Install
Install the framework, plus the optional @vortex-os/memory-extended add-on for semantic recall (drop it if you don't want search):
npm install @vortex-os/base @vortex-os/memory-extendedOn Windows PowerShell? If
npmfails with a script-execution /UnauthorizedAccesserror, that's PowerShell's default policy blocking npm's wrapper script — not a VortEX problem (it blocks every npm command). Fix it one of these ways: runnpm.cmd install …instead ofnpm install …, or usecmd.exe, or enable scripts once withSet-ExecutionPolicy -Scope CurrentUser RemoteSigned -Forceand retry.
Quick start
@vortex-os/base ships a vortex CLI. Two ways to a working instance:
Easiest — let your agent do it. In a new folder, open your coding agent (Claude Code, Codex, …) and tell it — keep the literal vortex init, don't translate or paraphrase it: "install @vortex-os/base and @vortex-os/memory-extended, then run vortex init." (Before the rule files exist the agent has no VortEX context, so a paraphrase like "initialize vortex" can be misread as a generic project setup; the exact vortex init avoids that.) The agent installs the packages and runs init (which asks for your name and role; what you're working on is optional). Then restart the agent in that folder so it loads the freshly created rule files (CLAUDE.md, AGENTS.md, …) and session hooks — agents read those only at startup. Bonus: the agent runs npm in its own shell, so the Windows PowerShell issue above never comes up.
Manual — three steps:
npm install @vortex-os/base @vortex-os/memory-extended # framework + semantic-recall add-on
npx vortex init # scaffold the instance (asks name + role; task optional)
# then open your agent (e.g. `claude`) in that folder — a fresh start loads the rules init just creatednpx vortex init is non-destructive and creates, in the current folder:
- the per-agent files —
AGENTS.md(the thin Codex-CLI entry, auto-loaded by Codex and otherAGENTS.md-aware tools) plus thin routersCLAUDE.md,GEMINI.md,.cursorrules, all pointing atAI-RULES.md(the single source of truth for shared rules) — so any agent host finds VortEX's behavior contract (these are generic templates you personalize over time); - the
data/skeleton (_memory/,worklog/,decision-log/,runbooks/,hubs/,inbox/), your user-profile memory, and today's first worklog; .claude/settings.jsonwith the session hooks wired asnpx --no-install vortex session-start/… session-end(the--no-installflag makes the auto-firing hook fail closed rather than install on a cache miss; resolving the barevortexbin — localnode_modules/.binfirst, then PATH — lets theglobal-setuphook fire from any folder, not only where a local install exists), the write-guard hook (vortex guard write— denies literal control bytes in file writes; remove itsPreToolUsegroup to opt out), plus the agent-mediated slash-commands in.claude/commands/;.agent/vortex.json(auto-record config) and a minimalpackage.jsonwith"type":"module"if none exists.
vortex import --from <folder> brings an existing notes folder in — markdown is auto-classified (worklog / decision-log / …) and attachments (PDFs, images, …) are copied byte-for-byte into the same layout; credential files (*.key, .env, secrets/ …) and oversized files are skipped and reported. As the framework improves, vortex update refreshes the installed templates without ever overwriting a file you edited (your edit is parked at <file>.new); vortex doctor checks instance health.
Pass the answers inline to skip the prompts:
npx vortex init --name "Alex" --role "engineer" --task "set up my work notes"Other CLI entry points (all run base-only — /recall lights up only when the optional add-on is installed):
npx vortex --list # list available commands
npx vortex status # instance state report
npx vortex import --from X # bring an existing notes folder into data/
npx vortex session-start # start-of-session boot report (git pull + counts + catch-up)
npx vortex session-end # no-op (kept for hook compatibility; gap handling is at session-start)
npx vortex doctor # health diagnosis
npx vortex update # refresh framework templates (never clobbers your edits)
npx vortex statusline # Claude Code status-bar renderer (see below)
npx vortex failure # failure ledger: record / list (the self-improvement loop)
npx vortex source-map # queryable map of your own source code: index / find / add-target / note / stats
npx vortex dashboard # local read-only status dashboard (see below)Which instance do these record to? In order: VORTEX_REPO_ROOT if set, else the
current folder when it is itself an instance, else the nearest enclosing
instance — the closest ancestor carrying .agent/vortex.json — else the global
pointer from vortex global-setup, else the current folder. The enclosing-instance
step is what makes a command (or a session hook) run from a
project folder inside an instance record to that instance; before it, such a run
treated the project folder as a root of its own and created a nested data/ tree
there. Behavior change to know about: if you use global-setup and work inside
a second instance's subfolder, that work now records to the instance you are
standing in rather than to the global one — set VORTEX_REPO_ROOT if you want the
global instance everywhere.
Self-improvement loop (failure ledger)
Rules saved in data/_memory/ are loaded at session start — but at action time
the model's attention is on the task, and a registered rule can still slip.
VortEX therefore counts: when the agent's own failure becomes visible (you
correct it, a test disproves it, a cross-check catches it), the agent records
it with vortex failure record --key <root-cause-key> --what "<one line>"
into data/_failures/ (append-only, one file per occurrence). Recurrence is
machine-counted per key and escalates on a ladder:
- 1st occurrence — recorded.
- 2nd, while a rule already covers it — that rule's write-time gate becomes mandatory.
- 3rd+ — the agent must propose a deterministic defense (a hook, a pre-commit check, a wrapper) — proposals only, nothing self-installs.
A guard_denied entry — an installed guard blocking the mistake — stays
visible in the counts (shown as ×N (+M guard-blocked)) but no longer drives
the ladder: escalation runs on unblocked occurrences only, so a working
defense doesn't re-trigger "propose a defense" for the class it already
covers.
The session-start report surfaces recurring keys automatically, and promoting
a lesson into _memory/ requires evidence links, a replay check ("would this
rule have prevented the recorded cases?") and your approval. Disable with
autoRecord.failures: false in .agent/vortex.json.
Guards ship in the box — vortex init wires them as Claude Code hooks:
vortex guard write(PreToolUse) denies file writes containing literal control bytes (escape notation always works instead) — a denial also records itself into the ledger.vortex guard risky-action(PreToolUse/Bash) turnsnpm/pnpm/yarn publishandgit pushinto a user-confirmation prompt carrying the instance's related failure-ledger counts plus a checklist — it asks, never denies. With the@vortex-os/ontosadd-on installed, the prompt also reads the knowledge graph and says "this failure class recurred ×N — covering rule: X / defense: Y", so accumulated lessons are consumed at the decision point (read-only, best-effort; absent add-on changes nothing). Turn a rule off withguards.publishAsk/guards.pushAsk: false, the graph lines withguards.graphContext: false, in.agent/vortex.json.vortex guard memory-router(UserPromptSubmit) spots a decision-why / recurrence-why / past-record question and nudges the agent to ground the answer in your records (decision chain, failure ledger,/recall) before replying.
All are fail-open (a guard bug never blocks your work) and opt-out by removing
their hook group in .claude/settings.json.
Source map (your code, queryable)
"Does my X do Y? Where is it implemented?" should be an indexed lookup, not a
fresh grep — or worse, an unverified assertion. vortex source-map index
scans the repos listed in .agent/vortex.json → sourceMap.targets
(zero-config default: the instance's own code folders) into a disposable,
machine-local SQLite index (data/_indexes/source-map.sqlite; needs Node ≥
22.5 for the built-in sqlite — older runtimes get a clear error and nothing
else is affected). Generic columns (solution · system · feature ·
kind) let one DB serve many programs; every row carries file:line, the
signature, and the preceding doc comment as a primary-source pointer.
find <term>answers from the index (--jsonfor agents) and marks stale targets; freshness is automatic — each target's git HEAD is fingerprinted at index time, andfind/session-start kick a detached background reindex when the code moved.add-target <repo-root>registers a repo mechanically (atomic write, dedup) — agents propose it the moment code work touches an unmapped repo.note --feature --claimrecords a capability answer the agent just verified from code into a separate overlay DB, stamped with the repo fingerprint and marked STALE once the code moves — LLM output never lands in the canonical index.
The regex indexer is an honest 80%: a symbol it misses is still a grep away, and an important claim still closes by reading the pointed-at file.
Status dashboard (vortex dashboard)
A LOCAL, read-only web page over the instance's data/ — record counts, active
handoffs, recurring failures, the ontos knowledge graph, code-map visualization,
health checks. Loopback only (127.0.0.1), never writes to your data, and no
extra installs (Node built-ins).
npx vortex dashboard # start (or confirm) this instance's dashboard
npx vortex dashboard status # running? whose? which version?
npx vortex dashboard stop # stop THIS instance's server (never another's)
npx vortex dashboard enable # auto-launch at session start (recorded in .agent/vortex.json)
npx vortex dashboard disable # never auto-launch, never re-offerNothing starts without a yes: until you decide, the session-start report carries
a one-time offer; enable/disable records the answer (dashboard.autoLaunch)
so it is never re-asked. Auto-launched servers stop on their own when the last
AI session closes. Two instances on one machine never touch each other's server
(identity is checked before any restart/stop); use dashboard.port to run them
side by side. The internal-structure pipeline docs (session lifecycle, transcript
flow, extraction tiers, …) ship with the package and appear in the drawer menu on
every install; an optional dashboard.pagesDir serves your own docs/diagram pages
from inside the instance and overrides the shipped copies per file. The
knowledge-graph pages (/graph, per-item mining on /extraction) light up when
the @vortex-os/ontos add-on is installed — without it they show a plain install
notice instead of an error.
Two of those pages answer different questions and are deliberately separate.
/graph draws the instance's own facts — every object and typed relation it knows.
/ontology draws the SCHEMA instead: the object types with their live counts, the
relations as nodes between them, and the domain/range rule table with each rule's
actual usage, so a relation that is allowed but has never been used shows up as an
unconnected node rather than a zero buried in a table. Because a schema holds no
individual facts, clicking a type or a relation lists its real instances and jumps
straight into /graph focused on the one you pick — the two layers stay separate
but never disconnected. Items with no relations are marked in that list before you
click, since the graph only draws what is connected.
Claude Code status bar (on by default)
vortex statusline renders a colored status bar for Claude Code's statusLine setting — model + a reasoning-effort meter (one bar whose height/color encode low→ultracode), a context-window gauge with used/total tokens, a clock, session cost, the 5-hour/7-day rate-limit gauges with time-to-reset, cache hit-rate, project + git branch/commit, session duration, lines changed, the number of open Claude Code sessions (best-effort process count) — and, inside a VortEX instance, the framework version and the latest worklog file:
🧠 Fable 5 │ █ max │ █░░░░░░░░░ 12% · 120K/1M │ 🕐 22:25 │ 💰 $9.22
5h ██████░░ 75%(1h9m) │ 7d ███████░ 96%(7h30m) │ 📦 cache 99%
📁 my-project │ ⎇ main 2b0949d │ ⏱ 1h26m │ +90 -49 │ ⧉ 1
🌀 VortEX │ last: 2026-06-10_0452-notes.mdThe bar is wired automatically by vortex init (new instances) and vortex update (existing instances) — merge-safe: a bar you already configured is kept untouched, and it is offered only once (delete the statusLine entry from .claude/settings.json and it stays deleted). To wire it by hand, switch forms, or replace a foreign bar:
npx vortex statusline install # full bar (4 lines inside an instance, 3 outside)
npx vortex statusline install --lite # compact 1-line bar
npx vortex statusline install --force # replace a non-VortEX bar explicitlyLibrary usage
import {
core,
slashCommands,
memorySystem,
worklog,
decisionLog,
proactiveCurator,
sessionRituals,
} from "@vortex-os/base";
// Use the slash-rituals registry against your own data directory
const registry = sessionRituals.createRitualRegistry();
const ctx = core.makeContext(process.cwd());
await slashCommands.runSlash("/session-start", { registry, context: ctx });Opt-in /curate surface
The /curate command is opt-in because it needs a host-supplied LLM adapter. To enable it on Claude Code, wire a sub-agent invoker:
import { proactiveCurator, sessionRituals } from "@vortex-os/base";
const llm = new proactiveCurator.ClaudeCodeLLMJudge(async ({ prompt }) => {
// Host-specific sub-agent invocation; return the sub-agent's raw answer.
return await invokeMySubAgent(prompt);
});
const registry = sessionRituals.createRitualRegistry({
curate: {
llm,
// Optional — supply the in-session insight surface with recent turns.
insightInputProvider: () => ({
recentTurns: myTurnBuffer.recent(20),
accumulatedTokens: myTurnBuffer.tokenCount(),
}),
},
});Without an LLMJudge, /curate is simply absent (graceful degradation); the rest of the rituals work unchanged.
Exported namespaces
Each internal workspace is exposed as a top-level namespace on the package:
| Namespace | Source workspace | Role |
|---|---|---|
| core | @vortex-os/core | Frontmatter parser (BOM-safe), three-tier privacy filter, ModuleContext path resolver, shared types |
| slashCommands | @vortex-os/slash-commands | Command, CommandRegistry, runSlash primitives |
| memorySystem | @vortex-os/memory-system | Markdown-frontmatter memory store + MEMORY.md index writer + diff helpers |
| dataLint | @vortex-os/data-lint | Pluggable linter for markdown directories (frontmatter / privacy / wiki-link checks) |
| aiCodingPitfalls | @vortex-os/ai-coding-pitfalls | Typed catalog of AI coding pitfall patterns |
| toolRules | @vortex-os/tool-rules | Typed catalog of tool usage rules |
| reportGenerator | @vortex-os/report-generator | HTML reports with privacy-marker section filtering |
| worklog | @vortex-os/worklog | Daily work-log store with year/month layout. Entries carry started: / finished: (HH:MM) plus a spans: list for multi-unit days, so work time can be summed from observed clocks |
| decisionLog | @vortex-os/decision-log | Decision-log store with template-driven entry creation |
| indexGenerator | @vortex-os/index-generator | _INDEX.md rendering (flat + nested modes) |
| runbooks | @vortex-os/runbooks | Runbook store with last_tested-based stale detection |
| linkRewriter | @vortex-os/link-rewriter | Wiki-link extract / resolve / check / rewrite |
| proactiveCurator | @vortex-os/proactive-curator | Topic-aware proposal engine — in-session insight capture + hub auto-curation with 4-action active placement (create-folder / create-file / append-section / update-file). Asymmetric LLM gate for hub thresholds (3 weak / 5 strong). Decline durability + Claude Code LLMJudge adapter. |
| sessionRituals | @vortex-os/session-rituals | Daily session-loop slash commands: /session-start, /log, /handoff, /decision, /agenda, /reindex, /resume, /vortex, /curate, /recall |
Capability add-ons
Future capability clusters publish as siblings under the @vortex-os scope and install alongside the base. The base auto-detects installed add-ons at session-start:
@vortex-os/memory-extended— shipped — six namespaces are live:sqlite(structured index + drift detection),vector(brute-force cosine backend, localmultilingual-e5-smallembedder),recall(two-stage hybrid/recallover memories and conversation sessions),sessionArchive(four first-party host adapters: Claude Code, Codex, Gemini, Claude Desktop),consolidate(post-session memory-candidate proposer), andmcp(an MCP server,vortex-mcp-recall, exposing memory tools over stdio). Peer-depends on this base. See memory-extended-design.md.@vortex-os/dev-toolkit(planned) — vibe coding + self-QA + CI/CD assistance.@vortex-os/vision(under consideration) — screen context + visual reasoning.
Each add-on installs alongside the base and extends what the agent can do without forcing a base upgrade.
Privacy & network behavior
vortex initfolder scan. To suggest content you might want to import,initdoes a read-only scan for common notes-folder names (e.g. an Obsidian vault, anotes/directory) under your home directory. It only reads directory listings to count Markdown files and surface a hint — it never copies, modifies, or transmits anything. Import happens only when you explicitly runvortex import --from <path>.- One optional update check. By default base runs a single npm-registry version check once per session at session start (
npm view @vortex-os/base version) to tell you whether a newer version is published — nothing is installed automatically. Offline → silent skip; disable entirely withupdates: { check: "off" }in.agent/vortex.json. Base makes no other outbound network requests. With the optional@vortex-os/memory-extendedadd-on installed, base sets semantic recall up the first time by downloading an embedding model (~470 MB once, read-onlyGETfromhuggingface.co) — in the background, so it never blocks session start. This is on by default (installing the add-on is the opt-in); to keep that download manual on a metered line or in CI, setautoRecord.vectorizeAutoDownload: falsein.agent/vortex.json(or envVORTEX_VECTORIZE_AUTO_DOWNLOAD=0) and set it up yourself withvortex vectorize//recall. The model is cacheable / offline-able viaHF_HUB_OFFLINE=1. The add-on also feeds transcript excerpts to whatever LLM adapter you wire into its consolidation step. See that package's README for details.
Packaging notes
- Bundled: all 14 workspaces are bundled into the published artifact via
tsup. Consumers do not need to install workspace packages individually. - External dependency:
yamlis left as a runtime dependency (npm resolves it on install). - Format: ESM only.
"type": "module"in your consumer is required (or set up.mjs). - Types: a single
dist/index.d.tsexposes all namespace types.
Related
- VortEX framework repository — source, design docs, integration template for instances
- Capability-cluster packaging design — how the framework splits into installable clusters
- Memory-extended design — memory-extended add-on design reference
License
MIT — see LICENSE.
