
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
infiniloom-node
Advanced tools
Node.js bindings for Infiniloom - AST-aware code context engine for RAG and vector databases. Tree-sitter parsing, PageRank ranking, BLAKE3 content-addressable chunks, 27+ tokenizers.
Node.js bindings for Infiniloom - Repository context engine for LLMs.
npm install infiniloom-node
git clone https://github.com/Topos-Labs/infiniloom.git
cd infiniloom/bindings/node
npm install
npm run build
const { pack } = require('infiniloom-node');
// Pack a repository with default settings
const context = pack('./my-repo');
console.log(context);
const { pack } = require('infiniloom-node');
const context = pack('./my-repo', {
format: 'xml', // Output format: 'xml', 'markdown', 'json', 'yaml', 'toon', or 'plain'
model: 'claude', // Target model: 'gpt-5.2', 'gpt-5.1', 'gpt-5', 'o3', 'gpt-4o', 'claude', 'gemini', 'llama', etc.
compression: 'balanced', // Compression: 'none', 'minimal', 'balanced', 'aggressive', 'extreme', 'focused', 'semantic'
mapBudget: 2000, // Token budget for repository map
maxSymbols: 50, // Maximum symbols to include in map
skipSecurity: false, // Skip security scanning
redactSecrets: true, // Redact detected secrets in output (default true)
skipSymbols: false, // Skip symbol extraction for faster scans
include: ['src/**/*.ts'], // Glob patterns to include
exclude: ['**/*.test.ts'], // Glob patterns to exclude
includeTests: false, // Include test files (default: false)
securityThreshold: 'critical', // Minimum severity to block: 'critical', 'high', 'medium', 'low'
tokenBudget: 50000 // Limit total output tokens (0 = no limit)
});
const { scan, scanWithOptions } = require('infiniloom-node');
// Simple scan with model
const stats = scan('./my-repo', 'claude');
console.log(`Repository: ${stats.name}`);
console.log(`Total files: ${stats.totalFiles}`);
console.log(`Total lines: ${stats.totalLines}`);
console.log(`Total tokens: ${stats.totalTokens}`);
console.log(`Primary language: ${stats.primaryLanguage}`);
console.log(`Languages:`, stats.languages);
// Advanced scan with options
const detailedStats = scanWithOptions('./my-repo', {
model: 'gpt-4o',
include: ['src/**/*.ts'], // Include only TypeScript source files
exclude: ['**/*.test.ts'], // Exclude test files
includeTests: false, // Exclude test directories
applyDefaultIgnores: true // Apply default ignores (node_modules, dist, etc.)
});
const { countTokens } = require('infiniloom-node');
const count = countTokens('Hello, world!', 'claude');
console.log(`Tokens: ${count}`);
const { semanticCompress } = require('infiniloom-node');
// Compress text while preserving important content
const longText = '... your long text content ...';
const compressed = semanticCompress(longText, 0.7, 0.5);
// Parameters:
// - text: The text to compress
// - similarityThreshold (optional): 0.0-1.0, default 0.7
// - budgetRatio (optional): 0.0-1.0, default 0.5
console.log(compressed);
const { Infiniloom } = require('infiniloom-node');
// Create an Infiniloom instance
const loom = new Infiniloom('./my-repo', 'claude');
// Get statistics
const stats = loom.getStats();
console.log(stats);
// Generate repository map
const map = loom.generateMap(2000, 50);
console.log(map);
// Pack with options (including new features)
const context = loom.pack({
format: 'xml',
compression: 'balanced',
tokenBudget: 50000, // Limit output size
include: ['src/**/*.ts'], // Filter files
exclude: ['**/*.test.ts']
});
console.log(context);
// Security scan - returns structured findings
const findings = loom.securityScan();
if (findings.length > 0) {
console.warn('Security issues found:');
for (const finding of findings) {
console.warn(`${finding.severity}: ${finding.kind} in ${finding.file}:${finding.line}`);
}
}
// Legacy formatted output (if needed)
const formattedFindings = loom.securityScanFormatted();
formattedFindings.forEach(f => console.log(f));
pack(path: string, options?: PackOptions): stringPack a repository into optimized LLM context.
Parameters:
path - Path to repository rootoptions - Optional packing optionsReturns: Formatted repository context as a string
scan(path: string, model?: string): ScanStatsScan a repository and return statistics. Applies default ignores automatically.
Parameters:
path - Path to repository rootmodel - Optional target model (default: "claude")Returns: Repository statistics
scanWithOptions(path: string, options?: ScanOptions): ScanStatsScan a repository with full configuration options.
Parameters:
path - Path to repository rootoptions - Optional scan optionsReturns: Repository statistics
countTokens(text: string, model?: string): numberCount tokens in text for a specific model.
Parameters:
text - Text to tokenize (null/undefined returns 0)model - Optional model name (default: "claude")Returns: Token count (0 for empty, null, or undefined input)
semanticCompress(text: string, similarityThreshold?: number, budgetRatio?: number): stringCompress text using semantic compression while preserving important content.
Parameters:
text - Text to compresssimilarityThreshold - Threshold for grouping similar chunks (0.0-1.0, default: 0.7). Note: Only affects output when built with "embeddings" feature.budgetRatio - Target size as ratio of original (0.0-1.0, default: 0.5). Lower values = more aggressive compression. Affects content as small as 10 characters. Use 1.0 to preserve content unchanged.Returns: Compressed text (may include truncation markers showing percentage and character counts)
scanSecurity(path: string): SecurityFinding[]Scan a repository for security issues (hardcoded secrets, API keys, etc.).
Parameters:
path - Path to repository rootReturns: Array of security findings
const { scanSecurity } = require('infiniloom-node');
const findings = scanSecurity('./my-repo');
for (const finding of findings) {
console.log(`${finding.severity}: ${finding.kind} in ${finding.file}:${finding.line}`);
}
Query caller/callee relationships and navigate your codebase programmatically.
buildIndex(path: string, options?: IndexOptions): IndexStatusBuild or update the symbol index for a repository (required for call graph queries).
const { buildIndex } = require('infiniloom-node');
const status = buildIndex('./my-repo');
console.log(`Indexed ${status.symbolCount} symbols`);
findSymbol(path: string, name: string): SymbolInfo[]Find symbols by name.
const { findSymbol, buildIndex } = require('infiniloom-node');
buildIndex('./my-repo');
const symbols = findSymbol('./my-repo', 'processRequest');
for (const s of symbols) {
console.log(`${s.name} (${s.kind}) at ${s.file}:${s.line}`);
}
getCallers(path: string, symbolName: string): SymbolInfo[]Get all functions/methods that call the target symbol.
const { getCallers, buildIndex } = require('infiniloom-node');
buildIndex('./my-repo');
const callers = getCallers('./my-repo', 'authenticate');
console.log(`authenticate is called by ${callers.length} functions`);
for (const c of callers) {
console.log(` ${c.name} at ${c.file}:${c.line}`);
}
getCallees(path: string, symbolName: string): SymbolInfo[]Get all functions/methods that the target symbol calls.
const { getCallees, buildIndex } = require('infiniloom-node');
buildIndex('./my-repo');
const callees = getCallees('./my-repo', 'main');
console.log(`main calls ${callees.length} functions`);
getReferences(path: string, symbolName: string): ReferenceInfo[]Get all references to a symbol (calls, imports, inheritance).
const { getReferences, buildIndex } = require('infiniloom-node');
buildIndex('./my-repo');
const refs = getReferences('./my-repo', 'UserService');
for (const r of refs) {
console.log(`${r.kind}: ${r.symbol.name} at ${r.symbol.file}:${r.symbol.line}`);
}
getCallGraph(path: string, options?: CallGraphOptions): CallGraphGet the complete call graph with all symbols and call relationships.
const { getCallGraph, buildIndex } = require('infiniloom-node');
buildIndex('./my-repo');
const graph = getCallGraph('./my-repo');
console.log(`${graph.stats.totalSymbols} symbols, ${graph.stats.totalCalls} calls`);
// Find most called functions
const callCounts = new Map();
for (const edge of graph.edges) {
callCounts.set(edge.callee, (callCounts.get(edge.callee) || 0) + 1);
}
const sorted = [...callCounts.entries()].sort((a, b) => b[1] - a[1]);
console.log('Most called:', sorted.slice(0, 5));
All call graph functions have async versions:
findSymbolAsync(path, name)getCallersAsync(path, symbolName)getCalleesAsync(path, symbolName)getReferencesAsync(path, symbolName)getCallGraphAsync(path, options)indexStatus(path: string): IndexStatusGet the status of an existing index.
const { indexStatus } = require('infiniloom-node');
const status = indexStatus('./my-repo');
if (status.exists) {
console.log(`Index has ${status.symbolCount} symbols`);
} else {
console.log('No index found - run buildIndex first');
}
Split large repositories into manageable chunks for multi-turn LLM conversations.
chunk(path: string, options?: ChunkOptions): RepoChunk[]Split repository into chunks for processing with limited context windows.
const { chunk } = require('infiniloom-node');
// Split large repo into manageable chunks
const chunks = chunk('./my-large-repo', {
strategy: 'module',
maxTokens: 50000,
model: 'claude'
});
for (const c of chunks) {
console.log(`Chunk ${c.index + 1}/${c.total}: ${c.focus} (${c.tokens} tokens)`);
// Send c.content to LLM for analysis
}
// Use dependency-aware chunking
const depChunks = chunk('./my-repo', {
strategy: 'dependency',
priorityFirst: true
});
ChunkOptions:
interface ChunkOptions {
strategy?: string; // "fixed", "file", "module", "symbol", "semantic", "dependency"
maxTokens?: number; // Maximum tokens per chunk (default: 8000)
overlap?: number; // Token overlap between chunks (default: 0)
model?: string; // Target model for token counting (default: "claude")
priorityFirst?: boolean; // Sort chunks by file priority (default: false)
}
RepoChunk:
interface RepoChunk {
index: number; // Chunk index (0-based)
total: number; // Total number of chunks
focus: string; // Description of chunk focus
tokens: number; // Token count
files: string[]; // Files in this chunk
content: string; // Combined content
}
Analyze the impact of changes to understand what code is affected.
analyzeImpact(path: string, files: string[], options?: ImpactOptions): ImpactResultAnalyze the impact of changes to files or symbols.
const { analyzeImpact, buildIndex } = require('infiniloom-node');
// Build index first
buildIndex('./my-repo');
// Analyze impact of changing a file
const impact = analyzeImpact('./my-repo', ['src/auth.js']);
console.log(`Impact level: ${impact.impactLevel}`);
console.log(`Summary: ${impact.summary}`);
// See what else needs updating
for (const dep of impact.dependentFiles) {
console.log(` Dependent: ${dep}`);
}
for (const sym of impact.affectedSymbols) {
console.log(` ${sym.impactType}: ${sym.name} in ${sym.file}`);
}
ImpactOptions:
interface ImpactOptions {
depth?: number; // Depth of dependency traversal (1-3, default: 2)
includeTests?: boolean; // Include test files in analysis (default: false)
model?: string; // Target model for token counting (default: "claude")
exclude?: string[]; // Glob patterns to exclude (e.g., ["**/*.test.ts", "dist/**"])
include?: string[]; // Glob patterns to include (e.g., ["src/**/*.ts"])
}
ImpactResult:
interface ImpactResult {
changedFiles: string[];
dependentFiles: string[];
testFiles: string[];
affectedSymbols: AffectedSymbol[];
impactLevel: string; // "low", "medium", "high", "critical"
summary: string;
}
interface AffectedSymbol {
name: string;
kind: string;
file: string;
line: number;
impactType: string;
}
Get semantic context around code changes for AI-powered code review.
getDiffContext(path: string, options?: DiffContextOptions): DiffContextGet context-aware diff with surrounding symbols and dependencies.
const { getDiffContext, buildIndex } = require('infiniloom-node');
// Build index for full context (optional but recommended)
buildIndex('./my-repo');
// Get context for uncommitted changes
const context = getDiffContext('./my-repo');
console.log(`Changed: ${context.changedFiles.length} files`);
// Get context for last commit with diff content
const commitContext = getDiffContext('./my-repo', {
fromRef: 'HEAD~1',
toRef: 'HEAD',
includeDiff: true
});
for (const f of commitContext.changedFiles) {
console.log(`${f.changeType}: ${f.path}`);
if (f.diff) {
console.log(f.diff);
}
}
// Get context for a PR (branch comparison)
const prContext = getDiffContext('./my-repo', {
fromRef: 'main',
toRef: 'feature-branch',
depth: 3
});
console.log(`Related symbols: ${prContext.contextSymbols.length}`);
console.log(`Related tests: ${prContext.relatedTests.length}`);
DiffContextOptions:
interface DiffContextOptions {
fromRef?: string; // Starting ref - "" for unstaged (default)
toRef?: string; // Ending ref - "HEAD" (default)
depth?: number; // Context expansion depth (1-3, default: 2)
budget?: number; // Token budget for context (default: 50000)
includeDiff?: boolean; // Include actual diff content (default: false)
format?: string; // Output format: "xml", "markdown", "json" (default: "xml")
model?: string; // Target model for token counting (default: "claude")
exclude?: string[]; // Glob patterns to exclude (e.g., ["**/*.test.ts", "dist/**"])
include?: string[]; // Glob patterns to include (e.g., ["src/**/*.ts"])
}
DiffContext:
interface DiffContext {
changedFiles: DiffFile[];
contextSymbols: ContextSymbol[];
relatedTests: string[];
totalTokens: number;
}
interface DiffFile {
path: string;
changeType: string;
additions: number;
deletions: number;
diff?: string; // Only if includeDiff is true
}
interface ContextSymbol {
name: string;
kind: string;
file: string;
line: number;
reason: string;
signature?: string;
}
isGitRepo(path: string): booleanCheck if a path is a git repository.
Parameters:
path - Path to checkReturns: true if path is a git repository, false otherwise
const { isGitRepo } = require('infiniloom-node');
if (isGitRepo('./my-project')) {
console.log('This is a git repository');
}
PackOptionsinterface PackOptions {
format?: string; // "xml", "markdown", "json", "yaml", "toon", or "plain"
model?: string; // "gpt-5.2", "gpt-5.1", "gpt-5", "o3", "gpt-4o", "claude", "gemini", "llama", etc.
compression?: string; // "none", "minimal", "balanced", "aggressive", "extreme", "focused", "semantic"
mapBudget?: number; // Token budget for repository map
maxSymbols?: number; // Maximum number of symbols in map
skipSecurity?: boolean; // Skip security scanning
redactSecrets?: boolean; // Redact detected secrets (default: true)
skipSymbols?: boolean; // Skip symbol extraction for faster scanning
include?: string[]; // Glob patterns to include (e.g., ["src/**/*.ts"])
exclude?: string[]; // Glob patterns to exclude (e.g., ["**/*.test.ts"])
includeTests?: boolean; // Include test files (default: false)
securityThreshold?: string;// Minimum severity to block: "critical", "high", "medium", "low"
tokenBudget?: number; // Limit total output tokens (0 = no limit, negative values rejected)
// Git-based filtering options (PR review integration)
changedOnly?: boolean; // Only include files changed in git
baseSha?: string; // Base SHA/ref for diff comparison (e.g., "main", "HEAD~5")
headSha?: string; // Head SHA/ref for diff comparison (default: working tree)
stagedOnly?: boolean; // Include staged changes only
includeRelated?: boolean; // Include related files (importers/dependencies)
relatedDepth?: number; // Depth for related file traversal (1-3, default: 1)
}
ScanOptionsinterface ScanOptions {
model?: string; // Target model for token counting (default: "claude")
include?: string[]; // Glob patterns to include
exclude?: string[]; // Glob patterns to exclude
includeTests?: boolean; // Include test files (default: false)
applyDefaultIgnores?: boolean; // Apply default ignores for dist/, node_modules/, etc. (default: true)
}
ScanStatsinterface ScanStats {
name: string;
totalFiles: number;
totalLines: number;
totalTokens: number;
primaryLanguage?: string;
languages: LanguageStat[];
securityFindings: number;
}
LanguageStatinterface LanguageStat {
language: string;
files: number;
lines: number;
percentage: number;
}
SecurityFindinginterface SecurityFinding {
file: string; // File where the finding was detected
line: number; // Line number (1-indexed)
severity: string; // "Critical", "High", "Medium", "Low", "Info"
kind: string; // Type of finding (e.g., "aws_access_key", "github_token")
pattern: string; // The matched pattern
}
GitCommitinterface GitCommit {
hash: string; // Full commit hash (40 characters)
shortHash: string; // Short commit hash (7 characters)
author: string; // Author name
email: string; // Author email
date: string; // Commit date (ISO 8601 format)
message: string; // Commit message (first line)
}
GitFileStatusinterface GitFileStatus {
path: string; // File path
oldPath?: string; // Old path (for renames)
status: string; // "Added", "Modified", "Deleted", "Renamed", "Copied", "Unknown"
}
GitChangedFileinterface GitChangedFile {
path: string; // File path
oldPath?: string; // Old path (for renames)
status: string; // "Added", "Modified", "Deleted", "Renamed", "Copied"
additions: number; // Number of lines added
deletions: number; // Number of lines deleted
}
GitBlameLineinterface GitBlameLine {
commit: string; // Commit hash that introduced the line
author: string; // Author who wrote the line
date: string; // Date when line was written
lineNumber: number; // Line number (1-indexed)
}
GitDiffLineinterface GitDiffLine {
changeType: string; // "add", "remove", or "context"
oldLine?: number; // Line number in old file (for remove/context)
newLine?: number; // Line number in new file (for add/context)
content: string; // Line content (without +/- prefix)
}
GitDiffHunkinterface GitDiffHunk {
oldStart: number; // Starting line in old file
oldCount: number; // Number of lines in old file
newStart: number; // Starting line in new file
newCount: number; // Number of lines in new file
header: string; // Hunk header (e.g., "@@ -1,5 +1,6 @@ function name")
lines: GitDiffLine[]; // Lines in this hunk
}
new Infiniloom(path: string, model?: string)Create a new Infiniloom instance.
getStats(): ScanStatsGet repository statistics.
generateMap(budget?: number, maxSymbols?: number): stringGenerate a repository map.
pack(options?: PackOptions): stringPack repository with specific options.
securityScan(): SecurityFinding[]Check for security issues and return structured findings.
securityScanFormatted(): string[]Check for security issues and return formatted strings (legacy format).
Git repository wrapper for accessing git operations like status, diff, log, and blame.
new GitRepo(path: string)Open a git repository.
Parameters:
path - Path to the repositoryThrows: Error if path is not a git repository
currentBranch(): stringGet the current branch name.
Returns: Current branch name (e.g., "main", "feature/xyz")
currentCommit(): stringGet the current commit hash.
Returns: Full SHA-1 hash of HEAD commit (40 characters)
status(): GitFileStatus[]Get working tree status (both staged and unstaged changes).
Returns: Array of file status objects
log(count?: number): GitCommit[]Get recent commits.
Parameters:
count - Maximum number of commits to return (default: 10)Returns: Array of commit objects
fileLog(path: string, count?: number): GitCommit[]Get commits that modified a specific file.
Parameters:
path - File path relative to repo rootcount - Maximum number of commits (default: 10)Returns: Array of commits that modified the file
blame(path: string): GitBlameLine[]Get blame information for a file.
Parameters:
path - File path relative to repo rootReturns: Array of blame line objects
lsFiles(): string[]Get list of files tracked by git.
Returns: Array of file paths
diffFiles(fromRef: string, toRef: string): GitChangedFile[]Get files changed between two commits.
Parameters:
fromRef - Starting commit/branch/tagtoRef - Ending commit/branch/tagReturns: Array of changed files with diff stats
uncommittedDiff(path: string): stringGet diff content for uncommitted changes in a file.
Parameters:
path - File path relative to repo rootReturns: Unified diff content
allUncommittedDiffs(): stringGet diff for all uncommitted changes.
Returns: Combined unified diff for all changed files
hasChanges(path: string): booleanCheck if a file has uncommitted changes.
Parameters:
path - File path relative to repo rootReturns: true if file has changes
lastModifiedCommit(path: string): GitCommitGet the last commit that modified a file.
Parameters:
path - File path relative to repo rootReturns: Commit information object
fileChangeFrequency(path: string, days?: number): numberGet file change frequency in recent days.
Parameters:
path - File path relative to repo rootdays - Number of days to look back (default: 30)Returns: Number of commits that modified the file in the period
fileAtRef(path: string, gitRef: string): stringGet file content at a specific git ref (commit, branch, tag).
Parameters:
path - File path relative to repo rootgitRef - Git ref (commit hash, branch name, tag, HEAD~n, etc.)Returns: File content as string
const repo = new GitRepo('./my-project');
const oldVersion = repo.fileAtRef('src/main.js', 'HEAD~5');
const mainVersion = repo.fileAtRef('src/main.js', 'main');
diffHunks(fromRef: string, toRef: string, path?: string): GitDiffHunk[]Parse diff between two refs into structured hunks with line-level changes. Useful for PR review tools that need to post comments at specific lines.
Parameters:
fromRef - Starting ref (e.g., "main", "HEAD~5", commit hash)toRef - Ending ref (e.g., "HEAD", "feature-branch")path - Optional file path to filter to a single fileReturns: Array of diff hunks with line-level change information
const repo = new GitRepo('./my-project');
const hunks = repo.diffHunks('main', 'HEAD', 'src/index.js');
for (const hunk of hunks) {
console.log(`Hunk at old:${hunk.oldStart} new:${hunk.newStart}`);
for (const line of hunk.lines) {
console.log(`${line.changeType}: ${line.content}`);
}
}
uncommittedHunks(path?: string): GitDiffHunk[]Parse uncommitted changes (working tree vs HEAD) into structured hunks.
Parameters:
path - Optional file path to filter to a single fileReturns: Array of diff hunks for uncommitted changes
const repo = new GitRepo('./my-project');
const hunks = repo.uncommittedHunks('src/index.js');
console.log(`${hunks.length} hunks with uncommitted changes`);
stagedHunks(path?: string): GitDiffHunk[]Parse staged changes into structured hunks.
Parameters:
path - Optional file path to filter to a single fileReturns: Array of diff hunks for staged changes only
const repo = new GitRepo('./my-project');
const hunks = repo.stagedHunks('src/index.js');
console.log(`${hunks.length} hunks staged for commit`);
Example:
const { GitRepo, isGitRepo } = require('infiniloom-node');
// Check if path is a git repo first
if (isGitRepo('./my-project')) {
const repo = new GitRepo('./my-project');
// Get current state
console.log(`Branch: ${repo.currentBranch()}`);
console.log(`Commit: ${repo.currentCommit()}`);
// Get recent commits
for (const commit of repo.log(5)) {
console.log(`${commit.shortHash}: ${commit.message}`);
}
// Get file history
for (const commit of repo.fileLog('src/index.js', 3)) {
console.log(`${commit.date}: ${commit.message}`);
}
// Get blame information
for (const line of repo.blame('src/index.js').slice(0, 10)) {
console.log(`Line ${line.lineNumber}: ${line.author}`);
}
// Check for uncommitted changes
if (repo.hasChanges('src/index.js')) {
const diff = repo.uncommittedDiff('src/index.js');
console.log(diff);
}
// Compare branches
const changes = repo.diffFiles('main', 'feature');
for (const file of changes) {
console.log(`${file.status}: ${file.path} (+${file.additions}/-${file.deletions})`);
}
}
Infiniloom automatically scans for sensitive data including:
Critical security issues will prevent packing unless skipSecurity: true is set.
# Install dependencies
npm install
# Build native addon
npm run build
# Build for release
npm run build --release
MIT
FAQs
Node.js bindings for Infiniloom - AST-aware code context engine for RAG and vector databases. Tree-sitter parsing, PageRank ranking, BLAKE3 content-addressable chunks, 27+ tokenizers.
We found that infiniloom-node demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.