Skip to content

🤖 Prototype: add overlay project support#4643

Open
KristofferC wants to merge 1 commit intomasterfrom
kc/overlay
Open

🤖 Prototype: add overlay project support#4643
KristofferC wants to merge 1 commit intomasterfrom
kc/overlay

Conversation

@KristofferC
Copy link
Copy Markdown
Member

@KristofferC KristofferC commented Mar 25, 2026

Prototyped the overlay project feature I mentioned in #4637 (comment) with Claude.
This still needs code loading support to merge in the overlay project into the workspace.
The goal here is to avoid using the environment stack for dev tools (which has a seprate manifest) and instead always resolve the dev tools together with your active project.
This does not help "torn environments" if you load packages, do package operations and then load more packages.
Also, it is a bit ugly that if you share a manifest with someone they get all these devtool packages in there, maybe there should be two manifests, one that is everything reachable from the actual active project and one that is the "orphan" dpeendencies assuming the overlay environment would be removed...

TODO:

  • Code loading support
  • Precompilation support

Usage:

julia> ENV["JULIA_PKG_OVERLAY"]
"@devtools"

(@devtools) [overlay] pkg> activate @devtools
  Activating project at `~/.julia/environments/devtools`

(@devtools) [overlay] pkg> st
Status `~/.julia/environments/devtools/Project.toml` (empty project)

(@devtools) [overlay] pkg> add BenchmarkTools, Revise
    Updating `~/.julia/environments/devtools/Project.toml`
  [6e4b80f9] + BenchmarkTools
  [295af30f] + Revise
    Updating `~/.julia/environments/devtools/Manifest.toml`
  [6e4b80f9] + BenchmarkTools
  [295af30f] + Revise

(@devtools) [overlay] pkg> activate --temp
  Activating new project at `/var/folders/2c/rk2fkhgn6c35lr6qp7cll4t00000gn/T/jl_sjMOea`

(jl_sjMOea) pkg> st --workspace
Status `/private/var/folders/2c/rk2fkhgn6c35lr6qp7cll4t00000gn/T/jl_sjMOea/Project.toml`
Status /Users/kc/.julia/environments/devtools/Project.toml
  [6e4b80f9] BenchmarkTools
  [295af30f] Revise

(jl_sjMOea) pkg> add Example
   Resolving package versions...
   Installed JuliaInterpreter ─ v0.10.11
   Installed Revise ─────────── v3.14.0
    Updating `/private/var/folders/2c/rk2fkhgn6c35lr6qp7cll4t00000gn/T/jl_sjMOea/Project.toml`
  [7876af07] + Example v0.5.5
    Updating `/private/var/folders/2c/rk2fkhgn6c35lr6qp7cll4t00000gn/T/jl_sjMOea/Manifest.toml`
  [7876af07] + Example v0.5.5

(jl_sjMOea) pkg> st -m
Status `/private/var/folders/2c/rk2fkhgn6c35lr6qp7cll4t00000gn/T/jl_sjMOea/Manifest.toml`
  [7876af07] Example v0.5.5

(jl_sjMOea) pkg> st -m --workspace
Status `/private/var/folders/2c/rk2fkhgn6c35lr6qp7cll4t00000gn/T/jl_sjMOea/Manifest.toml`
  [6e4b80f9] BenchmarkTools v1.6.3
  [da1fd8a2] CodeTracking v3.0.0
  [34da2185] Compat v4.18.1
  [807dbc54] Compiler v0.1.1
  [7876af07] Example v0.5.5
  [682c06a0] JSON v1.4.0

🤖 description:


Julia's stacked environments (LOAD_PATH / @v#.#) allow loading dev tools alongside project deps, but they use separate manifests. This can lead to incompatible versions being loaded, wasted precompilation, and [compat] violations. Workspaces solve this with a shared manifest, but require explicit [workspace] entries in every project.

An overlay project bridges this gap: a globally-configured Project.toml whose deps get merged into every active environment as if it were a workspace member. Dev tools like Debugger, JET, and Cthulhu can be listed once in the overlay and resolved together with whatever project you're working on — sharing a single manifest and respecting [compat].

