# Add Infiltrator.jl to Base?

**URL:** https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995
**Category:** Internals & Design
**Tags:** debug, debugging
**Created:** [March 16, 2022, 9:19pm UTC](https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995 "2022-03-16T21:19:43Z")
**Posts on this page:** 16
**Page:** 1

<div class="post-metadata">

### Author: ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)
#### Post date: [March 16, 2022, 9:19pm UTC](https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995/1 "2022-03-16T21:19:43Z")

</div>

I know that folks often ask to add things to Base here on Discourse, and that usually the correct answer is “no”, but I think there’s a very good reason to add Infiltrator.jl to Base Julia. Let me explain.

Infiltrator.jl is a very useful and performant tool for debugging. However, it has one main drawback. If you want to debug code in a package, you have to add Infiltrator as a project dependency. So whenever I want to use `@infiltrate`, I have to do `] add Infiltrator` and then add `using Infiltrator` to my package code. And then when I’m done debugging, I have to remember to undo those by deleting `using Infiltrator` and running `] rm Infiltrator`.

If Infiltrator.jl was in Base, then we wouldn’t need to do those things. We would always have a good debugging tool close at hand. Also, Infiltrator.jl is only 511 source lines of code and has no dependencies other than base + stdlib Julia, so it would not be a very large addition to the Julia code base.

---

<div class="post-metadata">

### Author: ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)
#### Post date: [March 16, 2022, 9:25pm UTC](https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995/2 "2022-03-16T21:25:38Z")

</div>

I share this concern, but it’s not too hard to write `Main.@infiltrate` instead of just `@infiltrate`.

---

<div class="post-metadata">

### Author: ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)
#### Post date: [March 16, 2022, 9:27pm UTC](https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995/3 "2022-03-16T21:27:38Z")

</div>

Ohhh, does that work? I was wondering if there was a better way to do this. I guess I should have asked on Discourse instead of Stack Overflow, which I did 22 days ago:

