Skip to content

paths

paths

Central, env-aware resolution of OpenJarvis' home directory.

OpenJarvis keeps all of its runtime state (config, databases, caches, logs, credentials, skills, recipes, …) under a single root so it never clutters the user's home directory beyond one directory. That root is resolved here, with the following precedence (highest first):

  1. $OPENJARVIS_HOME — explicit override (also honored by the shell installer, see scripts/install/install.sh).
  2. $XDG_DATA_HOME/openjarvis — when $XDG_DATA_HOME is set, follow the XDG Base Directory spec by nesting a single openjarvis directory under it. We deliberately use ONE directory rather than splitting across XDG config/data/cache so the install tree stays self-contained and relocatable.
  3. ~/.openjarvis — the historical default. With no env vars set, the resolved path is exactly this, so existing installs are untouched.

config.py re-exports :func:get_config_dir results through the legacy DEFAULT_CONFIG_DIR/DEFAULT_CONFIG_PATH names (computed dynamically) so the ~45 modules that import those names keep working while honoring the override. Modules that previously hardcoded Path.home() / ".openjarvis" should call :func:get_config_dir (or :func:get_data_dir / :func:get_cache_dir) instead.

Defense in depth: the resolved root must never live inside the OpenJarvis source tree (a misconfigured $OPENJARVIS_HOME pointing at the repo would otherwise scatter runtime artifacts into the working tree). This mirrors the guard in learning/spec_search/storage/paths.py and fails loudly per REVIEW.md's no-silent-failure discipline.

Classes

ConfigurationError

Bases: RuntimeError

Raised when the resolved home directory would violate isolation guarantees.

Functions

get_config_dir

get_config_dir() -> Path

Resolve OpenJarvis' single root directory, honoring env overrides.

Precedence: $OPENJARVIS_HOME > $XDG_DATA_HOME/openjarvis > ~/.openjarvis. The result is always absolute and is rejected if it falls inside the OpenJarvis source tree.

Source code in src/openjarvis/core/paths.py
def get_config_dir() -> Path:
    """Resolve OpenJarvis' single root directory, honoring env overrides.

    Precedence: ``$OPENJARVIS_HOME`` > ``$XDG_DATA_HOME/openjarvis`` >
    ``~/.openjarvis``. The result is always absolute and is rejected if it
    falls inside the OpenJarvis source tree.
    """
    env_home = os.environ.get("OPENJARVIS_HOME")
    if env_home:
        resolved = Path(env_home).expanduser().resolve()
        return _reject_source_tree(resolved)

    xdg_data = os.environ.get("XDG_DATA_HOME")
    if xdg_data:
        resolved = (Path(xdg_data).expanduser() / _XDG_SUBDIR_NAME).resolve()
        return _reject_source_tree(resolved)

    return (Path.home() / _DEFAULT_DIR_NAME).resolve()

get_config_path

get_config_path() -> Path

Resolve the path to config.toml under the OpenJarvis root.

Source code in src/openjarvis/core/paths.py
def get_config_path() -> Path:
    """Resolve the path to ``config.toml`` under the OpenJarvis root."""
    return get_config_dir() / "config.toml"

get_data_dir

get_data_dir() -> Path

Resolve the directory for persistent data (databases, blobs, …).

Consolidated under the single root; identical to :func:get_config_dir. Provided as a distinct name so call sites read intentionally.

Source code in src/openjarvis/core/paths.py
def get_data_dir() -> Path:
    """Resolve the directory for persistent data (databases, blobs, …).

    Consolidated under the single root; identical to :func:`get_config_dir`.
    Provided as a distinct name so call sites read intentionally.
    """
    return get_config_dir()

get_cache_dir

get_cache_dir() -> Path

Resolve the directory for regenerable caches (eval datasets, etc.).

Lives at <root>/cache so caches stay inside the single OpenJarvis directory instead of scattering across ~/.cache.

Source code in src/openjarvis/core/paths.py
def get_cache_dir() -> Path:
    """Resolve the directory for regenerable caches (eval datasets, etc.).

    Lives at ``<root>/cache`` so caches stay inside the single OpenJarvis
    directory instead of scattering across ``~/.cache``.
    """
    return get_config_dir() / "cache"