# \[ANN\] ShareAdd.jl - making easy to import packages from multiple environments

**URL:** <https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261>\
**Category:** Package Announcements\
**Tags:** package, announcement, workflow, shared-environments, stacked-environments\
**Created:** [October 13, 2024, 6:38pm UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261 "2024-10-13T18:38:19Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [October 13, 2024, 6:38pm UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/1 "2024-10-13T18:38:19Z")

</div>

I am happy to announce the newly registered package ShareAdd.jl .

The package is intended for the interactive use. It’s purpose is to make commonly used packages comfortably available without the dilemma of either adding them to the package under development or keeping them in the “main” Julia environment. Instead, these packages can be kept in [shared environments](https://pkgdocs.julialang.org/v1/environments/#Shared-environments), either grouped, or one package per environment, which would be added to the `LOAD_PATH` as necessary.

ShareAdd.jl exports macro `@usingany`. This macro makes package(s) available, if they are not already, and loads them with `using` keyword:

- If a package is available in any environment in `LOAD_PATH`, that’s OK.
- If a package is available in any of the shared environments, this environment will be pushed into `LOAD_PATH`.
- Otherwise if it can be installed, you will be prompted to select or create an environment to install the package(s).
- If the package is not listed in any registry, an error will be thrown.

The package also exports several utility functions.

For further details, see [documentation](https://eben60.github.io/ShareAdd.jl/).

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [November 22, 2024, 4:13pm UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/2 "2024-11-22T16:13:09Z")

</div>

Version 1.0 is now registered.

- Improved `using` syntax variations support - this is now OK, too:

```julia
@usingany Foo: bar

```

- Added the macro `@usingtmp` for those who prefer to use temporary environments:

```julia
@usingtmp Foo

```

will activate a temporary environment, `dev` there the package that was under development (if there was any) before the macro call, install Foo into this temporary env, and import it by `using Foo`.

- Documentation made even better. 🙂
- Some minor usage improvement.

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [December 1, 2024, 11:00am UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/3 "2024-12-01T11:00:09Z")

</div>

ShareAdd.jl can be combined nicely with BasicAutoloads.jl by @Lilith .

Here is my current `startup.jl`:

```julia

if VERSION >= v"1.11" && isinteractive()
	using ShareAdd
    import BasicAutoloads
    BasicAutoloads.register_autoloads([
    	["plot", "scatter"] => :(isdefined(Main, :plot) || @usingany Plots),
    	["DataFrame", "combine", "transform!", "transform", "select!", "select", "groupby"] 
    		=> :(@usingany DataFrames),
    	["CSV"] => :(@usingany CSV, StringEncodings, DataFrames),
    	["Dates", "Date","DateTime"] => :(@usingany Dates),
    	["mean", "std", "median"] => :(isdefined(Main, :mean) || @usingany Statistics), 
    	["@u_str"] => :(@usingany Unitful),  
    	["@benchmark"] => :(@usingany BenchmarkTools),   	
    ])
    println("ShareAdd & BasicAutoloads are loaded")
end

```

Now, should I e.g. type `mean([1,2,3])` or `1.55u"V"` in the REPL, Statistics.jl or resp. Unitful.jl would be first silently loaded.

The “main” shared environment, i.e. the folder “~/.julia/environments/v1.11/” contains now only `Revise`, `ShareAdd`, and `BasicAutoloads`. Most “shared” packages are each individually in the eponymous env, like `Plots` package is in `@Plots` shared env.

---

<div class="post-metadata">

**Author:** ![Lilith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lilith/32/27492_2.png) [@Lilith](https://discourse.julialang.org/u/Lilith)\
**Post date:** [December 1, 2024, 2:20pm UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/4 "2024-12-01T14:20:58Z")

</div>

Exciting! This reminds me of a hack I cobbled together [here](https://discourse.julialang.org/t/10-15-minute-ttfp-with-plots-jl-please-help/92636/23), I’m glad to see it in a package that is more usable 🙂

---

<div class="post-metadata">

**Author:** ![tecosaur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tecosaur/32/23206_2.png) [@tecosaur](https://discourse.julialang.org/u/tecosaur)\
**Post date:** [December 1, 2024, 2:59pm UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/5 "2024-12-01T14:59:49Z")

</div>

This approach is something that I’ve experimented with in my config (I’ve actually got an autoloads setup that looks through shared environments automatically), but I ran into the issue that shared environments are version-specific.

The solution to this I’ve currently got is to have the sets of available packages defined in a TOML file, and have per-version shared environments generated from that spec in a separate folder that’s added to the load path.

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [December 8, 2024, 9:19pm UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/6 "2024-12-08T21:19:00Z")

</div>

> [@tecosaur](#):
>
> but I ran into the issue that shared environments are version-specific.

Could you probably explain in more details what was going on?

* * *

Yes, sometimes a shared package gets recompiled, which is annoying with large packages like Plots.jl.

Now I’ve tried to look at it a bit systematically. I selected 8 packages I was working with in the last time, updated all their environments. Updated the shared env `@Plots`. Then

- start Julia with the environment of the next package
- `@usingany Plots` - which sometimes resulted in recompiling `Plots`
- exit Julia

After I did it once with each package, I repeated the cycle once again. Now, there was no recompiles on this second use of `@usingany Plots`.

So, the good news is, a recompile with one package doesn’t influence others. Once you always have the same combination of “main package environment” and the set of “additional packages”, and made no updates, no recompiles are expected.

However if you got it recompiled with `@usingany Plots`., and another day do `@usingany Makie`, and still another day `@usingany Plots` - each time you change the plotting package, you may expect it being recompiled. Presumably one of them cause downgrading of some dependencies, which another one then upgrades again the next day. I’m not sure what can be done about it.

---

<div class="post-metadata">

**Author:** ![tecosaur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tecosaur/32/23206_2.png) [@tecosaur](https://discourse.julialang.org/u/tecosaur)\
**Post date:** [December 9, 2024, 1:43am UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/7 "2024-12-09T01:43:07Z")

</div>

> [@Eben60](#):
>
> So, the good news is, a recompile with one package doesn’t influence others.

The real problem is that the resolved manifest with one Julia version will straight up be different to that of another Julia version: making global shared environments often incompatible with other Julia versions (how different many Julia versions work depending on the particular packages in the environment ).

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [December 9, 2024, 8:52am UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/8 "2024-12-09T08:52:25Z")

</div>

> [@tecosaur](#):
>
> The real problem is that the resolved manifest with one Julia version will straight up be different to that of another Julia version

Well, starting with Julia v1.11 it is possible to have separate manifests for different Julia versions. As v1.10 is now LTS, having non-version-specific manifest for v1.10 and version-specific ones for newer versions would probably cover the vast majority of use cases.

I’d implement creating version-specific manifests when using ShareAdd to update packages or environments. Thank you for drawing my attention to the issue 🙂

P.S. Actually as ShareAdd.jl specifies Juvila version \>= v1.10, it would cover 100% of cases supported by ShareAdd.jl

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [December 12, 2024, 10:56pm UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/9 "2024-12-12T22:56:55Z")

</div>

> [@Eben60](#):
>
> I’d implement creating version-specific manifests when using ShareAdd to update packages or environments.

✅ 🙂

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [January 26, 2025, 10:19am UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/10 "2025-01-26T10:19:35Z")

</div>

In the meanwhile, ShareAdd.jl is **@v2.1.0**

Apart from support for versioned manifests (which were recently BTW backported to Julia v1.10), ShareAdd.jl got new functions for managing shared environments: `info`, `update`, `delete`

> **Usage examples**
>
> ```julia
> julia> ShareAdd.info() # info function is public, not exported to avoid name collisions
> @About
> => ["About"]
> @BenchmarkTools
> => ["BenchmarkTools"]
> @Coverage
> => ["Coverage"]
> @DataFrames
> => ["CSV", "DataFrames", "StringEncodings"]
> @DocumenterTools
> => ["DocumenterTools"]
> @JLD2
> => ["JLD2"]
> @Makie
> => ["GLMakie", "Makie"]
> @PackageMaker
> => ["PackageMaker"]
> @Plots
> => ["Plots"]
> @Revise
> => ["TOML"]
> @StaticArrays
> => ["StaticArrays"]
> @StatsBase
> => ["StatsBase"]
> @ThisNThan
> => ["DefaultApplication", "FilePathsBase"]
> @Unitful
> => ["Unitful"]
> @v1.11
> => ["BasicAutoloads", "Revise", "ShareAdd"]
> 
> julia> ShareAdd.delete("@Revise")
> 
> julia> ShareAdd.info()
> @About
> => ["About"]
> @BenchmarkTools
> => ["BenchmarkTools"]
> @Coverage
> => ["Coverage"]
> @DataFrames
> => ["CSV", "DataFrames", "StringEncodings"]
> @DocumenterTools
> => ["DocumenterTools"]
> @JLD2
> => ["JLD2"]
> @Makie
> => ["GLMakie", "Makie"]
> @PackageMaker
> => ["PackageMaker"]
> @Plots
> => ["Plots"]
> @StatsBase
> => ["StatsBase"]
> @ThisNThan
> => ["DefaultApplication", "FilePathsBase"]
> @Unitful
> => ["Unitful"]
> @v1.11
> => ["BasicAutoloads", "Revise", "ShareAdd"]
> julia> ShareAdd.delete("@Revise") # it was redundant
> julia> ShareAdd.info(;upgradable=true)
> @Plots
> Plots: 1.40.8 --> 1.40.9
> julia> ShareAdd.update("@Plots")
> Activating project at `~/.julia/environments/Plots`
> Updating registry at `~/.julia/registries/General.toml`
> ...
> julia> 
> 
> ```

In my current experience, in most cases it makes sense to put each “shareable” package into a separate environment.

---

<div class="post-metadata">

**Author:** ![Nathan\_Boyer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nathan_boyer/32/14825_2.png) [@Nathan\_Boyer](https://discourse.julialang.org/u/Nathan_Boyer)\
**Post date:** [June 2, 2025, 8:06pm UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/11 "2025-06-02T20:06:02Z")

</div>

> [@Eben60](#):
>
> ```julia
> ["plot", "scatter"] => :(isdefined(Main, :plot) || @usingany Plots),
> ["mean", "std", "median"] => :(isdefined(Main, :mean) || @usingany Statistics), 
> 
> ```

Can you elaborate on the purpose of the `isdefined` checks here?

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [June 2, 2025, 8:17pm UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/12 "2025-06-02T20:17:25Z")

</div>

> [@Eben60](#):
>
> isdefined(Main, :plot)

By default my plotting package is `Plots`, but It could be I was using some other plotting package which also defines variable `plot`, e.g. `Makie`. In this case `Plots` shouldn’t be imported automagically.

---

<div class="post-metadata">

**Author:** ![Nathan\_Boyer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nathan_boyer/32/14825_2.png) [@Nathan\_Boyer](https://discourse.julialang.org/u/Nathan_Boyer)\
**Post date:** [June 2, 2025, 8:27pm UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/13 "2025-06-02T20:27:58Z")

</div>

Wouldn’t that always be the intended functionality though: only load if not already defined? It seems like I should add that to every line. I’m wondering if that check can be made implicit in the `register_autoloads` function.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [June 2, 2025, 8:31pm UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/14 "2025-06-02T20:31:04Z")

</div>

Check [Autoloads.jl](https://github.com/JuliaAPlavin/Autoloads.jl/tree/master?tab=readme-ov-file#differences-from-basicautoloadsjl) with the only difference from BasicAutoloads being more careful triggering: only executes the import when (1) the name doesn’t exist and (2) is actually _used_ in the repl, not _defined_.  
And these issues [1](https://github.com/LilithHafner/BasicAutoloads.jl/issues/20) [2](https://github.com/LilithHafner/BasicAutoloads.jl/issues/21) where I suggested to add this to BasicAutoloads.

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [June 2, 2025, 8:40pm UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/15 "2025-06-02T20:40:06Z")

</div>

That’s a good question, for which I have no answer, as I’m not the author of BasicAutoloads.jl - maybe @Lilith could answer.

From the practical point of view I can tell I’ve never noticed any problems with it: If some package already loaded, repeated import causes generally no problems and no noticeable delay. All other listed identifier are specific enough in my case that I can be sure the “right” package will be imported. `plots` was an exception.

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [June 2, 2025, 8:42pm UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/16 "2025-06-02T20:42:28Z")

</div>

> [@aplavin](#):
>
> Check [Autoloads.jl](https://github.com/JuliaAPlavin/Autoloads.jl/tree/master?tab=readme-ov-file#differences-from-basicautoloadsjl)

It seems not registered, is it?

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [June 2, 2025, 8:43pm UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/17 "2025-06-02T20:43:13Z")

</div>

> [@Eben60](#):
>
> It seems not registered, is it?

No, not registered in the General registry. Luckily, in Julia it’s easy to install from a url 🙂

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [April 13, 2026, 12:42pm UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/18 "2026-04-13T12:42:28Z")

</div>

**ShareAdd.jl v2.5** is out, featuring support for the **Workspace** feature introduced in Julia `v1.12`.

When calling `@usingany Foo`, ShareAdd.jl now checks if the package exists within your current workspace—either as a dependency or as a sub-project.

**Example Scenario:** Assume you are working in `MyWorkspace/test`:

- `MyWorkspace/docs` has `Documenter.jl` as a dependency.
- `MyWorkspace/SubProj/SubPkg` is a package within the monorepo.

Calling `@usingany Documenter` will resolve it by adding `MyWorkspace/docs` to your `LOAD_PATH`. If the package isn’t found in the workspace, the standard fallback behavior applies.

Similarly, calling `@usingany SubPkg` will now correctly import your `SubPkg.jl`.

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [June 14, 2026, 3:59pm UTC](https://discourse.julialang.org/t/ann-shareadd-jl-making-easy-to-import-packages-from-multiple-environments/121261/19 "2026-06-14T15:59:48Z")

</div>

**ShareAdd.jl v2.6** is out, with the new macro `@usinghere`.

This macro activates an environment in the directory of the current script (or its parent directory if the script is located within a `src` folder) and automatically adds any missing packages to that environment before importing them. This is specifically useful when writing standalone scripts that should self-manage their dependencies.

The addition has been inspired by [this discussion](https://discourse.julialang.org/t/ann-quickenv-jl-environment-manager/137486) and packages cited therein.
