Skip to content

fix: walk up directory tree to find manifest.json - #107

Open
mdbraber wants to merge 1 commit into
obsidianmd:masterfrom
mdbraber:fix/manifest-lookup-monorepo
Open

mdbraber wants to merge 1 commit into
obsidianmd:masterfrom
mdbraber:fix/manifest-lookup-monorepo

Conversation

@mdbraber

Copy link
Copy Markdown

Summary

  • Instead of only looking for manifest.json in process.cwd(), walk up the directory tree until a valid Obsidian plugin manifest is found (identified by having an id field)
  • Silently return null when no manifest is found, removing the console.error that fires in monorepo setups
  • Existing behavior is preserved: when no manifest is found, isDesktopOnly rules default to the safer option (Node.js imports disallowed, no Node globals)

Motivation

In monorepo setups (e.g., pnpm workspaces with Turborepo), ESLint often runs from the workspace root or a sub-package directory — neither of which contains manifest.json. The current code logs a noisy console.error("Failed to load JSON file:", err) every time, even though this is expected and harmless.

The walk-up approach mirrors how tools like ESLint itself find config files — start at cwd and check each parent directory. The id field check ensures we only match actual Obsidian plugin manifests, not unrelated manifest.json files (e.g., Chrome extensions).

Test plan

  • Existing 274 tests pass without modification
  • Verify in a monorepo where manifest.json is in a parent directory
  • Verify in a standard single-package setup (manifest.json in cwd — same behavior as before)
  • Verify no console.error output when manifest.json is absent

🤖 Generated with Claude Code

Instead of only looking for manifest.json in the current working
directory, walk up the directory tree until a valid Obsidian plugin
manifest is found (identified by having an `id` field).

This fixes noisy console.error output in monorepo setups where ESLint
runs from a workspace root or sub-package that doesn't contain
manifest.json directly. The plugin now silently returns null when no
manifest is found, which preserves the existing fallback behavior
(Node.js imports are disallowed, no Node globals added).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Mar 20, 2026

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@mdbraber

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

github-actions Bot added a commit that referenced this pull request Mar 20, 2026
@joethei

joethei commented Mar 20, 2026

Copy link
Copy Markdown
Contributor

I don't like how this walks up the directory tree indefinitely, there should be a limit.

@mdbraber

Copy link
Copy Markdown
Author

@joethei what would be reasonable limit? if we consider monorepo package structure I would say 2 or 3 would suffice? Or should it be configurable?

Comment thread lib/manifest.ts
cachedManifest = null;
return cachedManifest;
}
cachedManifest = findManifest(process.cwd());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
cachedManifest = findManifest(process.cwd());
return findManifest(process.cwd());

Comment thread lib/manifest.ts
return parsed as PluginManifest;
}
} catch {
// File doesn't exist or isn't valid JSON — keep walking.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is ignoring too many errors. We should distinguish between when the file doesn't exist and when a manifest file is invalid JSON. Let's maintain the existing behavior when the JSON manifest file we find is invalid.

Comment thread lib/manifest.ts
}

const parent = path.dirname(dir);
if (parent === dir) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should likely not traverse outside of a Git repo either. Check if the directory is a git root and if so stop traversing.

Comment thread lib/manifest.ts
// Obsidian plugin manifests always have an `id` field —
// skip unrelated manifest.json files (e.g. Chrome extensions).
if (parsed && typeof parsed === "object" && typeof parsed.id === "string") {
return parsed as PluginManifest;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should warn if we find a valid manifest.json that does not include a valid ID. Otherwise that becomes unexpectedly invisible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants