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

@liendev/core

v0.76.0

Published

Core indexing and analysis engine for Lien

Downloads

3,577

Readme

@liendev/core

Core indexing and analysis engine for Lien. This package provides the low-level APIs for structural code intelligence (dependency analysis, complexity metrics, and test associations), plus fast lexical (FTS5/BM25) code search over a local SQLite store. No embeddings, no model download.

Installation

npm install @liendev/core

Usage

import {
  indexCodebase,
  createVectorDB,
  ComplexityAnalyzer,
} from '@liendev/core';

// Index a codebase into the local SQLite structural store
await indexCodebase({
  rootDir: '/path/to/project',
});

// Open the structural store for the project
const db = await createVectorDB('/path/to/project');
await db.initialize();

// Run lexical (FTS5/BM25) keyword search
const results = await db.search('authenticate session token', 10);

// Analyze complexity
const analyzer = new ComplexityAnalyzer(db);
const report = await analyzer.analyze();

console.log(`Found ${report.summary.totalViolations} complexity violations`);

API reference

Indexing

indexCodebase(options: IndexingOptions): Promise<IndexingResult>

Index a codebase for lexical (FTS5) search and structural analysis. Chunks are parsed from the AST, enriched with complexity metrics and dependency metadata, and written to a local SQLite database. There is no embedding step.

interface IndexingOptions {
  rootDir?: string;           // Root directory (default: cwd)
  force?: boolean;            // Force full reindex (default: false)
  verbose?: boolean;          // Verbose output (default: false)
  config?: LienConfig;        // Pre-loaded config
  onProgress?: (progress: IndexingProgress) => void;  // Progress callback
}

interface IndexingResult {
  filesIndexed: number;
  chunksCreated: number;
  timeMs: number;
}

Example:

const result = await indexCodebase({
  rootDir: './my-project',
  force: true,
  onProgress: (progress) => {
    console.log(`Indexed ${progress.filesCompleted}/${progress.totalFiles} files`);
  },
});

console.log(`Indexed ${result.filesIndexed} files in ${result.timeMs}ms`);

Storage backend

Lien stores chunks in a local SQLite database behind the VectorDBInterface seam. createVectorDB() constructs the backend (currently always the SQLite structural store); the seam exists so an alternative backend can be introduced without touching call sites.

createVectorDB(rootDir: string): Promise<VectorDBInterface>

const db = await createVectorDB('./my-project');
await db.initialize();

db.search(query: string, limit?: number): Promise<SearchResult[]>

Perform lexical (FTS5/BM25) keyword search. The query text is tokenized and matched against symbol names, identifier-split symbol tokens, and chunk content; results are ranked by BM25. This is keyword search, not meaning-based: a paraphrase that shares no vocabulary with the code will not match. limit defaults to 5.

const results = await db.search('error handling retry backoff', 10);

Complexity analysis

new ComplexityAnalyzer(db: VectorDBInterface)

Create a complexity analyzer. Uses default thresholds (no config needed).

const analyzer = new ComplexityAnalyzer(db);

analyzer.analyze(files?: string[]): Promise<ComplexityReport>

Analyze code complexity. Optionally filter to specific files.

// Analyze all files
const report = await analyzer.analyze();

// Analyze specific files
const report = await analyzer.analyze(['src/utils.ts', 'src/parser.ts']);

console.log(`${report.summary.totalViolations} violations found`);
console.log(`Average complexity: ${report.summary.avgComplexity}`);

Complexity report structure

interface ComplexityReport {
  summary: {
    filesAnalyzed: number;
    totalViolations: number;
    bySeverity: { error: number; warning: number };
    avgComplexity: number;
    maxComplexity: number;
  };
  files: Record<string, FileComplexityData>;
}

interface FileComplexityData {
  violations: ComplexityViolation[];
  dependents: string[];        // Files that import this file
  testAssociations: string[];  // Test files covering this file
  // Own complexity severity, boosted (never downgraded) by dependent
  // count/complexity -- NOT the same concept as get_dependents'/`lien
  // annotate`'s blast-radius `riskLevel` (no test-coverage term here at
  // all). Serialized as `complexityRiskLevel` in `lien complexity
  // --format json` / `get_complexity`'s MCP response.
  riskLevel: 'low' | 'medium' | 'high' | 'critical';
}

interface ComplexityViolation {
  filepath: string;
  startLine: number;
  endLine: number;
  symbolName: string;
  symbolType: 'function' | 'method' | 'class' | 'file';
  language: string;
  complexity: number;
  threshold: number;
  severity: 'warning' | 'error';
  metricType: 'cyclomatic' | 'cognitive' | 'halstead_effort' | 'halstead_bugs';
  halsteadDetails?: HalsteadDetails;
}

Configuration

Lien no longer requires per-project configuration files. It uses:

  • Global config at ~/.lien/config.json (optional, for backend selection)
  • Environment variables (LIEN_BACKEND, LIEN_HOME)
  • Auto-detected ecosystems
  • Sensible defaults for all settings

For more details, see the Configuration Guide.

createDefaultConfig(): LienConfig

Create a default configuration.

const config = createDefaultConfig();

Git utilities

import {
  isGitRepo,
  getCurrentBranch,
  getCurrentCommit,
  getChangedFiles,
} from '@liendev/core';

const isGit = await isGitRepo('./my-project');
const branch = await getCurrentBranch('./my-project');
const commit = await getCurrentCommit('./my-project');
const changed = await getChangedFiles('./my-project');

Advanced usage

Progress tracking

Monitor indexing progress in real-time:

await indexCodebase({
  rootDir: './large-project',
  onProgress: (progress) => {
    const pct = (progress.filesCompleted / progress.totalFiles * 100).toFixed(1);
    console.log(`[${pct}%] ${progress.filesCompleted}/${progress.totalFiles} files`);
  },
});

Supported languages

TypeScript / JavaScript, Python, PHP, Rust, Go, Java, C#, Ruby, Kotlin, Swift, and more. See the main README for the full list.

Performance

  • Storage: SQLite (better-sqlite3, synchronous C binding), ~1.8MB native install
  • Search: SQLite FTS5 with BM25 ranking (porter + unicode61 tokenizer)
  • Chunking: AST-based with fallback to line-based
  • File context lookup: sub-millisecond (indexed WHERE file IN (...))

Architecture

@liendev/core
├── indexer/         # Indexing orchestration: manifest, incremental updates
├── vectordb/        # Storage backend behind VectorDBInterface + factory
│   └── sqlite/      #   SQLite structural store + FTS5/BM25 lexical search
├── insights/        # Complexity analysis
├── config/          # Configuration management
└── git/             # Git utilities

Who uses this?

Currently, @liendev/lien (the Lien CLI and MCP server).

Links