diff --git a/content/docs/expo-devtools/changelog.mdx b/content/docs/expo-devtools/changelog.mdx
index 1d291a0..6a600db 100644
--- a/content/docs/expo-devtools/changelog.mdx
+++ b/content/docs/expo-devtools/changelog.mdx
@@ -7,6 +7,31 @@ description: Every published release of @axonpack/expo-devtools, newest first.
Every published release, newest first. The current version is **3.0.0**.
+## 3.1.0
+
+
+
+### Minor changes
+
+- **An Axonpack tab in React Native DevTools**, beside Console and Sources, from the one line in `metro.config.js` you already had
+- **Nothing to set up on the device**: installing the package registers the tab, behind `__DEV__`
+- **Chrome's Network panel on the desktop**: the same requests, sockets, filters and settings as the app's Network tab, in a sortable, resizable table
+- **Request details**: headers, payload, preview, response, events, timing, cookies and initiator, with a hex dump for a binary body
+- **Overrides and blocking**: answer a request with your own status and body, or block its URL, from the request's menu
+- **A sandbox on the desktop**: edit any captured request, send it from the device and read the response side by side
+- **Code for any request**: cURL, HTTPie, fetch, axios, Node.js, Python, Swift, Kotlin and Go
+- **Copy and save to your computer**: copies land on the computer's clipboard, and a response body downloads as a file
+- **Network conditions from the desktop**: throttling, custom speeds and the user agent
+- **The app's theme in the tab**, with a theme picker, and a Reload chip that reloads the app
+- **Open DevTools from the app**: a debug build served by Metro shows a strip in the panel that opens React Native DevTools on the Axonpack tab
+- **Fetch/XHR** now keeps every request sent through `fetch` or `XMLHttpRequest`, whatever came back
+- Removed the `/axonpack-panel` route from the Metro wrap and `PANEL_ROUTE` from its exports. The page behind it was a mock-up and was never in the published files.
+
+### Patch changes
+
+- Updated dependencies [99f49a5]
+- @axonpack/react-native-devtools-tab@0.1.1
+
## 3.0.0
diff --git a/content/docs/expo-devtools/compatibility.mdx b/content/docs/expo-devtools/compatibility.mdx
index b825df8..06e6fc6 100644
--- a/content/docs/expo-devtools/compatibility.mdx
+++ b/content/docs/expo-devtools/compatibility.mdx
@@ -14,6 +14,11 @@ description: The versions this is built against, what it requires you to have in
That row is what the package is **built and tested against** — the versions in its own dev
dependencies and in the example app that exercises every tab.
+The [React Native DevTools tab](/docs/expo-devtools/react-native-devtools) comes from
+`@axonpack/react-native-devtools-tab`, which this package depends on. It needs React 19.2 or later,
+and a React Native with React Native DevTools, the debugger `j` opens. It is built and tested against
+the same row.
+
Every Expo package this needs is a peer dependency, so each resolves to the version your own SDK
ships. The row above is what the package is built and tested against, not a range it refuses to run
diff --git a/content/docs/expo-devtools/example-app.mdx b/content/docs/expo-devtools/example-app.mdx
index a494feb..79339dc 100644
--- a/content/docs/expo-devtools/example-app.mdx
+++ b/content/docs/expo-devtools/example-app.mdx
@@ -32,6 +32,9 @@ bun run ios # or: bun run android (full native build)
## A worked configuration
+`example/metro.config.js` already has the `withDevtools` line, so pressing `j` in Metro opens React
+Native DevTools with the [Axonpack tab](/docs/expo-devtools/react-native-devtools) in it.
+
`example/devtools.ts` doubles as a worked configuration: a dark default theme, a custom `midnight` one,
a `console.context` you can reach from the prompt, and all four storage adapters registered against
real AsyncStorage, MMKV, SecureStore and an in-memory `Map`.
diff --git a/content/docs/expo-devtools/index.mdx b/content/docs/expo-devtools/index.mdx
index cc068ad..7bb4da6 100644
--- a/content/docs/expo-devtools/index.mdx
+++ b/content/docs/expo-devtools/index.mdx
@@ -22,6 +22,9 @@ npx expo install @axonpack/expo-devtools react-native-safe-area-context react-na
| **[Crashes](/docs/expo-devtools/crash-reporting)** | JS errors, unhandled rejections, render errors and native exceptions, as readable reports |
| **[Debug](/docs/expo-devtools/debug)** | Tools that block or crash a thread on purpose |
+The Network tab is also on your computer, in [React Native
+DevTools](/docs/expo-devtools/react-native-devtools), from one line in `metro.config.js`.
+
Two more guides cover things that are not tabs: [themes](/docs/expo-devtools/themes), and
[capturing inside an in-app browser](/docs/expo-devtools/in-app-browsers).
diff --git a/content/docs/expo-devtools/meta.json b/content/docs/expo-devtools/meta.json
index cba42c8..fece363 100644
--- a/content/docs/expo-devtools/meta.json
+++ b/content/docs/expo-devtools/meta.json
@@ -18,6 +18,7 @@
"debug",
"themes",
"in-app-browsers",
+ "react-native-devtools",
"---Shipping---",
"production",
"example-app",
diff --git a/content/docs/expo-devtools/network.mdx b/content/docs/expo-devtools/network.mdx
index 951a9d6..2e93c1b 100644
--- a/content/docs/expo-devtools/network.mdx
+++ b/content/docs/expo-devtools/network.mdx
@@ -141,7 +141,7 @@ dependency.
## Limits
-- The list holds the **200** most recent requests; older ones fall off the end. Request and response
+- The list holds the **1,000** most recent requests; older ones fall off the end. Request and response
bodies are kept in full, never truncated.
- The phase breakdown is measured by the native networking stack, so it needs a development build,
and it only covers traffic that went through a stack this package hooks. Everything else keeps the
diff --git a/content/docs/expo-devtools/production.mdx b/content/docs/expo-devtools/production.mdx
index cbd174a..7fb52f9 100644
--- a/content/docs/expo-devtools/production.mdx
+++ b/content/docs/expo-devtools/production.mdx
@@ -45,6 +45,16 @@ unreachable with the devtools off.
not gated on `__DEV__`, so a build with `enabled: true` gets a prompt that runs whatever is typed
into it. Set `console: { repl: false }` for any build where that is not what you want.
+## The Metro line
+
+`withDevtools` in `metro.config.js` costs a release build nothing. All it adds to the config is
+dev-server middleware, which nothing but a dev server reads, so the bundle is the same with it as
+without. The tab itself registers only when `__DEV__` is true, so a release bundle carries none of it.
+
+Metro reads the config when it builds for release too, so keep `@axonpack/expo-devtools` in
+`dependencies`, not `devDependencies`, if your release install skips dev dependencies. A `__DEV__`
+check cannot guard the line: `metro.config.js` runs in Node, where `__DEV__` does not exist.
+
## Next step
diff --git a/content/docs/expo-devtools/quick-start.mdx b/content/docs/expo-devtools/quick-start.mdx
index e9f6db0..aeba216 100644
--- a/content/docs/expo-devtools/quick-start.mdx
+++ b/content/docs/expo-devtools/quick-start.mdx
@@ -75,6 +75,21 @@ tabs are already recording. The Storage tab is empty until you tell it which sto
[Storage](/docs/expo-devtools/storage). The panel reopens on whichever tab you last had open, for as long as
the app is running.
+## 3. Optional: the Network tab on your computer
+
+For the same Network tab in React Native DevTools too, add one line to `metro.config.js` and restart
+Metro:
+
+```js title="metro.config.js"
+const { getDefaultConfig } = require('expo/metro-config');
+const { withDevtools } = require('@axonpack/expo-devtools/metro');
+
+module.exports = withDevtools(getDefaultConfig(__dirname));
+```
+
+Press `j` in Metro and the **Axonpack** tab is beside Console and Sources. [React Native
+DevTools](/docs/expo-devtools/react-native-devtools) has the rest.
+
## Things that trip people up
- **Mount the provider exactly once.** The root is the place, because one mount there covers every
diff --git a/content/docs/expo-devtools/react-native-devtools.mdx b/content/docs/expo-devtools/react-native-devtools.mdx
new file mode 100644
index 0000000..e953b56
--- /dev/null
+++ b/content/docs/expo-devtools/react-native-devtools.mdx
@@ -0,0 +1,92 @@
+---
+title: React Native DevTools
+description: The Network tab on your computer, in its own Axonpack tab beside Console and Sources.
+---
+
+The package puts an **Axonpack** tab in React Native DevTools, the debugger that opens when you press
+`j` in Metro. It shows the same Network log as the panel on the device, laid out like Chrome's
+Network panel, and it reads the app's own stores: a request made on the phone is a row on the
+desktop the moment it starts, and a filter set on one side is set on the other.
+
+## Set it up
+
+One line in `metro.config.js`:
+
+```js
+const { getDefaultConfig } = require('expo/metro-config');
+const { withDevtools } = require('@axonpack/expo-devtools/metro');
+
+module.exports = withDevtools(getDefaultConfig(__dirname));
+```
+
+Restart Metro after changing it; a reload of the app is not enough, because Metro reads its config
+once when it starts. Nothing is set up on the device: the tab registers itself in a debug build,
+behind `__DEV__`, and a release build carries none of it.
+
+## Open it
+
+- Press `j` in the terminal running Metro, or pick **Open DevTools** in the app's dev menu.
+- Or open the panel on the device. In a debug build whose bundle came from Metro, a strip under the
+ panel's header says **Metro server detected**, and its **Open DevTools** button opens React
+ Native DevTools on the Axonpack tab.
+
+The tab takes a second to appear after DevTools opens: it is added once DevTools has connected to
+the app and asked which tabs it has.
+
+## Network
+
+Everything the device's Network tab has:
+
+- The request table, with sortable, resizable columns, grouping by client and big or dense rows.
+- The filter bar: search with regex, match case and whole word, invert, the request types, and
+ More filters for methods, sources, status, size and duration.
+- The overview strip across the top of the log. Drag across it to keep only the requests that started
+ in that window.
+- The request pane: Headers, Payload, Preview, Response, EventStream, Timing, Cookies and
+ Initiator, and Messages for a socket. A binary response shows a hex dump.
+- The row menu, on a right-click or the ⋮ in the request pane: the copy items, **Save response
+ body**, **Block this URL**, **Override response…** and **Try in sandbox**.
+- Throttling in the toolbar, and custom speeds, the user agent and stacked header values under the
+ gear.
+
+
+## The sandbox
+
+**Try in sandbox** opens a captured request in the request pane, laid out like a web API client: the
+method and URL across the top, the request and its response side by side.
+
+- **Authentication**, **Network Conditions**, **Cookies**, **Headers**, **Query Parameters** and
+ **Body** are sections of their own. A bearer token or API key is hidden until you show it.
+- **Send** sends the request from the device, through the app's own `fetch`, so it goes out with the
+ device's network, cookies and conditions, and shows up as a row in the log as well.
+- The response shows its time, size and status, then its cookies, the headers that were sent and
+ the ones that came back, and the body as a JSON tree or as raw text.
+- **Code Snippet** writes the request as cURL, HTTPie, JavaScript fetch, axios, Node.js fetch, Python
+ requests, Swift URLSession, Kotlin OkHttp or Go net/http.
+
+## Copying and saving
+
+Copies land on **your computer's** clipboard, not the device's, and **Save response body**
+downloads the body as a file. Both are done by the browser DevTools runs in.
+
+## The bar
+
+- **Axonpack** and its mark, on the left. Hover the mark for what the tab is and links to the docs,
+ the changelog, the other libraries and GitHub.
+- The theme picker: the app's own themes, and a choice made here is the app's choice too.
+- **Reload** reloads the app, as `r` in Metro does.
+- The refresh icon draws the tab again without touching the app. It does not pick up code you have
+ saved since; use **Reload** for that.
+
+Every control is listed in the [DevTools tab reference](/docs/expo-devtools/reference/devtools-tab).
+
+## When the tab does not appear
+
+Restart Metro first: it reads `metro.config.js` only when it starts. If the tab is still missing, the
+DevTools console says why, and [Troubleshooting](/docs/react-native-devtools-tab/troubleshooting)
+lists each message and what to do about it.
+
+
+ The same limit as on the device, and for the same reason: every body is kept whole. The desktop
+ table draws every row, which stays quick at that size.
+
diff --git a/content/docs/expo-devtools/reference/devtools-tab.mdx b/content/docs/expo-devtools/reference/devtools-tab.mdx
new file mode 100644
index 0000000..ff35a41
--- /dev/null
+++ b/content/docs/expo-devtools/reference/devtools-tab.mdx
@@ -0,0 +1,180 @@
+---
+title: React Native DevTools tab
+description: Every control in the Axonpack tab on your computer: the bar, the toolbar, the filter bar, settings, the table, the request pane, overrides and the sandbox.
+---
+
+The tab reads the same stores as the panel on the device, so a filter, a sort, a setting or a rule
+changed here is changed there too, and the other way round. Setting it up is on [React Native
+DevTools](/docs/expo-devtools/react-native-devtools).
+
+## The bar
+
+| Item | What it does |
+| ------------------- | ---------------------------------------------------------------------------------------------------------------------- |
+| **Axonpack** mark | Hover it for what the tab is, with links to the docs, the changelog, the other libraries and GitHub. |
+| Tabs | Press and hold a tab to pick it up, then drag it to a new place. |
+| » | Appears when the tabs do not fit, and lists the ones that were left out. |
+| Palette | The app's themes. A theme picked here is the app's theme too. |
+| **Reload** | Reloads the app, as `r` in Metro does. |
+| Refresh | Draws the tab again without touching the app. It does not pick up code saved since; **Reload** does. |
+
+A tab with a dotted pattern across its top is one of this package's own. The order you drag them
+into lasts until the app reloads.
+
+
+## Toolbar
+
+| Control | What it does |
+| ---------------- | ------------------------------------------------------------------------------------------------------------- |
+| Record | Pauses and resumes capture. Red while recording. |
+| Clear | Throws away the log. |
+| Sort arrow | Flips the direction of the current sort. Its tooltip says what pressing it would give you. |
+| Filter | Shows or hides the filter bar. Filled while any filter is on. |
+| Throttling | `No throttling`, `Slow 3G`, `Fast 3G`, `Fast 4G`, `Offline`, `Custom`. The same profiles as the device's. |
+| Export | Downloads the rows the filters keep as JSON, the same file the device's Export shares. |
+| Settings (gear) | Shows or hides the settings pane. |
+
+## Filter bar
+
+| Control | What it does |
+| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
+| Filter | Matches method, URL, status code and source. Match case, match whole word and regular expression sit inside the box, with a clear ✕. |
+| **Invert** | Shows everything the search does not match. |
+| Clear all filters | Resets every filter, and the window picked on the overview. |
+| **More filters** | Opens the menu below. A count on it says how many of those are on. |
+| Types | `All`, `Fetch/XHR`, `JS`, `Img`, `Media`, `Other`. Fetch/XHR is every request sent through `fetch` or `XMLHttpRequest`; the others go by the response's MIME type. |
+
+### More filters
+
+| Item | What it does |
+| ------------------------------- | -------------------------------------------------------------------------- |
+| Hide data URLs | Drops requests whose URL starts with `data:`. |
+| Hide failed requests | Drops requests that errored. |
+| Only requests in flight | Keeps the ones that have not finished. |
+| Blocked or overridden requests | Keeps the ones a rule of yours answered. |
+| Status | An expression: `404`, `4xx`, `>= 400`, `200-299`, `failed`, `pending`. |
+| Larger than, Smaller than | A size, with a unit or without: `20kb`, `2mb`. |
+| Slower than, Faster than | A duration: `500ms`, `2s`. |
+| Methods | One per method captured. More than one can be on. |
+| Sources | One per source seen. More than one can be on. |
+
+A field that cannot be read turns red and filters nothing.
+
+## Settings
+
+| Setting | What it does |
+| --------------------- | ------------------------------------------------------------------------------------------------------ |
+| Big request rows | Taller rows, each cell with its second line: the status text, what the app was handed, and the time to the first byte. The tab's own setting, apart from the device's. |
+| Group by fetch client | Groups the rows under a header per source, with a count. |
+| Overview | Shows the overview strip above the table. |
+| Stack header values | In Headers, puts each value under its name. The tab's own setting, apart from the device's. |
+| Sort by | Time, size, duration or status, and the direction. |
+| User agent | `Default`, `iPhone Safari`, `Android Chrome`, `Chrome (macOS)`, `Chrome (Windows)`, `Googlebot`, `Custom`. |
+| Custom throttling | Download (kbps), Upload (kbps) and Latency (ms): what the `Custom` throttle means. |
+
+## Overview
+
+Each request is a bar across time, green while it waits for the first byte and blue while the body
+comes in. Drag across it to keep only the requests that started in that window, drag a handle to move
+one edge, and double-click to let go. The window is the same one the device's overview picks.
+
+## The table
+
+| Column | What it shows |
+| ------ | ---------------------------------------------------------------------------------- |
+| Name | The last part of the path and the query, with an icon for the kind of response. |
+| Method | The HTTP method. |
+| Status | The code, with big rows its text under it, or `(pending)`, `(canceled)` or `(failed)`. |
+| Source | The client that sent it: `fetch`, `xhr`, `expo/fetch`, a WebView and so on. |
+| Size | What crossed the wire, and with big rows, what the app was handed under it. |
+| Time | How long it took, and with big rows, the time to the first byte under it. |
+
+Click **Status**, **Size** or **Time** to sort by it, and again to flip the direction. Drag the line
+between two headers to resize a column. A failed request is drawn in red. Hovering a cell shows both
+of its lines, whatever the row size.
+
+Under the table, the status line counts the requests, what was transferred and when the last one
+finished. While a filter is on, each figure reads *shown / all*.
+
+Click a row to open it in the request pane. Right-click a row for its menu.
+
+## Request pane
+
+It opens beside the table, and the table narrows to its Name column. Drag the line between them to
+change the split. ✕ closes it.
+
+| Tab | What it shows |
+| ----------- | -------------------------------------------------------------------------------------- |
+| Headers | Network conditions when any were on, then General, Response Headers and Request Headers. |
+| Payload | The request body as fields, or as a JSON tree. Uploaded files by name and size. |
+| Preview | An image, a page, an SVG, JSON or XML as a tree, or the code, highlighted. |
+| Response | The body as it came. A binary body as a hex dump. |
+| EventStream | A server-sent event stream's events, in place of Preview and Response. |
+| Timing | The phases the platform measured, or the wait and the download. |
+| Cookies | The cookies the request sent and the ones the response set. |
+| Initiator | The code that made the request, with the source around the line. |
+| Messages | For a socket, every message in both directions, in place of the others. |
+
+The ⋮ at the end of the tab bar opens the request's menu.
+
+## The request menu
+
+Right-click on a row, or ⋮ in the request pane.
+
+| Item | What it does |
+| ---------------------------- | ----------------------------------------------------------------------------------- |
+| **Try in sandbox** | Opens the request in the sandbox, below. |
+| Copy URL | To your computer's clipboard. |
+| Copy as cURL, fetch, Node.js | The request as a command, to your computer's clipboard. |
+| Copy request payload | When the request had a body. |
+| Copy response | When the response has a text body. |
+| **Save response body** | Downloads the body as a file, named after the request. |
+| **Block this URL** | Makes the app's requests to it fail. Once blocked, it reads **Stop blocking this URL**. |
+| **Override response…** | Opens the override editor, below. |
+
+A copy shows **Copied**, or why it could not copy, at the foot of the tab.
+
+## Override editor
+
+Opens in the request pane, with ✕ to go back to the request.
+
+| Field | What it is |
+| ------------ | ----------------------------------------------------------------------------- |
+| Status | The code to answer with. Anything that is not a status from 100 to 599 is 200. |
+| Content type | Sent as the response's `Content-Type`. Empty means `application/json`. |
+| Body | What the app gets back. |
+
+It starts from the rule the URL already has, or from what the server really answered. **Save**
+applies it to every request to that exact URL, **Remove** drops it, **Cancel** goes back. While a rule
+is on the request is not sent at all, so the endpoint does not have to exist.
+
+## Sandbox
+
+Opens in the request pane, with ✕ to go back to the request. The request is on the left and its
+response on the right; in a narrow pane they stack.
+
+| Part | What it holds |
+| ------------------ | --------------------------------------------------------------------------------------------------------------------- |
+| Address bar | The method, coloured by verb, the URL without its query, a copy button, and **Send**. |
+| Authentication | `none`, `bearer` (a token) or `api key` (a header name and a value). A secret is hidden until the eye shows it. |
+| Network Conditions | Throttling, custom speeds and the user agent. The whole app's, not this request's. |
+| Cookies | Key and value rows, sent together as one `Cookie` header. |
+| Headers | Key and value rows. |
+| Query Parameters | Key and value rows, added to the URL. |
+| Body | The request body, with **Format JSON** when it is JSON that is not laid out yet. A GET or HEAD is sent without one. |
+| Code Snippet | The request as cURL, HTTPie, JavaScript fetch, axios, Node.js fetch, Python requests, Swift URLSession, Kotlin OkHttp or Go net/http, with a copy button. Folded to start with. |
+
+A table always ends with a blank row that becomes the next one as you type. A row's checkbox leaves it
+out of the request without deleting it.
+
+**Send** sends the request from the device, through the app's own `fetch`. The response then shows:
+
+| Part | What it holds |
+| ---------------- | -------------------------------------------------------------------------------- |
+| Head | The time, the size and the status. |
+| Cookies | The cookies the response set. |
+| Request Headers | The headers the request actually went with, auth and cookies included. |
+| Response Headers | Every header that came back. |
+| Body | Its content type, **Preview** as a JSON tree or **Raw** with line numbers, a copy button, and **Download**. |
+
+The sent request is also a row in the log, on both surfaces.
diff --git a/content/docs/expo-devtools/reference/index.mdx b/content/docs/expo-devtools/reference/index.mdx
index b368e6b..5d4facd 100644
--- a/content/docs/expo-devtools/reference/index.mdx
+++ b/content/docs/expo-devtools/reference/index.mdx
@@ -19,6 +19,7 @@ crashes without it: the control says what it needs instead.
+
## API
diff --git a/content/docs/expo-devtools/reference/meta.json b/content/docs/expo-devtools/reference/meta.json
index eb431cd..56480d0 100644
--- a/content/docs/expo-devtools/reference/meta.json
+++ b/content/docs/expo-devtools/reference/meta.json
@@ -12,6 +12,7 @@
"performance-tab",
"storage-tab",
"debug-tab",
+ "devtools-tab",
"---API---",
"provider",
"hooks",
diff --git a/content/docs/expo-devtools/reference/network-tab.mdx b/content/docs/expo-devtools/reference/network-tab.mdx
index fc380bf..fd00aff 100644
--- a/content/docs/expo-devtools/reference/network-tab.mdx
+++ b/content/docs/expo-devtools/reference/network-tab.mdx
@@ -23,7 +23,6 @@ truncated.
| Record / Clear | As on [the panel](/docs/expo-devtools/reference/panel#toolbar-row). |
| Sort (↑ / ↓) | Flips the direction of whatever **Sort by** is set to. Its label says what pressing it would give you. |
| Filter (⌕ list) | Opens the filters panel below. |
-| Preserve log (🔖) | On by default. Keeps captured rows when a wired-up WebView page navigates; off means the log clears with the page. |
| Export (⤓) | Opens the OS share sheet with the **currently filtered** list as JSON, named `network-log-.json`. |
| Settings (⚙) | Opens the settings panel below. |
@@ -33,7 +32,7 @@ truncated.
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| Search box | Matches method, URL, status code and source, not header or body text. Clear it with the ✕ inside the box. |
| **Invert** chip | Shows everything that does *not* match the search text. |
-| **Type** chips | `All`, `Fetch/XHR`, `JS`, `Img`, `Media`, `Other`, classified from the response MIME type. |
+| **Type** chips | `All`, `Fetch/XHR`, `JS`, `Img`, `Media`, `Other`. Fetch/XHR is every request sent through `fetch` or `XMLHttpRequest`, whatever came back; the others go by the response's MIME type. |
| **Status** chips | `All` plus one per band captured (`2xx`, `4xx`, `Failed`, `Pending`). Each one writes the field below. |
| Status expression | `404`, `4xx`, `>= 400`, `200-299`, `failed`, `pending`. Unreadable text turns the field red and filters nothing. |
| **Method** chips | One per method actually captured (`GET`, `POST`, …), and more than one can be on at once. `All` clears them. |
@@ -100,11 +99,11 @@ Shown when **Show overview** is on, and only once at least one request is captur
| Badges | Resource type · source (only when it came from a WebView) · response size (large rows only). |
| ⋮ | The copy menu, also on long-press anywhere in the row. |
-The row menu: **Copy URL**, **Copy as cURL**, **Copy as fetch**, **Copy as fetch (Node.js)**, then
+The row menu: **Try in sandbox**, then **Copy URL**, **Copy as cURL**, **Copy as fetch**, **Copy as fetch (Node.js)**, then
**Copy request payload** and **Copy response** when those exist, **Share response body** when there is
a body at all (the only way to get an image or a PDF out), then **Block this URL** and **Override
-response…**. The sheet's own menu is the same list with **Try in sandbox** on top and no **Override
-response…**, since that editor opens from the list.
+response…**. The sheet's own menu is the same list without **Override response…**, since that editor
+opens from the list.
## A socket row
diff --git a/content/docs/expo-devtools/reference/panel.mdx b/content/docs/expo-devtools/reference/panel.mdx
index adbd058..2cccfab 100644
--- a/content/docs/expo-devtools/reference/panel.mdx
+++ b/content/docs/expo-devtools/reference/panel.mdx
@@ -16,11 +16,20 @@ button itself never appears inside the modal.
| Palette (🎨) | Opens the theme list; the active one is ticked. Applies immediately. |
| Close (✕) | Dismisses the panel. Recording carries on while it is closed. |
+In a debug build whose bundle came from Metro, a strip under the header says **Metro server
+detected**. Its **Open DevTools** button opens [React Native
+DevTools](/docs/expo-devtools/react-native-devtools) on the Axonpack tab, the same window the dev
+menu opens. A release build, or a bundle built into the app, has no strip.
+
The tab you last had open is remembered for the life of the app process, so reopening the panel returns
you to it. Only the active tab is mounted, so switching tabs and back resets that tab's filters, its
open detail sheet and its scroll position. Captured data is untouched: it lives in the stores, not the
views.
+A detail sheet slides up from the bottom and closes with its ✕, a tap outside it, or a drag of its
+handle or header down. With the keyboard up the sheet grows to make room, up to just short of the top
+of the panel, and its content scrolls in what is left.
+
## Toolbar row
On the three tabs that record — Network, Console, Performance — it opens with the same two controls:
diff --git a/content/docs/react-native-devtools-tab/changelog.mdx b/content/docs/react-native-devtools-tab/changelog.mdx
index 5683c07..dd1f18f 100644
--- a/content/docs/react-native-devtools-tab/changelog.mdx
+++ b/content/docs/react-native-devtools-tab/changelog.mdx
@@ -7,6 +7,16 @@ description: Every published release of @axonpack/react-native-devtools-tab, new
Every published release, newest first. The current version is **0.1.0**.
+## 0.1.1
+
+
+
+- **Open DevTools on your tab**: `registerTab` returns `focus()`, and the next DevTools window lands on that tab
+- **Switch an open window to your tab**: `focus()` also brings the tab forward in a window that is already open
+- **Copy to the computer's clipboard**: give an element `COPY_ATTRIBUTE` with the text, and a click copies it there instead of on the device
+- **Your own right-click menu**: a tab that handles a right-click no longer gets the browser's menu on top of it
+- **A clearer about card**: hover the mark by a tab's name for what it is and links to the docs, changelog, other libraries and GitHub
+
## 0.1.0
diff --git a/content/docs/react-native-devtools-tab/reference.mdx b/content/docs/react-native-devtools-tab/reference.mdx
index 66d7f70..d91c759 100644
--- a/content/docs/react-native-devtools-tab/reference.mdx
+++ b/content/docs/react-native-devtools-tab/reference.mdx
@@ -13,7 +13,7 @@ they do, and a release build has no connection at all, so it stays quiet.
```ts
import { ReactNativeDevtoolsPanel } from "@axonpack/react-native-devtools-tab";
-ReactNativeDevtoolsPanel.registerTab(options: TabOptions): void;
+const tab = ReactNativeDevtoolsPanel.registerTab(options: TabOptions): RegisteredTab;
```
Call it once per tab, as many times as you have tabs.
@@ -33,6 +33,35 @@ An id is derived from `name` rather than written by hand, and numbered if two ta
is also the DevTools panel's own id, so a reload lands on the tab that is already open instead of
leaving a dead one in the strip beside a new one.
+### RegisteredTab
+
+What `registerTab` returns.
+
+| Member | Type | What it does |
+| --------- | ------------ | --------------------------------------------------------------------------------------------- |
+| `focus()` | `() => void` | Shows this tab in a DevTools window that is already open, and in the next one that connects |
+
+Call `focus()` just before opening DevTools from the app, for example with `DevSettings`'s
+`openDebugger`, and the window lands on the tab instead of on Console. On iOS nothing else can
+choose the panel: `openDebugger` takes no argument, and DevTools picks its starting panel before
+any tab of yours has been added.
+
+## COPY_ATTRIBUTE
+
+```ts
+import { COPY_ATTRIBUTE } from "@axonpack/react-native-devtools-tab";
+
+;
+```
+
+An element carrying it has its value copied to the clipboard of the computer DevTools runs on when
+it is clicked, and a short note in the tab says whether that worked. Any `onClick` on the element
+still runs, after the copy.
+
+A handler runs in the app, so a copy written the ordinary way, with the app's own clipboard module,
+lands on the device's clipboard, which a phone does not share with the computer. This is the way to
+put text on the computer's.
+
## withReactNativeDevtoolsTab
The Metro side. One line in `metro.config.js`, and the tab is served.
diff --git a/content/docs/react-pretty-print/changelog.mdx b/content/docs/react-pretty-print/changelog.mdx
index 153f237..558e11f 100644
--- a/content/docs/react-pretty-print/changelog.mdx
+++ b/content/docs/react-pretty-print/changelog.mdx
@@ -7,6 +7,12 @@ description: Every published release of @axonpack/react-pretty-print, newest fir
Every published release, newest first. The current version is **0.1.0**.
+## 0.1.1
+
+
+
+- **The text behind a copy action**: a JSON tree's copy menu items now carry what they copy, for a host that does the copying itself
+
## 0.1.0
diff --git a/content/docs/react-pretty-print/context-menu.mdx b/content/docs/react-pretty-print/context-menu.mdx
index 01785a5..d34de5d 100644
--- a/content/docs/react-pretty-print/context-menu.mdx
+++ b/content/docs/react-pretty-print/context-menu.mdx
@@ -25,8 +25,12 @@ const [menu, setMenu] = useState<{ items: MenuItem[]; x: number; y: number } | n
/>;
```
-`MenuItem` is `{ label: string; onSelect: () => void }`. Render the labels and call `onSelect` on
-press.
+`MenuItem` is `{ label: string; onSelect: () => void; copyText?: string }`. Render the labels and
+call `onSelect` on press.
+
+A copy item also carries `copyText`, the text it copies. It is for a host that has to do the copying
+itself, somewhere `onSelect` does not run: a browser drawing the menu for a tree that lives on a
+device, for example, where the browser's clipboard is the one that matters.
## Which items appear