[https://stackoverflow.com/questions/71208181/use-infiltrator-jl-on-package-code-without-adding-infitrator-to-project-toml](https://stackoverflow.com/questions/71208181/use-infiltrator-jl-on-package-code-without-adding-infitrator-to-project-toml)

---

<div class="post-metadata">

### Author: ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)
#### Post date: [March 16, 2022, 9:46pm UTC](https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995/4 "2022-03-16T21:46:50Z")

</div>

Hmm, I tried using `Main.@infiltrate` in my code and I’m getting the error below. Any advice?

```julia
julia> using Infiltrator

julia> using PackageA
[Info: Precompiling PackageA [b7d5e62f-924e-4906-b2b5-430ba4531d91]
ERROR: LoadError: UndefVarError: @infiltrate not defined
Stacktrace:
  [1] #macroexpand#51
    @ ./expr.jl:115 [inlined]
  [2] macroexpand
    @ ./expr.jl:114 [inlined]
  [3] docm(source::LineNumberNode, mod::Module, meta::Any, ex::Any, define::Bool) (repeats 2 times)
    @ Base.Docs ./docs/Docs.jl:537
  [4] (::DocStringExtensions.var"#32#33"{typeof(DocStringExtensions.template_hook)})(::LineNumberNode, ::Vararg{Any})
    @ DocStringExtensions ~/.julia/packages/DocStringExtensions/iscC8/src/templates.jl:11
  [5] var"@doc"(::LineNumberNode, ::Module, ::String, ::Vararg{Any})
    @ Core ./boot.jl:517
  [6] include(mod::Module, _path::String)
    @ Base ./Base.jl:418
  [7] include(x::String)
    @ PackageA ~/projects/PackageA/src/PackageA.jl:1
  [8] top-level scope
    @ ~/projects/PackageA/src/PackageA.jl:12
  [9] include
    @ ./Base.jl:418 [inlined]
 [10] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt64}}, source::Nothing)
    @ Base ./loading.jl:1318
 [11] top-level scope
    @ none:1
 [12] eval
    @ ./boot.jl:373 [inlined]
 [13] eval(x::Expr)
    @ Base.MainInclude ./client.jl:453
 [14] top-level scope
    @ none:1

```

---

<div class="post-metadata">

### Author: ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)
#### Post date: [March 16, 2022, 11:34pm UTC](https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995/5 "2022-03-16T23:34:55Z")

</div>

That shouldn’t be fatal, it just means your package wasn’t fully precompiled

---

<div class="post-metadata">

### Author: ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)
#### Post date: [March 17, 2022, 2:16am UTC](https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995/6 "2022-03-17T02:16:19Z")

</div>

Did you try adding Infiltrator in your default Julia environment? I think that makes it implicitly available in other environments as part of the environment stack in `LOAD_PATH`?

Then you should be able to do `using Infiltrator` within your package — it’ll emit some warnings about undeclared dependencies but otherwise work.

That said, I do kinda wish Infiltrator or something like it was part of the REPL stdlib. If there was a macro `@REPL` to spawn a REPL inside an arbitrary scope that would be pretty great.

---

<div class="post-metadata">

### Author: ![pfitzseb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pfitzseb/32/45566_2.png) [@pfitzseb](https://discourse.julialang.org/u/pfitzseb)
#### Post date: [July 28, 2022, 3:31pm UTC](https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995/7 "2022-07-28T15:31:39Z")

</div>

Just wrote some (minimal) documentation for this:  
[https://juliadebug.github.io/Infiltrator.jl/stable/API/#Infiltration-and-exfiltration](https://juliadebug.github.io/Infiltrator.jl/stable/API/#Infiltration-and-exfiltration)

There’s also a precompile-safe function form now, which you can use like this:

```julia
if isdefined(Main, :Infiltrator)
  Main.infiltrate(@ __MODULE__ , Base.@locals, @ __FILE__ , @ __LINE__ )
end

```

---

<div class="post-metadata">

### Author: ![jbu](https://avatars.discourse-cdn.com/v4/letter/j/a8b319/32.png) [@jbu](https://discourse.julialang.org/u/jbu)
#### Post date: [July 29, 2022, 4:05am UTC](https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995/8 "2022-07-29T04:05:13Z")

</div>

An older thread has additional details / tips that might be helpful for keeping Infiltrator out of your dependencies:

> [@Separate "Dev" packages in Project.toml](https://discourse.julialang.org/t/separate-dev-packages-in-project-toml/63143):
>
> When creating a package, I often use dependencies that are purely for development and have nothing to do with my package’s functionality (e.g. [Revise.jl](https://timholy.github.io/Revise.jl/stable/), [Debugger.jl](https://github.com/JuliaDebug/Debugger.jl), [Infiltrator.jl](https://github.com/JuliaDebug/Infiltrator.jl). If I ever wanted to share my package, these unnecessary packages would be shared too unless I manually deleted them from the Project.toml. [Pipenv](https://pipenv-fork.readthedocs.io/en/latest/basics.html#pipenv-install) (for Python) makes a distinction between “dev” dependencies only needed for development ([dev-packages] in the Pipfile), and strictly necessary dependencies needed for ru…

---

<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 22, 2023, 3:30pm UTC](https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995/9 "2023-06-22T15:30:55Z")

</div>

> [@c42f](#):
>
> That said, I do kinda wish Infiltrator or something like it was part of the REPL stdlib. If there was a macro `@REPL` to spawn a REPL inside an arbitrary scope that would be pretty great.

 ![image](https://global.discourse-cdn.com/julialang/original/3X/6/8/68eaed574c7296281cbc86b576083d75e78c72cb.png)

I’ve been waiting here 30 minutes for the debugger to reach my breakpoint just so I can experiment with a few local variables there. I tried `@infiltrate` first, but it errored since not in my package dependencies (even with Infiltrate in my default environment).

Has there been any movement in the last year to get the Infiltrator functionality into Base?

---

<div class="post-metadata">

### Author: ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)
#### Post date: [June 22, 2023, 7:54pm UTC](https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995/10 "2023-06-22T19:54:50Z")

</div>

Did you know that you can write `Main.@infiltrate` in your package code and it will work if you have Infiltrator loaded in your session? You can edit it in with Revise once the deved package is loaded, otherwise it might complain at load, not sure

---

<div class="post-metadata">

### Author: ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)
#### Post date: [June 22, 2023, 8:05pm UTC](https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995/11 "2023-06-22T20:05:00Z")

</div>

That was mentioned in the first reply: [Add Infiltrator.jl to Base? - #2 by pdeffebach](https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995/2)

---

<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 22, 2023, 8:45pm UTC](https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995/12 "2023-06-22T20:45:10Z")

</div>

`Main.@infiltrate` wasn’t working when I tried it earlier, but it is working now.  
`Main.infiltrate(@ __MODULE__ , Base.@locals, @ __FILE__ , @ __LINE__ )` did work earlier, but it’s not a very convenient solution.

---

<div class="post-metadata">

### Author: ![haberdashPI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/haberdashpi/32/26337_2.png) [@haberdashPI](https://discourse.julialang.org/u/haberdashPI)
#### Post date: [June 23, 2023, 12:03am UTC](https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995/13 "2023-06-23T00:03:01Z")

</div>

That would be a nice convenience, but in the meantime why not just add it as a dependency to your project? It’s a little annoying to have to remember to remove it later when you’re done debugging, but if you don’t add a compat bound for it adding Aqua to your tests will catch it for you.

---

<div class="post-metadata">

### Author: ![TI36XPro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ti36xpro/32/33658_2.png) [@TI36XPro](https://discourse.julialang.org/u/TI36XPro)
#### Post date: [June 25, 2023, 3:24am UTC](https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995/14 "2023-06-25T03:24:10Z")

</div>

If you need to quickly grab some variables internal to the function you can use the `Ref` trick that is discussed in [this](https://www.youtube.com/watch?v=g-iOOhh2U6o&t=10s) video. Extremely useful, I use it literally all the time. Between that and `Infiltrator` I actually never use `Debugger` when developing the code packages I use for my PhD research.

Basically it works like this. Make a “box” that can hold anything.  
Define this in `Main`.

```julia
xx = Ref{Any}()

```

Then you have a big deep function that the debugger would take forever to reach. You can do

```julia
function some_very_deep_function()
# code
# code 
# ...
Main.xx[] = some var

end

```

After the function finishes you can then play around with that variable in `Main`.

```julia
xx[] # de-ref, do whatever you want, inspect, etc.

```

---

<div class="post-metadata">

### Author: ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)
#### Post date: [June 25, 2023, 6:11am UTC](https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995/15 "2023-06-25T06:11:49Z")

</div>

If I want to see some local variables in a function for debugging I just declare them as global in that function…

---

<div class="post-metadata">

### Author: ![mariusd](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mariusd/32/23231_2.png) [@mariusd](https://discourse.julialang.org/u/mariusd)
#### Post date: [September 12, 2023, 5:53am UTC](https://discourse.julialang.org/t/add-infiltrator-jl-to-base/77995/16 "2023-09-12T05:53:14Z")

</div>

try this: [ALL\_MODULES\_EXCEPT\_MAIN](https://www.julia-vscode.org/docs/dev/userguide/debugging/#ALL_MODULES_EXCEPT_MAIN)
