TypeScript API and binary installer for pj - a fast project finder.
- Dual-purpose package: Works as both a global CLI tool and a TypeScript library
- Automatic binary management: Downloads and manages the pj binary automatically
- Smart binary resolution: Prefers globally installed pj, falls back to managed binary
- Full TypeScript support: Complete type definitions for all APIs
- Cross-platform: Works on macOS, Linux, and Windows
npm install -g @joe-sh/pjThen use pj directly:
pj --iconsnpm install @joe-sh/pjimport { Pj, discover } from '@joe-sh/pj';
// Using the class-based API
const pj = new Pj();
const projects = await pj.discover();
console.log(projects);
// Using standalone functions
const allProjects = await discover();
// Find a specific project
const myProject = await pj.findProject('my-app');
// Search for projects by pattern
const reactProjects = await pj.findProjects(/react/i);
// Get projects grouped by marker type
const byMarker = await pj.discoverByMarker();
console.log(byMarker.get('package.json')); // All Node.js projectsconst projects = await pj.discover({
// Search paths
paths: ['~/projects', '~/code'],
// Project markers to detect
markers: ['.git', 'package.json', 'go.mod'],
// Patterns to exclude
excludes: ['node_modules', 'vendor'],
// Maximum search depth
maxDepth: 3,
// Include icons in output
icons: true,
// Bypass cache
noCache: true,
});import { Pj, loadConfig, saveConfig } from '@joe-sh/pj';
// Load existing configuration
const config = await loadConfig();
// Create instance with custom config
const pj = new Pj({
paths: ['~/my-projects'],
maxDepth: 5,
});
// Save configuration
await pj.saveConfig();import { Pj, getBinaryManager } from '@joe-sh/pj';
const pj = new Pj();
// Check binary status
const status = await pj.getBinaryStatus();
console.log(status);
// { available: true, path: '/usr/local/bin/pj', version: '1.4.1', source: 'global' }
// Ensure binary is available (downloads if needed)
const binaryPath = await pj.ensureBinary();
// Update to latest version
await pj.updateBinary();
// Get version
const version = await pj.getBinaryVersion();const pj = new Pj();
// Clear the project cache
await pj.clearCache();
// Get cache info
const info = await pj.getCacheInfo();
console.log(info);
// { exists: true, path: '~/.cache/pj', fileCount: 3, totalSize: 4096 }The main class for interacting with pj.
new Pj(config?: Partial<PjConfig>)| Method | Description |
|---|---|
discover(options?) |
Discover all projects |
discoverFromPaths(paths, options?) |
Discover projects from specific paths |
findProject(name, options?) |
Find a project by name |
findProjects(pattern, options?) |
Find projects matching a pattern |
discoverByMarker(options?) |
Get projects grouped by marker type |
countByMarker(options?) |
Count projects by marker type |
clearCache() |
Clear the pj project cache |
getCacheInfo() |
Get information about the pj cache |
loadConfig(path?) |
Load configuration from file |
saveConfig(config?, path?) |
Save configuration to file |
getConfig() |
Get current configuration |
setConfig(config) |
Update configuration |
ensureBinary(options?) |
Ensure the pj binary is available |
getBinaryStatus() |
Get the status of the pj binary |
updateBinary(options?) |
Update the pj binary |
getBinaryVersion() |
Get the version of the pj binary |
| Function | Description |
|---|---|
discover(options?) |
Discover all projects |
discoverFromPaths(paths, options?) |
Discover from specific paths |
findProject(name, options?) |
Find a project by name |
findProjects(pattern, options?) |
Find projects by pattern |
discoverByMarker(options?) |
Group projects by marker |
countByMarker(options?) |
Count projects by marker |
loadConfig(path?) |
Load configuration |
saveConfig(config, path?) |
Save configuration |
clearCache() |
Clear the project cache |
getCacheInfo() |
Get cache information |
getBinaryManager() |
Get the binary manager instance |
interface Project {
path: string; // Absolute path to the project
name: string; // Project name (directory name)
marker: string; // Marker that identified this project
icon?: string; // Optional Nerd Font icon
priority?: number; // Marker priority
}
interface DiscoverOptions {
paths?: string[];
markers?: string[];
excludes?: string[];
maxDepth?: number;
noIgnore?: boolean;
nested?: boolean;
noCache?: boolean;
icons?: boolean;
configPath?: string;
verbose?: boolean;
}
interface PjConfig {
paths: string[];
markers: string[];
exclude: string[];
maxDepth: number;
cacheTTL: number;
noIgnore: boolean;
noNested: boolean;
icons: Record<string, string>;
}
interface BinaryStatus {
available: boolean;
path: string | null;
version: string | null;
source: 'global' | 'cache' | 'env' | null;
}| Variable | Description |
|---|---|
PJ_BINARY_PATH |
Override the pj binary path |
PJ_SKIP_INSTALL |
Skip binary download during npm install |
PJ_INSTALL_BINARY |
Force binary download in CI environments |
This package tracks the pj CLI version using a major.minor pinning strategy:
| This package | Compatible pj versions |
|---|---|
1.4.x |
1.4.0, 1.4.1, 1.4.2, ... |
1.5.x |
1.5.0, 1.5.1, 1.5.2, ... |
How it works:
- This package stays in sync with pj's major.minor version
- Patch versions (the third number) are independent — patches to this package are for TypeScript wrapper bug fixes, not pj CLI changes
- When you install or update, the package automatically downloads the latest compatible pj patch within your major.minor range
What this means for you:
@joe-sh/[email protected]will install the latestpj 1.4.x(e.g.,1.4.5if available)- When pj
1.5.0is released, upgrade to@joe-sh/[email protected]to get the new features
The package looks for the pj binary in this order:
PJ_BINARY_PATHenvironment variable- Globally installed
pjin PATH (if version-compatible) - Cached binary in
~/.cache/pj-node/(if version-compatible) - Downloads from GitHub releases (highest compatible version)
- Node.js 20.0.0 or higher
MIT