ultraworkers/claw-code · error · std::io::Error
unable to resolve a skills install root; set CLAW_CONFIG_HOM
Error message
unable to resolve a skills install root; set CLAW_CONFIG_HOME or HOME
What it means
`default_skill_install_root` (commands/src/lib.rs:3851) resolves the install registry by checking `CLAW_CONFIG_HOME`, then `CODEX_HOME`, then `HOME` (falling back to `~/.claw/skills`). If none of the three is set it returns `ErrorKind::NotFound` with this message. It is hit by `install_skill` and `uninstall_skill`, i.e. `/skills install` and `/skills uninstall`.
Source
Thrown at rust/crates/commands/src/lib.rs:3851
),
)?;
Ok(CreatedAgent { name, path })
}
fn default_skill_install_root() -> std::io::Result<PathBuf> {
if let Ok(claw_config_home) = env::var("CLAW_CONFIG_HOME") {
return Ok(PathBuf::from(claw_config_home).join("skills"));
}
if let Ok(codex_home) = env::var("CODEX_HOME") {
return Ok(PathBuf::from(codex_home).join("skills"));
}
if let Some(home) = env::var_os("HOME") {
return Ok(PathBuf::from(home).join(".claw").join("skills"));
}
Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
"unable to resolve a skills install root; set CLAW_CONFIG_HOME or HOME",
))
}
fn resolve_skill_install_source(source: &str, cwd: &Path) -> std::io::Result<SkillInstallSource> {
let candidate = PathBuf::from(source);
let source = if candidate.is_absolute() {
candidate
} else {
cwd.join(candidate)
};
let source = fs::canonicalize(&source).map_err(|e| {
std::io::Error::new(
e.kind(),
format!("skill source '{}' not found: {e}", source.display()),
)
})?;
if source.is_dir() {View on GitHub (pinned to 08106b0c37)
Solutions
- Export CLAW_CONFIG_HOME to a writable dir (it takes priority): `export CLAW_CONFIG_HOME=$HOME/.claw`.
- Otherwise export HOME: `export HOME=/root` (root becomes `$HOME/.claw/skills`).
- In containers/services, set the variable in the unit file or Dockerfile ENV so the claw process always inherits it.
Example fix
# before /skills install ./my-skill # unable to resolve a skills install root; set CLAW_CONFIG_HOME or HOME # after export CLAW_CONFIG_HOME="$HOME/.claw" /skills install ./my-skill
Defensive patterns
Strategy: validation
Validate before calling
fn skill_root_ok() -> bool {
std::env::var_os("CLAW_CONFIG_HOME").is_some()
|| std::env::var_os("CODEX_HOME").is_some()
|| std::env::var_os("HOME").is_some()
} Try / catch
match install_skill(source, cwd) {
Err(e) if e.kind() == std::io::ErrorKind::NotFound
&& e.to_string().contains("skills install root") => {
// set CLAW_CONFIG_HOME/HOME and retry once
}
other => other,
} Prevention
- Always launch claw with CLAW_CONFIG_HOME set to a writable dir
- In containers/systemd units add ENV HOME or Environment=CLAW_CONFIG_HOME
- Never run claw under `env -i` without re-exporting HOME
When it happens
Trigger: Running `/skills install <src>` or `/skills uninstall <name>` in a process whose environment has none of CLAW_CONFIG_HOME, CODEX_HOME, or HOME defined.
Common situations: Minimal Docker containers without a HOME for the runtime user; systemd/launchd services with a scrubbed environment; CI jobs using `env -i`; test harnesses that clear the environment; `setenv -u HOME` shells.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- skill source '{}' not found: {e}
- skill directory '{}' must contain SKILL.md
- skill source '{}' must be a directory with SKILL.md or a mar
- unable to derive an installable invocation name from '{}'
- HOME is not set (on Windows, set USERPROFILE or HOME, or use
AI-assisted analysis of ultraworkers/claw-code@08106b0c37 (2026-08-18).
Data as JSON: /api/errors/e4553e3cf770b5e3.
Report an issue: GitHub.