{"record":{"id":"f3841fe1b6d08979","repo":"can1357/oh-my-pi","slug":"project-scoped-install-requires-running-inside-a-p","errorCode":null,"errorMessage":"project-scoped install requires running inside a project directory","messagePattern":"project-scoped install requires running inside a project directory","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/extensibility/plugins/marketplace/manager.ts","lineNumber":870,"sourceCode":"\t\tconst config = await this.#loadRuntimeConfig(scope);\n\t\tdelete config.plugins[packageName];\n\t\tdelete config.settings[packageName];\n\t\tawait this.#writeRuntimeConfig(scope, config);\n\t}\n\n\tasync #setRuntimePluginEnabled(scope: \"user\" | \"project\", packageName: string, enabled: boolean): Promise<void> {\n\t\tconst config = await this.#loadRuntimeConfig(scope);\n\t\tconst previous = config.plugins[packageName];\n\t\tif (!previous) return;\n\n\t\tconfig.plugins[packageName] = { ...previous, enabled };\n\t\tawait this.#writeRuntimeConfig(scope, config);\n\t}\n\n\t#registryPath(scope: \"user\" | \"project\"): string {\n\t\tif (scope === \"project\") {\n\t\t\tif (!this.#opts.projectInstalledRegistryPath) {\n\t\t\t\tthrow new Error(\"project-scoped install requires running inside a project directory\");\n\t\t\t}\n\t\t\treturn this.#opts.projectInstalledRegistryPath;\n\t\t}\n\t\treturn this.#opts.installedRegistryPath;\n\t}\n\n\tasync #findInBothRegistries(pluginId: string): Promise<{\n\t\tuserEntries: InstalledPluginEntry[] | undefined;\n\t\tprojectEntries: InstalledPluginEntry[] | undefined;\n\t\tuserReg: InstalledPluginsRegistry;\n\t\tprojectReg: InstalledPluginsRegistry;\n\t}> {\n\t\tconst [userReg, projectReg] = await Promise.all([\n\t\t\treadInstalledPluginsRegistry(this.#opts.installedRegistryPath),\n\t\t\tthis.#opts.projectInstalledRegistryPath\n\t\t\t\t? readInstalledPluginsRegistry(this.#opts.projectInstalledRegistryPath)\n\t\t\t\t: Promise.resolve({ version: 2 as const, plugins: {} as Record<string, InstalledPluginEntry[]> }),\n\t\t]);","sourceCodeStart":852,"sourceCodeEnd":888,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/extensibility/plugins/marketplace/manager.ts#L852-L888","documentation":"MarketplaceManager.#registryPath() returns the file path of the installed-plugins registry for a scope. For the \"project\" scope it relies on the projectInstalledRegistryPath option, which is only provided when the manager was constructed inside a recognizable project directory. When that option is absent, any project-scoped operation throws this error.","triggerScenarios":"Calling installPlugin(name, marketplace, {scope:\"project\"}), uninstall with project scope, or any code path that resolves the project registry while the manager was constructed without a project directory (e.g. in a home directory, tmp, or SDK embedding without projectInstalledRegistryPath).","commonSituations":"Running a project-scoped install from outside a git/project root; CI jobs executing in a bare workspace without project detection; embedding the MarketplaceManager programmatically without passing projectInstalledRegistryPath.","solutions":["cd into a project directory (one that yields a project registry path) and retry","Use user scope instead: {scope: \"user\"}","If embedding the manager, pass projectInstalledRegistryPath in the constructor options"],"exampleFix":"// before\nawait manager.installPlugin(\"myplugin\", \"community\", { scope: \"project\" }); // run in ~/\n// after\ncd ~/my-project   # or:\nawait manager.installPlugin(\"myplugin\", \"community\", { scope: \"user\" });","handlingStrategy":"fallback","validationCode":"// ensure a project registry path is available before project-scope ops\nconst inProject = Boolean(projectRoot && projectInstalledRegistryPath);\nconst scope = inProject ? 'project' : 'user';","typeGuard":"null","tryCatchPattern":"try {\n  await manager.installPlugin(name, marketplace, { scope: 'project' });\n} catch (err) {\n  if (err.message.includes('requires running inside a project directory')) {\n    await manager.installPlugin(name, marketplace, { scope: 'user' });\n  } else throw err;\n}","preventionTips":["cd into the project root before project-scoped installs","Pass projectInstalledRegistryPath when constructing the manager in embedded/SDK contexts","Default scripts to user scope when project context is uncertain","Detect project root (git root / config file) before choosing scope"],"tags":["plugin","configuration","scope"],"backgroundTag":"missing-project-context","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}