EveryInc/compound-engineering-plugin · error · Error
Local plugin path not found: ${directPath}
Error message
Local plugin path not found: ${directPath} What it means
When the `--plugin` argument to `cleanup` looks like a filesystem path (starts with `.`, `/`, or `~`), `resolveCleanupPluginPath` expands `~` and resolves it, then checks existence. If the resolved directory does not exist on disk it throws this error with the fully resolved path, so the message shows exactly where it looked.
Source
Thrown at src/commands/cleanup.ts:661
}
function resolveCleanupTargets(targetArg: string): CleanupTarget[] {
if (targetArg === "all") return [...cleanupTargets]
const targets = targetArg.split(",").map((entry) => entry.trim()).filter(Boolean)
for (const target of targets) {
if (!cleanupTargets.includes(target as CleanupTarget)) {
throw new Error(`Unknown cleanup target: ${target}. Use one of: ${cleanupTargets.join(", ")}, all`)
}
}
return targets as CleanupTarget[]
}
async function resolveCleanupPluginPath(input: string): Promise<string> {
if (input.startsWith(".") || input.startsWith("/") || input.startsWith("~")) {
const expanded = expandHome(input)
const directPath = path.resolve(expanded)
if (await pathExists(directPath)) return directPath
throw new Error(`Local plugin path not found: ${directPath}`)
}
const repoRoot = fileURLToPath(new URL("../..", import.meta.url))
const rootManifestPath = path.join(repoRoot, ".claude-plugin", "plugin.json")
if (await pathExists(rootManifestPath)) {
try {
const raw = await fs.readFile(rootManifestPath, "utf8")
const manifest = JSON.parse(raw) as { name?: string }
if (manifest.name === input) return repoRoot
} catch {
// Fall through to legacy multi-plugin layout.
}
}
const legacyPluginPath = path.join(repoRoot, "plugins", input)
const legacyManifestPath = path.join(legacyPluginPath, ".claude-plugin", "plugin.json")
if (await pathExists(legacyManifestPath)) return legacyPluginPath
View on GitHub (pinned to c9c10f8c75)
Solutions
- Check the resolved path printed in the error exists: ls <path>/.claude-plugin/plugin.json.
- Run the command from the directory you based the relative path on, or switch to an absolute path.
- If you meant the bundled plugin rather than a local checkout, omit the leading ./, / or ~ and pass the plugin name (e.g. --plugin compound-engineering).
Example fix
// before (run from repo root, but plugin lives elsewhere) bun run src/index.ts cleanup --plugin ./plugins/compound-engineering // Error: Local plugin path not found: /repo/plugins/compound-engineering // after bun run src/index.ts cleanup --plugin /absolute/path/to/compound-engineering
Defensive patterns
Strategy: validation
Validate before calling
import { existsSync } from "node:fs"
import { resolve } from "node:path"
const direct = resolve(input.replace(/^~(?=\/|$)/, process.env.HOME ?? ""))
if (input.startsWith(".") || input.startsWith("/") || input.startsWith("~")) {
if (!existsSync(direct)) throw new Error(`Plugin path does not exist: ${direct}`)
if (!existsSync(direct + "/.claude-plugin/plugin.json")) throw new Error(`Missing plugin manifest at ${direct}`)
} Type guard
function isExistingPluginPath(p: string): p is string & { __pluginDir: true } {
return existsSync(p) && existsSync(path.join(p, ".claude-plugin", "plugin.json"))
} Try / catch
try {
await cleanup({ plugin: pluginArg })
} catch (e) {
if (e instanceof Error && e.message.startsWith("Local plugin path not found:")) {
console.error(`Path ${e.message.split(": ")[1]} does not exist. Check CWD and spelling.`)
} else throw e
} Prevention
- Prefer absolute paths for --plugin in scripts; relative paths resolve against the current working directory.
- Verify the directory contains .claude-plugin/plugin.json before passing it.
- Remember `~` inside quotes may not be expanded by the shell — the CLI expands it, but test in your environment.
When it happens
Trigger: Passing `--plugin ./nonexistent`, `--plugin ~/plugins/compound-engineering` when the directory was moved/deleted, or an absolute path with a typo. The path must also be a loadable plugin dir for later steps, but this specific error fires purely on non-existence of the resolved path.
Common situations: Relative path run from the wrong working directory ("./" resolves against CWD); a checkout deleted or relocated after cloning; `~` expansion pointing at another user's home in CI; Windows-style paths that don't resolve on the host OS.
Related errors
- Local plugin path not found: ${directPath}
- Plugin directory not found: ${pluginPath}
- Cleanup currently supports only the compound-engineering plu
- Unknown cleanup target: ${target}. Use one of: ${cleanupTarg
- Unknown bundled plugin: ${input}
AI-assisted analysis of EveryInc/compound-engineering-plugin@c9c10f8c75 (2026-08-31).
Data as JSON: /api/errors/3b68493e96053e5c.
Report an issue: GitHub.