- docs
- Packages
- Embed a stable path in your IDE or shell
Embed a stable path in your IDE or shell
Use this page to give an editor, script or shell a package path that survives upgrades.
Pick a path mode
Section titled “Pick a path mode”Package-store paths are content-addressed and change on every upgrade, so never embed them in an IDE config or shell profile. Embed a symlink instead. Four modes cover every case:
| Mode | Flag | Path | Auto-install | Use case |
|---|---|---|---|---|
| Package store (default) | (none) | ~/.ocx/packages/…/<digest>/ | no (run ocx package install or ocx package pull first) | CI, scripts, one-shot queries |
| Candidate symlink | --candidate | ~/.ocx/symlinks/…/candidates/<tag> | no | Pin a specific tag in editor or IDE config |
| Current symlink | --current | ~/.ocx/symlinks/…/current | no | “Always selected” path in shell profiles or IDE settings |
| Your own link | --link <PATH> | <PATH> | no | A path your build or repository chooses, such as ./.tools/cmake |
All three symlink modes target the package root directly. Consumers traverse one level in: …/content/ for files, …/entrypoints/ for launchers, or …/metadata.json to read the metadata. The current symlink exists only after you run ocx package install --select kitware/cmake:3.32 once, and --current fails until then.
// .vscode/settings.json: path survives every upgrade{ "cmake.cmakePath": "~/.ocx/symlinks/ocx.sh/kitware/cmake/current/content/bin/cmake" }# ~/.bashrc: always resolves to the selected versionexport PATH="$HOME/.ocx/symlinks/ocx.sh/kitware/cmake/current/content/bin:$PATH"When ocx package install --select kitware/cmake:3.32 runs later, current is re-pointed. The IDE and the shell pick up the new version with no config edits.
Write the link where a tool expects it
Section titled “Write the link where a tool expects it”When a build tool wants the package at a path of its own, let ocx write the link there:
ocx package install --link ./.tools/cmake "kitware/cmake:4.2.0"The link keeps the package safe from ocx clean for as long as it exists. A link you create yourself with ln -s does not. ocx clean may remove the package behind it. Delete the link when you no longer need the package, and the next ocx clean reclaims it.
For automation, ocx package which prints the resolved package root directly:
ocx package install --select "kitware/cmake:4.2.0"ocx package which --current "kitware/cmake:4.2.0"ocx package which --candidate "kitware/cmake:4.2.0"--candidate, --current and --link fail immediately if the required symlink is absent. They never auto-install, and neither does the default package-store mode: ocx package which locates a package and downloads nothing. A digest component in the identifier is rejected.
Run an installed binary on Windows
Section titled “Run an installed binary on Windows”On Windows, ocx package install and ocx package select generate two files per entrypoint in the package’s entrypoints/ directory:
| File | Role |
|---|---|
<name>.exe | Native launcher, the sole Windows entry point for all callers |
<name>.shim | One-line sidecar carrying the absolute package root |
There is no .cmd launcher. .EXE is always present in the default Windows PATHEXT. Bare-name resolution in cmd.exe, PowerShell and Git Bash therefore finds <name>.exe with no PATHEXT configuration.
The .exe shim reads <name>.shim at invocation time. It then calls CreateProcessW directly to spawn ocx launcher exec, and it does not route through cmd.exe. Caller arguments never pass through a second cmd.exe parse, which closes the BatBadBut / CVE-2024-24576 class of argument-injection vulnerability.
The committed shim blobs (about 333 KiB for x86_64 and 239 KiB for aarch64) are unsigned in this release. Authenticode signing via SignPath Foundation is a documented follow-on step. The unsigned shim is fully functional for backend automation such as CI, Bazel and devcontainers. SmartScreen friction applies only to interactive end-user downloads.
Activate tools with direnv
Section titled “Activate tools with direnv”For direnv-driven projects, ocx direnv init writes an .envrc file that calls ocx direnv export on each cd. The stateless export block is re-evaluated by direnv whenever ocx.toml or ocx.lock changes.
ocx initocx add "kitware/cmake:4.2.0"ocx direnv initThis routes through the project toolchain, so the binaries on $PATH match the digests locked in ocx.lock. You need no ambient installs and no manual export statements.