Configuration (checked in order, first wins):

  • Pkg.OVERLAY_PROJECT[] = "~/.julia/overlay"
  • ENV["JULIA_PKG_OVERLAY"] = "@devtools"

Paths starting with @ are expanded via Base.load_path_expand, so "@devtools" resolves to ~/.julia/environments/devtools/Project.toml.

The implementation injects the overlay into env.workspace in the EnvCache constructor (~5 lines), which means all downstream code — dep loading, compat intersection, resolve hashing, precompilation — works automatically since it already iterates over workspace members.

When the overlay project itself is active (pkg> activate @devtools), only add and rm are supported — they write directly to the overlay's Project.toml without resolution or manifest updates. Other operations (develop, update, pin, free) error with a clear message. The REPL prompt shows [overlay] when the overlay project is active.


Julia's stacked environments (LOAD_PATH / @v#.#) allow loading dev tools
alongside project deps, but they use separate manifests. This can lead to
incompatible versions being loaded, wasted precompilation, and [compat]
violations. Workspaces solve this with a shared manifest, but require
explicit [workspace] entries in every project.

An overlay project bridges this gap: a globally-configured Project.toml
whose deps get merged into every active environment as if it were a
workspace member. Dev tools like Debugger, JET, and Cthulhu can be listed
once in the overlay and resolved together with whatever project you're
working on — sharing a single manifest and respecting [compat].

Configuration (checked in order, first wins):
  - Pkg.OVERLAY_PROJECT[] = "~/.julia/overlay"
  - ENV["JULIA_PKG_OVERLAY"] = "@devtools"

Paths starting with @ are expanded via Base.load_path_expand, so
"@devtools" resolves to ~/.julia/environments/devtools/Project.toml.

The implementation injects the overlay into env.workspace in the EnvCache
constructor (~5 lines), which means all downstream code — dep loading,
compat intersection, resolve hashing, precompilation — works automatically
since it already iterates over workspace members.

When the overlay project itself is active (pkg> activate @devtools),
only `add` and `rm` are supported — they write directly to the overlay's
Project.toml without resolution or manifest updates. Other operations
(develop, update, pin, free) error with a clear message. The REPL prompt
shows [overlay] when the overlay project is active.

Also fixes print_diff crash when both old and new PackageSpecs are not
instantiated (no manifest entry), and uses absolute paths in workspace
status output when the member is outside the project tree.

Closes #4637

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@vchuravy
Copy link
Copy Markdown
Member

Neat! Would be good to add a test that preference merging works with an overlay project.

@KristofferC
Copy link
Copy Markdown
Member Author

Neat! Would be good to add a test that preference merging works with an overlay project.

Yes, I forgot to mention that. I am actually not sure it works with workspaces?

@KristofferC
Copy link
Copy Markdown
Member Author

Things that can be discussed:

  • How impactful is this in terms of Pkg "strict" mode for well-behaved [compat] + precompilation #4637? It avoids having your debug tools load potentially invalid dependencies. It also hopefully avoids the situation where you start julia, load a debug tool, then swap to another environment.
  • Is a global variable + env the best way to set an overlay project?
  • Should there be support for multiple overlay projects? Implementation-wise, it is easy.

@StefanKarpinski
Copy link
Copy Markdown
Member

Very cool!

It also hopefully avoids the situation where you start julia, load a debug tool, then swap to another environment.

I'm not clear how it avoids this. Can you explain?

Is a global variable + env the best way to set an overlay project?

Feels like an extra layer of indirection. We could just pick @overlay or @devtools as the name.

@KristofferC
Copy link
Copy Markdown
Member Author

KristofferC commented Mar 25, 2026

Feels like an extra layer of indirection. We could just pick @overlay or @devtools as the name.

It feels to me like you would want this path to be customizable to easily be able to swap between different overlay projects (or to disable it) etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: New

Development

Successfully merging this pull request may close these issues.

3 participants