{"record":{"id":"4b8409e64c09618d","repo":"upstash/context7","slug":"fix-permissions-with","errorCode":null,"errorMessage":"Fix permissions with:","messagePattern":"Fix permissions with:","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/skill.ts","lineNumber":464,"sourceCode":"          throw dirErr;\n        }\n      }\n\n      installedSkills.push(`${skill.project}/${skill.name}`);\n    } catch (err) {\n      const error = err as NodeJS.ErrnoException;\n      if (error.code === \"EACCES\" || error.code === \"EPERM\") {\n        continue;\n      }\n      const errMsg = err instanceof Error ? err.message : String(err);\n      log.warn(`Failed to install ${skill.name}: ${errMsg}`);\n    }\n  }\n\n  if (permissionError) {\n    installSpinner.fail(\"Permission denied\");\n    log.blank();\n    log.warn(\"Fix permissions with:\");\n    for (const dir of failedDirs) {\n      const parentDir = join(dir, \"..\");\n      log.dim(`  sudo chown -R $(whoami) \"${parentDir}\"`);\n    }\n    log.blank();\n    return;\n  }\n\n  installSpinner.succeed(`Installed ${installedSkills.length} skill(s)`);\n  trackEvent(\"install\", { skills: installedSkills, ides: targets.ides });\n\n  const installedNames = selectedSkills.map((s) => s.name);\n  logInstallSummary(targets, targetDirs, installedNames);\n}\n\nasync function searchCommand(query: string): Promise<void> {\n  trackEvent(\"command\", { name: \"search\" });\n  log.blank();","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/upstash/context7/blob/5284672feb575908efead6fcf1b5e542f8d607bb/packages/cli/src/commands/skill.ts#L446-L482","documentation":"During the skill install loop, writes into target directories (agent skill folders such as ~/.claude/skills or project paths) threw Node filesystem errors with code EACCES or EPERM. The loop records permissionError and the failed directories, fails the spinner with 'Permission denied', and prints 'Fix permissions with:' followed by a `sudo chown -R $(whoami) <parentDir>` line per failing directory.","triggerScenarios":"Target skill directory (or its parent) is owned by root or another user — typically because it was created earlier via sudo; read-only mount or macOS-protected path; container/CI environment where the CLI user lacks write access to the home or project dir.","commonSituations":"Previously ran the CLI (or the agent) with sudo, leaving root-owned ~/.claude or .agents directories; installing into a project directory on a read-only bind mount; locked-down corporate macOS home directories.","solutions":["Run exactly the suggested command for each listed directory: `sudo chown -R $(whoami) \"<parentDir>\"`, then retry the install.","Alternatively pick a writable target: install to project scope instead of global, or vice versa, via the target flags.","Never run `context7` itself with sudo — it creates root-owned config/skill dirs that cause exactly this error later.","In containers/CI, ensure the runtime user owns the HOME and working directory."],"exampleFix":"// before (common cause): running the CLI elevated creates root-owned dirs\nsudo ctx7 skill add owner/repo\n// after: fix ownership once, then always run unprivileged\nsudo chown -R $(whoami) ~/.claude\nctx7 skill add owner/repo","handlingStrategy":"try-catch","validationCode":"import { access, constants } from \"node:fs/promises\";\n\n// Pre-check write access to every target dir before installing\nfor (const dir of targetDirs) {\n  try {\n    await access(dir, constants.W_OK);\n  } catch {\n    console.error(`No write permission for ${dir} - fix ownership first (sudo chown -R $(whoami) \"${dir}/..\").`);\n    process.exit(1);\n  }\n}","typeGuard":"function isPermissionError(err: unknown): err is NodeJS.ErrnoException {\n  return (\n    err instanceof Error &&\n    (err as NodeJS.ErrnoException).code === \"EACCES\" ||\n    (err as NodeJS.ErrnoException).code === \"EPERM\"\n  );\n}","tryCatchPattern":"try {\n  await writeFile(targetPath, content, \"utf8\");\n} catch (err) {\n  if (isPermissionError(err)) {\n    permissionError = true;\n    failedDirs.add(dir);\n    continue; // collect all failing dirs, report once at the end\n  }\n  throw err;\n}","preventionTips":["Never run the CLI with sudo - it creates root-owned config/skill directories that trigger EACCES later.","If a previous sudo run caused this, run the printed `sudo chown -R $(whoami) <parentDir>` once and retry.","In CI/containers, ensure the process user owns HOME and the project directory.","Pre-check W_OK access on target directories before starting the install loop."],"tags":["cli","skills","filesystem","permissions","eacces","install"],"backgroundTag":"permission-denied-eacces","analyzedSha":"5284672feb575908efead6fcf1b5e542f8d607bb","analyzedAt":"2026-08-18T18:00:18.510Z","schemaVersion":2},"datasetVersion":"2026-08-24T22:17:12.610Z"}