npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

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

About

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

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

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

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

Open Software & Tools

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

© 2026 – Pkg Stats / Ryan Hefner

@luxia/core

v0.0.8

Published

Agnos core CLI and plugin framework

Downloads

1,328

Readme

@luxia/core

npm version node license

The core of agnos. Ships the CLI binary, the plugin loader, the orchestrator, and every public type that agent and domain plugins build against.

What it provides

  • The agnos CLI binary. Parses commands, builds a ResolveContext, loads plugins, and dispatches.
  • The plugin loader. Walks the project's node_modules for any package with an "agnos" field in its package.json and registers it.
  • The orchestrator. Coordinates per-domain resolve and per-agent materialize lifecycles, with idempotent re-runs and per-agent cleanup.
  • Cross-platform filesystem primitives. A Linker that probes for symlink privileges and falls back to junctions or copies, plus a RepoFetcher for git and local skill sources.
  • The public type surface that agent and domain plugins import: AgentPlugin, DomainPlugin, ResolveContext, MaterializeContext, and every resolved-item shape.

Install

You usually install @luxia/agnos instead. Install @luxia/core directly only when you are building a plugin and need the types and helpers:

pnpm add -D @luxia/core

In a plugin's package.json:

{
  "peerDependencies": {
    "@luxia/core": "^0.0.5"
  }
}

Public API

Everything is named-exported from the package root. The most common entry points:

import type {
  AgentPlugin,
  DomainPlugin,
  ResolveContext,
  MaterializeContext,
  ResolvedRule,
  ResolvedMcp,
  ResolvedSkill,
  Logger,
} from "@luxia/core";

import {
  // CLI and orchestration
  loadPlugins,
  reconcile,
  reinstate,
  activateAgent,
  materializeAgent,
  cleanupAgent,

  // Config and state
  readConfig,
  writeConfig,
  readState,
  writeState,

  // Paths
  buildPaths,
  findProjectRoot,
  AGNOS_DIR,
  CONFIG_FILE,
  STATE_FILE,

  // Sources and fetching
  parseSource,
  createRepoFetcher,
  resolveGitCommit,

  // Skills
  findSkillsInRepo,
  hashSkillDir,
  prepareSkills,

  // Filesystem
  createLinker,
  ensureLink,

  // Logging
  createLogger,
} from "@luxia/core";

Plugin contracts

Agent plugin

import type { AgentPlugin } from "@luxia/core";

const plugin: AgentPlugin = {
  id: "myagent",
  displayName: "My Agent",
  paths: { skillsDir: ".myagent/skills" },
  handles: {
    rules: {
      async onInitialize(state, ctx) {
        /* materialize */
      },
      async onCleanup(ctx) {
        /* strip */
      },
    },
    mcp: {
      async onInitialize(state, ctx) {
        /* regenerate */
      },
      async onCleanup(ctx) {
        /* strip */
      },
    },
  },
};

export default plugin;

The full interface lives in src/types/public.ts.

Domain plugin

import type { DomainPlugin } from "@luxia/core";
import { z } from "zod";

const plugin: DomainPlugin = {
  name: "prompts",
  priority: 50,
  declarationSchema: z.object({
    /* ... */
  }),
  async resolve(decl, ctx) {
    /* ... */
  },
  async add(input, ctx) {
    /* ... */
  },
  async remove(name, ctx) {
    /* ... */
  },
};

export default plugin;

Built-in domain priorities: rules=10, mcp=20, skills=30, docs=40. Lower runs first on activation; higher runs first on cleanup.

Discovery

agnos finds plugins by scanning node_modules for any package whose package.json contains:

{
  "agnos": {
    "type": "agent",
    "id": "myagent"
  }
}

type is "agent" or "domain". id is the short name users put in agnos.json#agents or that the orchestrator uses to route domain handlers. The package's default export is the plugin object. No registration call. No central allowlist.

When two installed plugins claim the same id, agnos errors at startup and asks the user to disambiguate via { id, package } in agnos.json#agents.

ResolveContext

Every plugin handler receives a ResolveContext (or MaterializeContext, which extends it). It contains everything a plugin should need without reaching into the filesystem on its own:

interface ResolveContext {
  agnosRoot: string; // absolute path of .agnos/
  projectRoot: string; // absolute path of the project
  cacheDir: string; // absolute path of .agnos/cache/
  configPath: string; // absolute path of agnos.json
  statePath: string; // absolute path of .agnos/state.json
  logger: Logger; // info / success / warn / error / debug
  fetcher: RepoFetcher; // git + local source fetching
  linker: Linker; // cross-platform symlink + fallback
  dryRun?: boolean; // when true, plugins log "would: ..." and skip side effects
  indent?: string; // prepended to wrapped logger output inside hooks
}

Plugins should never construct paths from process.cwd(). Always go through ctx.

Lifecycle

The orchestrator iterates domains by ascending priority for activation and descending for cleanup. For each agent:

  1. domain.onInitialize(ctx) runs once per project (gated by .agnos/state.json).
  2. domain.resolve(declaration, ctx) produces ResolvedRule/ResolvedMcp/etc.
  3. domain.onAgentActivate(agent, activeAgents, ctx) lets the domain bootstrap declarative agent paths (this is how paths.skillsDir becomes a symlink).
  4. agent.handles.<domain>.onInitialize(state, ctx) materializes the resolved state for this agent.

On removal, step 4 becomes onCleanup, step 3 becomes onAgentDeactivate, and everything runs in reverse priority order.

Every step must be idempotent. Re-running agnos install on a clean tree should produce zero output.

License

MIT.