diff --git a/cspell.json b/cspell.json
index 16de9757fb8..bf3040265c2 100644
--- a/cspell.json
+++ b/cspell.json
@@ -113,6 +113,7 @@
"Maddiaa",
"mathbb",
"memfs",
+ "memset",
"merkle",
"metas",
"minreq",
diff --git a/docs/docs/getting_started/tooling/index.mdx b/docs/docs/getting_started/tooling/index.mdx
deleted file mode 100644
index ac480f3c9f5..00000000000
--- a/docs/docs/getting_started/tooling/index.mdx
+++ /dev/null
@@ -1,38 +0,0 @@
----
-title: Tooling
-Description: This section provides information about the various tools and utilities available for Noir development. It covers the Noir playground, IDE tools, Codespaces, and community projects.
-Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling]
----
-
-Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world.
-
-## Playground
-
-The Noir playground is an easy way to test small ideas, share snippets, and integrate in other websites. You can access it at [play.noir-lang.org](https://play.noir-lang.org).
-
-## IDE tools
-
-When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more.
-
-The easiest way to use these tools is by installing the [Noir VS Code extension](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir).
-
-## Codespaces
-
-Some Noir repos have leveraged Codespaces in order to ease the development process. You can visit the [noir-starter](https://github.com/noir-lang/noir-starter) for an example.
-
-
-
-## GitHub Actions
-
-You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as
-installing `noirup` and running tests in your GitHub Action `yml` file.
-
-See the
-[config file in the Noir repo](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) for an example usage.
-
-## Community projects
-
-As an open-source project, Noir has received many contributions over time. Some of them are related with developer tooling, and you can see some of them in [Awesome Noir repository](https://github.com/noir-lang/awesome-noir#dev-tools)
diff --git a/docs/docs/how_to/debugger/_category_.json b/docs/docs/how_to/debugger/_category_.json
new file mode 100644
index 00000000000..cc2cbb1c253
--- /dev/null
+++ b/docs/docs/how_to/debugger/_category_.json
@@ -0,0 +1,6 @@
+{
+ "label": "Debugging",
+ "position": 5,
+ "collapsible": true,
+ "collapsed": true
+}
diff --git a/docs/docs/how_to/debugger/debugging_with_the_repl.md b/docs/docs/how_to/debugger/debugging_with_the_repl.md
new file mode 100644
index 00000000000..09e5bae68ad
--- /dev/null
+++ b/docs/docs/how_to/debugger/debugging_with_the_repl.md
@@ -0,0 +1,164 @@
+---
+title: Using the REPL Debugger
+description:
+ Step by step guide on how to debug your Noir circuits with the REPL Debugger.
+keywords:
+ [
+ Nargo,
+ Noir CLI,
+ Noir Debugger,
+ REPL,
+ ]
+sidebar_position: 1
+---
+
+#### Pre-requisites
+
+In order to use the REPL debugger, first you need to install recent enough versions of Nargo and vscode-noir.
+
+## Debugging a simple circuit
+
+Let's debug a simple circuit:
+
+```rust
+fn main(x : Field, y : pub Field) {
+ assert(x != y);
+}
+```
+
+To start the REPL debugger, using a terminal, go to a Noir circuit's home directory. Then:
+
+`$ nargo debug`
+
+You should be seeing this in your terminal:
+
+```
+[main] Starting debugger
+At ~/noir-examples/recursion/circuits/main/src/main.nr:1:9
+ 1 -> fn main(x : Field, y : pub Field) {
+ 2 assert(x != y);
+ 3 }
+>
+```
+
+The debugger displays the current Noir code location, and it is now waiting for us to drive it.
+
+Let's first take a look at the available commands. For that we'll use the `help` command.
+
+```
+> help
+Available commands:
+
+ opcodes display ACIR opcodes
+ into step into to the next opcode
+ next step until a new source location is reached
+ out step until a new source location is reached
+ and the current stack frame is finished
+ break LOCATION:OpcodeLocation add a breakpoint at an opcode location
+ over step until a new source location is reached
+ without diving into function calls
+ restart restart the debugging session
+ delete LOCATION:OpcodeLocation delete breakpoint at an opcode location
+ witness show witness map
+ witness index:u32 display a single witness from the witness map
+ witness index:u32 value:String update a witness with the given value
+ memset index:usize value:String update a memory cell with the given
+ value
+ continue continue execution until the end of the
+ program
+ vars show variable values available at this point
+ in execution
+ stacktrace display the current stack trace
+ memory show memory (valid when executing unconstrained code)
+ step step to the next ACIR opcode
+
+Other commands:
+
+ help Show this help message
+ quit Quit repl
+
+```
+
+Some commands operate only for unconstrained functions, such as `memory` and `memset`. If you try to use them while execution is paused at an ACIR opcode, the debugger will simply inform you that you are not executing unconstrained code:
+
+```
+> memory
+Unconstrained VM memory not available
+>
+```
+
+Before continuing, we can take a look at the initial witness map:
+
+```
+> witness
+_0 = 1
+_1 = 2
+>
+```
+
+Cool, since `x==1`, `y==2`, and we want to check that `x != y`, our circuit should succeed. At this point we could intervene and use the witness setter command to change one of the witnesses. Let's set `y=3`, then back to 2, so we don't affect the expected result:
+
+```
+> witness
+_0 = 1
+_1 = 2
+> witness 1 3
+_1 = 3
+> witness
+_0 = 1
+_1 = 3
+> witness 1 2
+_1 = 2
+> witness
+_0 = 1
+_1 = 2
+>
+```
+
+Now we can inspect the current state of local variables. For that we use the `vars` command.
+
+```
+> vars
+>
+```
+
+We currently have no vars in context, since we are at the entry point of the program. Let's use `next` to execute until the next point in the program.
+
+```
+> vars
+> next
+At ~/noir-examples/recursion/circuits/main/src/main.nr:1:20
+ 1 -> fn main(x : Field, y : pub Field) {
+ 2 assert(x != y);
+ 3 }
+> vars
+x:Field = 0x01
+```
+
+As a result of stepping, the variable `x`, whose initial value comes from the witness map, is now in context and returned by `vars`.
+
+```
+> next
+ 1 fn main(x : Field, y : pub Field) {
+ 2 -> assert(x != y);
+ 3 }
+> vars
+y:Field = 0x02
+x:Field = 0x01
+```
+
+Stepping again we can finally see both variables and their values. And now we can see that the next assertion should succeed.
+
+Let's continue to the end:
+
+```
+> continue
+(Continuing execution...)
+Finished execution
+> q
+[main] Circuit witness successfully solved
+```
+
+Upon quitting the debugger after a solved circuit, the resulting circuit witness gets saved, equivalent to what would happen if we had run the same circuit with `nargo execute`.
+
+We just went through the basics of debugging using Noir REPL debugger. For a comprehensive reference, check out [the reference page](../../reference/debugger/debugger_repl.md).
diff --git a/docs/docs/how_to/debugger/debugging_with_vs_code.md b/docs/docs/how_to/debugger/debugging_with_vs_code.md
new file mode 100644
index 00000000000..a5858c1a5eb
--- /dev/null
+++ b/docs/docs/how_to/debugger/debugging_with_vs_code.md
@@ -0,0 +1,68 @@
+---
+title: Using the VS Code Debugger
+description:
+ Step by step guide on how to debug your Noir circuits with the VS Code Debugger configuration and features.
+keywords:
+ [
+ Nargo,
+ Noir CLI,
+ Noir Debugger,
+ VS Code,
+ IDE,
+ ]
+sidebar_position: 0
+---
+
+This guide will show you how to use VS Code with the vscode-noir extension to debug a Noir project.
+
+#### Pre-requisites
+
+- Nargo
+- vscode-noir
+- A Noir project with a `Nargo.toml`, `Prover.toml` and at least one Noir (`.nr`) containing an entry point function (typically `main`).
+
+## Running the debugger
+
+The easiest way to start debugging is to open the file you want to debug, and press `F5`. This will cause the debugger to launch, using your `Prover.toml` file as input.
+
+You should see something like this:
+
+![Debugger launched](@site/static/img/debugger/1-started.png)
+
+Let's inspect the state of the program. For that, we open VS Code's _Debug pane_. Look for this icon:
+
+![Debug pane icon](@site/static/img/debugger/2-icon.png)
+
+You will now see two categories of variables: Locals and Witness Map.
+
+![Debug pane expanded](@site/static/img/debugger/3-debug-pane.png)
+
+1. **Locals**: variables of your program. At this point in execution this section is empty, but as we step through the code it will get populated by `x`, `result`, `digest`, etc.
+
+2. **Witness map**: these are initially populated from your project's `Prover.toml` file. In this example, they will be used to populate `x` and `result` at the beginning of the `main` function.
+
+Most of the time you will probably be focusing mostly on locals, as they represent the high level state of your program.
+
+You might be interested in inspecting the witness map in case you are trying to solve a really low level issue in the compiler or runtime itself, so this concerns mostly advanced or niche users.
+
+Let's step through the program, by using the debugger buttons or their corresponding keyboard shortcuts.
+
+![Debugger buttons](@site/static/img/debugger/4-debugger-buttons.png)
+
+Now we can see in the variables pane that there's values for `digest`, `result` and `x`.
+
+![Inspecting locals](@site/static/img/debugger/5-assert.png)
+
+We can also inspect the values of variables by directly hovering on them on the code.
+
+![Hover locals](@site/static/img/debugger/6-hover.png)
+
+Let's set a break point at the `keccak256` function, so we can continue execution up to the point when it's first invoked without having to go one step at a time.
+
+We just need to click the to the right of the line number 18. Once the breakpoint appears, we can click the `continue` button or use its corresponding keyboard shortcut (`F5` by default).
+
+![Breakpoint](@site/static/img/debugger/7-break.png)
+
+Now we are debugging the `keccak256` function, notice the _Call Stack pane_ at the lower right. This lets us inspect the current call stack of our process.
+
+That covers most of the current debugger functionalities. Check out [the reference](../../reference/debugger/debugger_vscode.md) for more details on how to configure the debugger.
\ No newline at end of file
diff --git a/docs/docs/how_to/merkle-proof.mdx b/docs/docs/how_to/merkle-proof.mdx
index 003c7019a93..16c425bed76 100644
--- a/docs/docs/how_to/merkle-proof.mdx
+++ b/docs/docs/how_to/merkle-proof.mdx
@@ -5,6 +5,7 @@ description:
merkle tree with a specified root, at a given index.
keywords:
[merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree]
+sidebar_position: 4
---
Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is
diff --git a/docs/docs/noir/concepts/functions.md b/docs/docs/noir/concepts/functions.md
index 2c9bc33fdfc..f656cdfd97a 100644
--- a/docs/docs/noir/concepts/functions.md
+++ b/docs/docs/noir/concepts/functions.md
@@ -62,7 +62,7 @@ fn main(x : [Field]) // can't compile, has variable size
fn main(....// i think you got it by now
```
-Keep in mind [tests](../../getting_started/tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove:
+Keep in mind [tests](../../tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove:
```rust
fn main(x : [Field]) {
@@ -190,7 +190,7 @@ Supported attributes include:
- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function`
- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details
- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details.
-- **test**: mark the function as unit tests. See [Tests](../../getting_started/tooling/testing.md) for more details
+- **test**: mark the function as unit tests. See [Tests](../../tooling/testing.md) for more details
### Field Attribute
diff --git a/docs/docs/getting_started/tooling/_category_.json b/docs/docs/reference/debugger/_category_.json
similarity index 53%
rename from docs/docs/getting_started/tooling/_category_.json
rename to docs/docs/reference/debugger/_category_.json
index 55804c03a71..27869205ad3 100644
--- a/docs/docs/getting_started/tooling/_category_.json
+++ b/docs/docs/reference/debugger/_category_.json
@@ -1,6 +1,6 @@
{
- "position": 2,
- "label": "Tooling",
+ "label": "Debugger",
+ "position": 1,
"collapsible": true,
"collapsed": true
}
diff --git a/docs/docs/reference/debugger/debugger_known_limitations.md b/docs/docs/reference/debugger/debugger_known_limitations.md
new file mode 100644
index 00000000000..936d416ac4b
--- /dev/null
+++ b/docs/docs/reference/debugger/debugger_known_limitations.md
@@ -0,0 +1,59 @@
+---
+title: Known limitations
+description:
+ An overview of known limitations of the current version of the Noir debugger
+keywords:
+ [
+ Nargo,
+ Noir Debugger,
+ VS Code,
+ ]
+sidebar_position: 2
+---
+
+# Debugger Known Limitations
+
+There are currently some limits to what the debugger can observe.
+
+## Mutable references
+
+The debugger is currently blind to any state mutated via a mutable reference. For example, in:
+
+```
+let mut x = 1;
+let y = &mut x;
+*y = 2;
+```
+
+The update on `x` will not be observed by the debugger. That means, when running `vars` from the debugger REPL, or inspecting the _local variables_ pane in the VS Code debugger, `x` will appear with value 1 despite having executed `*y = 2;`.
+
+## Variables of type function or mutable references are opaque
+
+When inspecting variables, any variable of type `Function` or `MutableReference` will render its value as `<>` or `<>`.
+
+## Debugger instrumentation affects resulting ACIR
+
+In order to make the state of local variables observable, the debugger compiles Noir circuits interleaving foreign calls that track any mutations to them. While this works (except in the cases described above) and doesn't introduce any behavior changes, it does as a side effect produce bigger bytecode. In particular, when running the command `opcodes` on the REPL debugger, you will notice Unconstrained VM blocks that look like this:
+
+```
+...
+5 BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [], q_c: 2 }), Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(2))], q_c: 0 })]
+ | outputs=[]
+ 5.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) }
+ 5.1 | Mov { destination: RegisterIndex(3), source: RegisterIndex(1) }
+ 5.2 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } }
+ 5.3 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } }
+ 5.4 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) }
+ 5.5 | Mov { destination: RegisterIndex(3), source: RegisterIndex(3) }
+ 5.6 | Call { location: 8 }
+ 5.7 | Stop
+ 5.8 | ForeignCall { function: "__debug_var_assign", destinations: [], inputs: [RegisterIndex(RegisterIndex(2)), RegisterIndex(RegisterIndex(3))] }
+...
+```
+
+If you are interested in debugging/inspecting compiled ACIR without these synthetic changes, you can invoke the REPL debugger with the `--skip-instrumentation` flag or launch the VS Code debugger with the `skipConfiguration` property set to true in its launch configuration. You can find more details about those in the [Debugger REPL reference](debugger_repl.md) and the [VS Code Debugger reference](debugger_vscode.md).
+
+:::note
+Skipping debugger instrumentation means you won't be able to inspect values of local variables.
+:::
+
diff --git a/docs/docs/reference/debugger/debugger_repl.md b/docs/docs/reference/debugger/debugger_repl.md
new file mode 100644
index 00000000000..46e2011304e
--- /dev/null
+++ b/docs/docs/reference/debugger/debugger_repl.md
@@ -0,0 +1,360 @@
+---
+title: REPL Debugger
+description:
+ Noir Debugger REPL options and commands.
+keywords:
+ [
+ Nargo,
+ Noir CLI,
+ Noir Debugger,
+ REPL,
+ ]
+sidebar_position: 1
+---
+
+## Running the REPL debugger
+
+`nargo debug [OPTIONS] [WITNESS_NAME]`
+
+Runs the Noir REPL debugger. If a `WITNESS_NAME` is provided the debugger writes the resulting execution witness to a `WITNESS_NAME` file.
+
+### Options
+
+| Option | Description |
+| --------------------- | ------------------------------------------------------------ |
+| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover]|
+| `--package ` | The name of the package to debug |
+| `--print-acir` | Display the ACIR for compiled circuit |
+| `--deny-warnings` | Treat all warnings as errors |
+| `--silence-warnings` | Suppress warnings |
+| `-h, --help` | Print help |
+
+None of these options are required.
+
+:::note
+Since the debugger starts by compiling the target package, all Noir compiler options are also available. Check out the [compiler reference](../nargo_commands.md#nargo-compile) to learn more about the compiler options.
+:::
+
+## REPL commands
+
+Once the debugger is running, it accepts the following commands.
+
+#### `help` (h)
+
+Displays the menu of available commands.
+
+```
+> help
+Available commands:
+
+ opcodes display ACIR opcodes
+ into step into to the next opcode
+ next step until a new source location is reached
+ out step until a new source location is reached
+ and the current stack frame is finished
+ break LOCATION:OpcodeLocation add a breakpoint at an opcode location
+ over step until a new source location is reached
+ without diving into function calls
+ restart restart the debugging session
+ delete LOCATION:OpcodeLocation delete breakpoint at an opcode location
+ witness show witness map
+ witness index:u32 display a single witness from the witness map
+ witness index:u32 value:String update a witness with the given value
+ memset index:usize value:String update a memory cell with the given
+ value
+ continue continue execution until the end of the
+ program
+ vars show variable values available at this point
+ in execution
+ stacktrace display the current stack trace
+ memory show memory (valid when executing unconstrained code) value
+ step step to the next ACIR opcode
+
+Other commands:
+
+ help Show this help message
+ quit Quit repl
+
+```
+
+### Stepping through programs
+
+#### `next` (n)
+
+Step until the next Noir source code location. While other commands, such as [`into`](#into-i) and [`step`](#step-s), allow for finer grained control of the program's execution at the opcode level, `next` is source code centric. For example:
+
+```
+3 ...
+4 fn main(x: u32) {
+5 assert(entry_point(x) == 2);
+6 swap_entry_point(x, x + 1);
+7 -> assert(deep_entry_point(x) == 4);
+8 multiple_values_entry_point(x);
+9 }
+```
+
+
+Using `next` here would cause the debugger to jump to the definition of `deep_entry_point` (if available).
+
+If you want to step over `deep_entry_point` and go straight to line 8, use [the `over` command](#over) instead.
+
+#### `over`
+
+Step until the next source code location, without diving into function calls. For example:
+
+```
+3 ...
+4 fn main(x: u32) {
+5 assert(entry_point(x) == 2);
+6 swap_entry_point(x, x + 1);
+7 -> assert(deep_entry_point(x) == 4);
+8 multiple_values_entry_point(x);
+9 }
+```
+
+
+Using `over` here would cause the debugger to execute until line 8 (`multiple_values_entry_point(x);`).
+
+If you want to step into `deep_entry_point` instead, use [the `next` command](#next-n).
+
+#### `out`
+
+Step until the end of the current function call. For example:
+
+```
+ 3 ...
+ 4 fn main(x: u32) {
+ 5 assert(entry_point(x) == 2);
+ 6 swap_entry_point(x, x + 1);
+ 7 -> assert(deep_entry_point(x) == 4);
+ 8 multiple_values_entry_point(x);
+ 9 }
+ 10
+ 11 unconstrained fn returns_multiple_values(x: u32) -> (u32, u32, u32, u32) {
+ 12 ...
+ ...
+ 55
+ 56 unconstrained fn deep_entry_point(x: u32) -> u32 {
+ 57 -> level_1(x + 1)
+ 58 }
+
+```
+
+Running `out` here will resume execution until line 8.
+
+#### `step` (s)
+
+Skips to the next ACIR code. A compiled Noir program is a sequence of ACIR opcodes. However, an unconstrained VM opcode denotes the start of an unconstrained code block, to be executed by the unconstrained VM. For example (redacted for brevity):
+
+```
+0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ]
+1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))]
+ 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) }
+ 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } }
+ 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } }
+ 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) }
+ 1.4 | Call { location: 7 }
+ ...
+ 1.43 | Return
+2 EXPR [ (1, _1) -2 ]
+```
+
+The `->` here shows the debugger paused at an ACIR opcode: `BRILLIG`, at index 1, which denotes an unconstrained code block is about to start.
+
+Using the `step` command at this point would result in the debugger stopping at ACIR opcode 2, `EXPR`, skipping unconstrained computation steps.
+
+Use [the `into` command](#into-i) instead if you want to follow unconstrained computation step by step.
+
+#### `into` (i)
+
+Steps into the next opcode. A compiled Noir program is a sequence of ACIR opcodes. However, a BRILLIG opcode denotes the start of an unconstrained code block, to be executed by the unconstrained VM. For example (redacted for brevity):
+
+```
+0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ]
+1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))]
+ 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) }
+ 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } }
+ 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } }
+ 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) }
+ 1.4 | Call { location: 7 }
+ ...
+ 1.43 | Return
+2 EXPR [ (1, _1) -2 ]
+```
+
+The `->` here shows the debugger paused at an ACIR opcode: `BRILLIG`, at index 1, which denotes an unconstrained code block is about to start.
+
+Using the `into` command at this point would result in the debugger stopping at opcode 1.0, `Mov ...`, allowing the debugger user to follow unconstrained computation step by step.
+
+Use [the `step` command](#step-s) instead if you want to skip to the next ACIR code directly.
+
+#### `continue` (c)
+
+Continues execution until the next breakpoint, or the end of the program.
+
+#### `restart` (res)
+
+Interrupts execution, and restarts a new debugging session from scratch.
+
+#### `opcodes` (o)
+
+Display the program's ACIR opcode sequence. For example:
+
+```
+0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ]
+1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))]
+ 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) }
+ 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } }
+ 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } }
+ 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) }
+ 1.4 | Call { location: 7 }
+ ...
+ 1.43 | Return
+2 EXPR [ (1, _1) -2 ]
+```
+
+### Breakpoints
+
+#### `break [Opcode]` (or shorthand `b [Opcode]`)
+
+Sets a breakpoint on the specified opcode index. To get a list of the program opcode numbers, see [the `opcode` command](#opcodes-o). For example:
+
+```
+0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ]
+1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))]
+ 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) }
+ 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } }
+ 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } }
+ 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) }
+ 1.4 | Call { location: 7 }
+ ...
+ 1.43 | Return
+2 EXPR [ (1, _1) -2 ]
+```
+
+In this example, issuing a `break 1.2` command adds break on opcode 1.2, as denoted by the `*` character:
+
+```
+0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ]
+1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))]
+ 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) }
+ 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } }
+ 1.2 | * Const { destination: RegisterIndex(1), value: Value { inner: 0 } }
+ 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) }
+ 1.4 | Call { location: 7 }
+ ...
+ 1.43 | Return
+2 EXPR [ (1, _1) -2 ]
+```
+
+Running [the `continue` command](#continue-c) at this point would cause the debugger to execute the program until opcode 1.2.
+
+#### `delete [Opcode]` (or shorthand `d [Opcode]`)
+
+Deletes a breakpoint at an opcode location. Usage is analogous to [the `break` command](#).
+
+### Variable inspection
+
+#### vars
+
+Show variable values available at this point in execution.
+
+:::note
+The ability to inspect variable values from the debugger depends on compilation to be run in a special debug instrumentation mode. This instrumentation weaves variable tracing code with the original source code.
+
+So variable value inspection comes at the expense of making the resulting ACIR bytecode bigger and harder to understand and optimize.
+
+If you find this compromise unacceptable, you can run the debugger with the flag `--skip-debug-instrumentation`. This will compile your circuit without any additional debug information, so the resulting ACIR bytecode will be identical to the one produced by standard Noir compilation. However, if you opt for this, the `vars` command will not be available while debugging.
+:::
+
+
+### Stacktrace
+
+#### `stacktrace`
+
+Displays the current stack trace.
+
+
+### Witness map
+
+#### `witness` (w)
+
+Show witness map. For example:
+
+```
+_0 = 0
+_1 = 2
+_2 = 1
+```
+
+#### `witness [Witness Index]`
+
+Display a single witness from the witness map. For example:
+
+```
+> witness 1
+_1 = 2
+```
+
+#### `witness [Witness Index] [New value]`
+
+Overwrite the given index with a new value. For example:
+
+```
+> witness 1 3
+_1 = 3
+```
+
+
+### Unconstrained VM memory
+
+#### `memory`
+
+Show unconstrained VM memory state. For example:
+
+```
+> memory
+At opcode 1.13: Store { destination_pointer: RegisterIndex(0), source: RegisterIndex(3) }
+...
+> registers
+0 = 0
+1 = 10
+2 = 0
+3 = 1
+4 = 1
+5 = 2³²
+6 = 1
+> into
+At opcode 1.14: Const { destination: RegisterIndex(5), value: Value { inner: 1 } }
+...
+> memory
+0 = 1
+>
+```
+
+In the example above: we start with clean memory, then step through a `Store` opcode which stores the value of register 3 (1) into the memory address stored in register 0 (0). Thus now `memory` shows memory address 0 contains value 1.
+
+:::note
+This command is only functional while the debugger is executing unconstrained code.
+:::
+
+#### `memset [Memory address] [New value]`
+
+Update a memory cell with the given value. For example:
+
+```
+> memory
+0 = 1
+> memset 0 2
+> memory
+0 = 2
+> memset 1 4
+> memory
+0 = 2
+1 = 4
+>
+```
+
+:::note
+This command is only functional while the debugger is executing unconstrained code.
+:::
\ No newline at end of file
diff --git a/docs/docs/reference/debugger/debugger_vscode.md b/docs/docs/reference/debugger/debugger_vscode.md
new file mode 100644
index 00000000000..c027332b3b0
--- /dev/null
+++ b/docs/docs/reference/debugger/debugger_vscode.md
@@ -0,0 +1,82 @@
+---
+title: VS Code Debugger
+description:
+ VS Code Debugger configuration and features.
+keywords:
+ [
+ Nargo,
+ Noir CLI,
+ Noir Debugger,
+ VS Code,
+ IDE,
+ ]
+sidebar_position: 0
+---
+
+# VS Code Noir Debugger Reference
+
+The Noir debugger enabled by the vscode-noir extension ships with default settings such that the most common scenario should run without any additional configuration steps.
+
+These defaults can nevertheless be overridden by defining a launch configuration file. This page provides a reference for the properties you can override via a launch configuration file, as well as documenting the Nargo `dap` command, which is a dependency of the VS Code Noir debugger.
+
+
+## Creating and editing launch configuration files
+
+To create a launch configuration file from VS Code, open the _debug pane_, and click on _create a launch.json file_.
+
+![Creating a launch configuration file](@site/static/img/debugger/ref1-create-launch.png)
+
+A `launch.json` file will be created, populated with basic defaults.
+
+### Noir Debugger launch.json properties
+
+#### projectFolder
+
+_String, optional._
+
+Absolute path to the Nargo project to debug. By default, it is dynamically determined by looking for the nearest `Nargo.toml` file to the active file at the moment of launching the debugger.
+
+#### proverName
+
+_String, optional._
+
+Name of the prover input to use. Defaults to `Prover`, which looks for a file named `Prover.toml` at the `projectFolder`.
+
+#### generateAcir
+
+_Boolean, optional._
+
+If true, generate ACIR opcodes instead of unconstrained opcodes which will be closer to release binaries but less convenient for debugging. Defaults to `false`.
+
+#### skipInstrumentation
+
+_Boolean, optional._
+
+Skips variables debugging instrumentation of code, making debugging less convenient but the resulting binary smaller and closer to production. Defaults to `false`.
+
+:::note
+Skipping instrumentation causes the debugger to be unable to inspect local variables.
+:::
+
+## `nargo dap [OPTIONS]`
+
+When run without any option flags, it starts the Nargo Debug Adapter Protocol server, which acts as the debugging backend for the VS Code Noir Debugger.
+
+All option flags are related to preflight checks. The Debug Adapter Protocol specifies how errors are to be informed from a running DAP server, but it doesn't specify mechanisms to communicate server initialization errors between the DAP server and its client IDE.
+
+Thus `nargo dap` ships with a _preflight check_ mode. If flag `--preflight-check` and the rest of the `--preflight-*` flags are provided, Nargo will run the same initialization routine except it will not start the DAP server.
+
+`vscode-noir` will then run `nargo dap` in preflight check mode first before a debugging session starts. If the preflight check ends in error, vscode-noir will present stderr and stdout output from this process through its own Output pane in VS Code. This makes it possible for users to diagnose what pieces of configuration might be wrong or missing in case of initialization errors.
+
+If the preflight check succeeds, `vscode-noir` proceeds to start the DAP server normally but running `nargo dap` without any additional flags.
+
+### Options
+
+| Option | Description |
+| --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
+| `--preflight-check` | If present, dap runs in preflight check mode. |
+| `--preflight-project-folder ` | Absolute path to the project to debug for preflight check. |
+| `--preflight-prover-name ` | Name of prover file to use for preflight check |
+| `--preflight-generate-acir` | Optional. If present, compile in ACIR mode while running preflight check. |
+| `--preflight-skip-instrumentation` | Optional. If present, compile without introducing debug instrumentation while running preflight check. |
+| `-h, --help` | Print help. |
diff --git a/docs/docs/tooling/debugger.md b/docs/docs/tooling/debugger.md
new file mode 100644
index 00000000000..184c436068f
--- /dev/null
+++ b/docs/docs/tooling/debugger.md
@@ -0,0 +1,27 @@
+---
+title: Debugger
+description: Learn about the Noir Debugger, in its REPL or VS Code versions.
+keywords: [Nargo, VSCode, Visual Studio Code, REPL, Debugger]
+sidebar_position: 2
+---
+
+# Noir Debugger
+
+There are currently two ways of debugging Noir programs:
+
+1. From VS Code, via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir).
+2. Via the REPL debugger, which ships with Nargo.
+
+In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation) and vscode-noir:
+
+- Noir 0.xx
+- Nargo 0.xx
+- vscode-noir 0.xx
+
+:::info
+At the moment, the debugger supports debugging binary projects, but not contracts.
+:::
+
+We cover the VS Code Noir debugger more in depth in [its VS Code debugger how-to guide](../how_to/debugger/debugging_with_vs_code.md) and [the reference](../reference/debugger/debugger_vscode.md).
+
+The REPL debugger is discussed at length in [the REPL debugger how-to guide](../how_to/debugger/debugging_with_the_repl.md) and [the reference](../reference/debugger/debugger_repl.md).
diff --git a/docs/docs/getting_started/tooling/language_server.md b/docs/docs/tooling/language_server.md
similarity index 100%
rename from docs/docs/getting_started/tooling/language_server.md
rename to docs/docs/tooling/language_server.md
diff --git a/docs/docs/getting_started/tooling/testing.md b/docs/docs/tooling/testing.md
similarity index 100%
rename from docs/docs/getting_started/tooling/testing.md
rename to docs/docs/tooling/testing.md
diff --git a/docs/sidebars.js b/docs/sidebars.js
index f1e79ba9ebc..cf7e852fed5 100644
--- a/docs/sidebars.js
+++ b/docs/sidebars.js
@@ -65,6 +65,11 @@ export default {
label: 'Reference',
items: [{ type: 'autogenerated', dirName: 'reference' }],
},
+ {
+ type: 'category',
+ label: 'Tooling',
+ items: [{ type: 'autogenerated', dirName: 'tooling' }],
+ },
{
type: 'html',
value: '',
diff --git a/docs/static/img/debugger/1-started.png b/docs/static/img/debugger/1-started.png
new file mode 100644
index 00000000000..6f764d4e601
Binary files /dev/null and b/docs/static/img/debugger/1-started.png differ
diff --git a/docs/static/img/debugger/2-icon.png b/docs/static/img/debugger/2-icon.png
new file mode 100644
index 00000000000..31706670ccb
Binary files /dev/null and b/docs/static/img/debugger/2-icon.png differ
diff --git a/docs/static/img/debugger/3-debug-pane.png b/docs/static/img/debugger/3-debug-pane.png
new file mode 100644
index 00000000000..24c112da96f
Binary files /dev/null and b/docs/static/img/debugger/3-debug-pane.png differ
diff --git a/docs/static/img/debugger/4-debugger-buttons.png b/docs/static/img/debugger/4-debugger-buttons.png
new file mode 100644
index 00000000000..64c1e05be8a
Binary files /dev/null and b/docs/static/img/debugger/4-debugger-buttons.png differ
diff --git a/docs/static/img/debugger/5-assert.png b/docs/static/img/debugger/5-assert.png
new file mode 100644
index 00000000000..0bfed6562af
Binary files /dev/null and b/docs/static/img/debugger/5-assert.png differ
diff --git a/docs/static/img/debugger/6-hover.png b/docs/static/img/debugger/6-hover.png
new file mode 100644
index 00000000000..20579ec461e
Binary files /dev/null and b/docs/static/img/debugger/6-hover.png differ
diff --git a/docs/static/img/debugger/7-break.png b/docs/static/img/debugger/7-break.png
new file mode 100644
index 00000000000..aca5121d722
Binary files /dev/null and b/docs/static/img/debugger/7-break.png differ
diff --git a/docs/static/img/debugger/debugger-intro.gif b/docs/static/img/debugger/debugger-intro.gif
new file mode 100644
index 00000000000..06e3b853555
Binary files /dev/null and b/docs/static/img/debugger/debugger-intro.gif differ
diff --git a/docs/static/img/debugger/ref1-create-launch.png b/docs/static/img/debugger/ref1-create-launch.png
new file mode 100644
index 00000000000..0b6cb8b3ec6
Binary files /dev/null and b/docs/static/img/debugger/ref1-create-launch.png differ