Tap.Workspace 0.5.0-beta.6

This is a prerelease version of Tap.Workspace.
There is a newer version of this package available.
See the version list below for details.
dotnet add package Tap.Workspace --version 0.5.0-beta.6
                    
NuGet\Install-Package Tap.Workspace -Version 0.5.0-beta.6
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Tap.Workspace" Version="0.5.0-beta.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Tap.Workspace" Version="0.5.0-beta.6" />
                    
Directory.Packages.props
<PackageReference Include="Tap.Workspace" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Tap.Workspace --version 0.5.0-beta.6
                    
#r "nuget: Tap.Workspace, 0.5.0-beta.6"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Tap.Workspace@0.5.0-beta.6
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Tap.Workspace&version=0.5.0-beta.6&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Tap.Workspace&version=0.5.0-beta.6&prerelease
                    
Install as a Cake Tool

<div align="center"> <p> <img src="assets/tap-logo.svg" alt="Tap" width="150"> </p>

<picture> <source srcset="assets/tap-hero-dark.png" media="(prefers-color-scheme: dark)"> <img src="assets/tap-hero.png" alt="Tap tunnel and HTTP inspector illustration" width="620"> </picture>

<p><strong>Two local-first tools for HTTP: one to watch traffic arrive, one to send it.</strong></p>

<p> <a href="https://philbir.github.io/tap/"><strong>Landing page and docs</strong></a> </p>

<p> <a href="https://philbir.github.io/tap/"><img alt="Docs" src="https://img.shields.io/badge/docs-GitHub%20Pages-14945f"></a> <img alt=".NET" src="https://img.shields.io/badge/.NET-10-512bd4?logo=dotnet"> <img alt="Aspire" src="https://img.shields.io/badge/Aspire-ready-7b2ff7"> <img alt="Cloudflare Tunnel" src="https://img.shields.io/badge/Cloudflare-Tunnel-f38020?logo=cloudflare"> <img alt="Tailscale Funnel" src="https://img.shields.io/badge/Tailscale-Funnel-5e64f4?logo=tailscale"> <img alt="UI" src="https://img.shields.io/badge/UI-React%2019-14945f?logo=react"> </p> </div>


The big picture

Local HTTP development has two halves. Sometimes the internet needs to reach your laptop โ€” a webhook, an OAuth callback, a mobile build, a partner poking at your machine for ten minutes โ€” and you need to see exactly what arrived. Other times you are the client, and you need to compose a request, authenticate properly, send it, and keep it somewhere your team can find it next month.

Tap is two products, one for each half:

๐Ÿ”Œ Tap Tunnel + Inspector Give localhost a real public URL through Cloudflare Tunnel or Tailscale, and capture every request, response, SSE event, and WebSocket frame that flows through it. Runs as the tap CLI or as .NET Aspire resources.
๐Ÿงช Tap Studio An HTTP workbench: compose requests, run real authentication flows, execute, and keep the whole workspace in your git repo as Markdown. Ships as a desktop app, with an AI assistant built in.

They share a philosophy more than they share code:

  • Local-first. Everything runs on your machine. No account, no cloud workspace, no telemetry. Quick tunnels cost nothing; stable hostnames just need a domain you already own.
  • Plain text, in your repo. Studio's workspace is Markdown with YAML frontmatter โ€” no proprietary export, no sync service, ordinary git diffs.
  • Secrets stay out of files. The Inspector never persists credentials; Studio resolves secret references at execute time and keeps tokens in your OS state folder, never in the workspace.
  • Explicit boundaries. Tunnels are private by default where the provider allows it, and public exposure is something you opt into with your eyes open.
inbound    Internet โ”€โ–ถ Cloudflare Tunnel / Tailscale โ”€โ–ถ Tap capture proxy โ”€โ–ถ your service
                                                              โ”‚
                                                              โ–ผ
                                                        Inspector UI
                                                        requests ยท SSE ยท WS ยท replay

outbound   request.req.md + auth profile + environment โ”€โ–ถ Tap Studio โ”€โ–ถ any API
           โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Markdown, in your repo โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     executor

Use either on its own. Used together, Studio composes the call and the Inspector shows you what your service actually received.


๐Ÿ”Œ Tap Tunnel + Inspector

For the moment when localhost needs to behave like a real internet endpoint, but you still want full visibility into every request. Mobile app hooks, webhook deliveries, third-party OAuth redirects, partner integrations, and "can you hit my laptop for a minute?" demos all need the same two things: a tunnel that is quick to bring up, and a request log that tells you what actually happened.

๐Ÿ“– Full reference: docs/inspector.md

Public tunnels are scanned within minutes. As soon as a public hostname's TLS certificate hits a CT log โ€” immediately, when Cloudflare Tunnel or Tailscale Funnel comes up โ€” opportunistic scanners start probing for admin endpoints and known-CVE banners. Always pair public tunnels with Tap's auth options (header / CIDR / country / OIDC) or edge controls like Cloudflare Access and WAF rules. For Tailscale, prefer WithTailscaleServe(...) (tailnet-only) over WithTailscaleFunnel(...) (public) unless you actually need internet exposure.

What it does

Tunnels without ceremony Free TryCloudflare URLs, dashboard connector tokens, API-managed Cloudflare tunnels + DNS, or Tailscale Serve/Funnel when your tailnet is the right boundary.
Captures every hop Method, host, path, headers, status, timing, request and response bodies, and image previews โ€” recorded before forwarding to your upstream.
Live streaming protocols text/event-stream responses and WebSocket connections proxy through the same port and render as live, direction-tagged timelines in dedicated SSE and WS tabs.
Replay and QR Replay any captured request; scan the public URL straight onto a phone from the QR tab.
Aspire-native Model inspectors and tunnels in your AppHost. Allocated ports and generated hostnames resolve at startup and show up in the dashboard.
Auth on the public path Header, CIDR, country, and OIDC checks gate the proxy branch before traffic reaches your upstream. The UI port stays local.

Install

All three routes install the same tap CLI.

dotnet tool install -g Tap                                                   # .NET 10 SDK on PATH
curl -fsSL https://raw.githubusercontent.com/philbir/tap/main/install.sh | sh # Linux/macOS, self-contained
irm https://raw.githubusercontent.com/philbir/tap/main/install.ps1 | iex      # Windows

Make sure ~/.dotnet/tools (Linux/macOS) or %USERPROFILE%\.dotnet\tools (Windows) is on your PATH. Pin a version with TAP_VERSION=0.1.0 (or $env:TAP_VERSION on Windows). Archives are also on the Releases page as tap-<version>-<rid>.tar.gz with a SHA256SUMS alongside.

Cloudflare features need cloudflared on PATH โ€” brew install cloudflared, winget install Cloudflare.cloudflared, or tap install-cloudflared. Tailscale host modes need the tailscale CLI; Docker mode doesn't.

Quick start โ€” CLI

tap run http://localhost:3000

Proxy on http://localhost:4444, Inspector UI on http://localhost:4445.

# throwaway public URL, no account needed
tap run http://localhost:3000 --quick

# your own hostname, via a tunnel you created in the Cloudflare dashboard
tap run http://localhost:3000 --token "$CLOUDFLARE_TUNNEL_TOKEN" --hostname api-local.example.com

# tailnet-only (the safe default)
tap run http://localhost:3000 --tailscale

# public Tailscale Funnel โ€” pair it with auth
tap run http://localhost:3000 --tailscale --tailscale-public --auth-header "X-Tap-Key=$TAP_KEY"

Every flag, every environment variable, and the tap.config file format: docs/inspector.md.

Quick start โ€” Aspire

using Aspire.Hosting;

var builder = DistributedApplication.CreateBuilder(args);

var api = builder.AddProject<Projects.Sample_Api>("api");

var tap = builder.AddTap<Projects.Tap_Server>();
api.WithTap(tap);

builder.Build().Run();

Inspector UI on http://localhost:5198; traffic through http://localhost:5199 is recorded before it reaches api. Add .WithQuickTunnel(), .WithTunnel(...), .WithTailscaleServe(...), or .WithTailscaleFunnel(...) to put a tunnel in front โ€” the Aspire recipes cover each mode.

Packages

Package Purpose
Tap.Hosting Aspire AppHost extensions: AddTap, AddTapContainer, WithTap, WithTunnel, WithQuickTunnel, WithTailscaleServe (tailnet-only, default), WithTailscaleFunnel (public, opt-in), WithExistingTunnel, WithApiManagedTunnel, WithDynamicHostname, WithSystemDaemon / WithEphemeralDaemon / WithFunnelPort.
Tap.Server ASP.NET Core capture server: YARP reverse proxy, capture middleware, WebSocket-terminating proxy, SSE event parser, REST API, /api/stream push channel, and the bundled React Inspector UI.
Tap.Cli Local command host that reuses the same server code.

Both entry points run the same Tap.Server host: the CLI builds TapInspectorOptions from flags, environment variables, and tap.config; Aspire writes the same options as project environment variables.


๐Ÿงช Tap Studio

The other direction: you are the client. Studio is a full HTTP request workbench โ€” compose, authenticate, execute, document โ€” with a workspace that lives in your repository as plain Markdown.

๐Ÿ“– Full reference: docs/studio.md ยท ๐Ÿ“„ On-disk format: docs/workspace-format.md

Tap Studio composing and executing a request

What it does

Full request composition Method, URL, query params, headers, and bodies as None / Form / Multipart / Raw / Binary / GraphQL โ€” with JSON/XML formatting, multi-file uploads, and a GraphQL editor backed by the live schema.
Real responses Status, duration, size, syntax-highlighted body with image and binary previews, plus Headers, the exact Request that went on the wire, the auth/variable Flow, and which Secrets were resolved.
Streaming SSE responses stream in live; requests marked protocol: websocket open a real socket and append frames as they arrive.
Many authentication flows OAuth 2.0 / OIDC (authorization code + PKCE, client credentials, ROPC, device code), Microsoft Entra, Azure CLI (direct + on-behalf-of), GitHub (PAT / gh CLI / GitHub App / OAuth App), AWS SigV4, signed JWT, bearer, basic, API key, and custom headers.
AI assistance Hand the request to GitHub Copilot CLI or Claude Code โ€” running locally, with your existing CLI login โ€” and get a proposed edit you review before saving.
Git-native workspace Requests, collections, auth profiles, and environments are Markdown files. Built-in branch, diff, stage, and commit.
Variables and secrets A six-level cascade (workspace โ†’ collection โ†’ stage โ†’ environment โ†’ request โ†’ per-run) over pluggable providers: process env with allowlists, an encrypted workspace file, Azure Key Vault, and machine-local system variables.

Authentication, properly

Creating an auth profile starts from a template catalog; the wizard then asks only for the fields that flow actually needs, and shows you what it will write before it writes it.

The auth-flow catalog

Tokens never touch the workspace โ€” they live in ~/.tap/auth-tokens.json, keyed by workspace and profile, and refresh automatically. The redirect URI is owned by the runtime and shown read-only so you know exactly what to register with your identity provider; the desktop app uses the stable tap-studio://callback deep link instead of an ephemeral loopback port. You can also pick which browser and profile handles an interactive sign-in, so a work tenant doesn't land in your personal session.

OAuth 2.0 authorization code + PKCE

Details and the full grant matrix: docs/studio.md.

AI assistance

Studio spawns an AI coding CLI you already have installed โ€” no bundled SDK, no extra credentials. The assistant is handed the request you're editing plus the collection's base URL, default auth, and shared headers, the available auth profiles, the environment names, and the variable catalog, so it edits your workspace instead of inventing endpoints and tokens.

The AI assistant proposing a request edit

It never writes files. It proposes a structured request that the UI applies to the editor as an unsaved change, together with Markdown documentation for the request โ€” you review the diff and decide whether to keep it. Secrets are always referenced as {{variables}}, never inlined.

The workspace is your repo

A request edit as an ordinary git diff

.tap/
โ”œโ”€โ”€ tap.md                                โ† workspace: name, providers, default env
โ”œโ”€โ”€ auth/corp-entra.auth.md               โ† auth profile shared by every collection
โ”œโ”€โ”€ environments/local.env.md             โ† named variable set
โ””โ”€โ”€ collections/billing/
    โ”œโ”€โ”€ _collection.md                    โ† baseUrl, stages, default auth/headers
    โ”œโ”€โ”€ billing-oauth.auth.md             โ† auth profile scoped to this collection
    โ””โ”€โ”€ create-customer.req.md            โ† one request, as a fenced http block

Because a request is a couple of lines of Markdown, review, blame, cherry-pick, and revert all work the way they do for code. Studio is the only thing that writes the YAML โ€” editors PUT a typed spec and the server re-emits the file โ€” so what lands in your diff is predictable.

Install and run

Studio ships as a native desktop app (Tauri 2 wrapping the self-contained Tap.Studio sidecar). Grab the .dmg, .msi/.exe, or .deb from Releases; it self-updates from there.

From source, the whole dev loop is one command:

cd samples
aspire run

That brings up demo-api (an upstream exercising every verb, content type, SSE, WebSockets, GraphQL, and a real OAuth2/OIDC server), studio-api, and the Vite UI on port 5297. Point it at your own repo with STUDIO_WORKSPACE=/path/to/your/repo aspire run, and add RunDesktop=true to open the native window too.


Development

dotnet restore Tap.slnx
dotnet build   Tap.slnx
dotnet run --project samples/Sample.AppHost   # tunnels + inspector scenarios
cd samples && aspire run                      # Tap Studio

The SDK is pinned in global.json to .NET 10 and TreatWarningsAsErrors is on globally, so warnings break the build. There is no test project yet.

Two independent UIs, both yarn 4 (Berry):

cd src/ui-inspector && yarn && yarn dev   # Inspector โ€” port 5197
cd src/ui-studio    && yarn && yarn dev   # Studio    โ€” port 5297
cd docs-site        && yarn && yarn build # landing page + docs

src/ui-inspector is built into src/backend/Tap.Server/wwwroot/ on every server build, and src/ui-studio into Tap.Studio's wwwroot. Skip those with -p:SkipTapUiBuild=true and -p:SkipStudioUiBuild=true when iterating on C# only. The generated wwwroot directories are gitignored โ€” never hand-edit them.

Layout

assets/                       Logo, hero art, and documentation screenshots
docs/                         Reference documentation
docs-site/                    Vite landing page + docs, published to GitHub Pages
src/backend/Tap.Core/         Shared auth and Cloudflare/cloudflared primitives
src/backend/Tap.Hosting/      Aspire integration and lifecycle hooks
src/backend/Tap.Server/       Capture server, YARP proxy, SSE/WS API, bundled Inspector UI
src/backend/Tap.Cli/          CLI host for the inspector server
src/backend/Tap.Studio/       Studio backend (REST + SSE, auth runner, AI, git)
src/backend/Tap.Workspace/    Workspace parsing, variable providers, and rendering
src/ui-inspector/             Vite + React Inspector UI
src/ui-studio/                Vite + React Studio UI
src/desktop/                  Tauri desktop shell for Studio
samples/                      Sample AppHosts, the demo API, and a sample workspace

Documentation

Document Contents
docs/inspector.md Tunnel modes, full CLI reference, Cloudflare and Tailscale setup, proxy auth, Aspire recipes, configuration.
docs/studio.md Workspace model, request composer, authentication flows, variables and secrets, AI assistant, git, desktop app.
docs/workspace-format.md The authoritative on-disk format spec for Studio workspaces.
docs/ARCHITECTURE.md Deep technical background on the capture path and tunnel providers.
src/desktop/README.md Desktop shell internals, build, signing, and release pipeline.
docs/release-notes/ Per-release notes.

License

TBD.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Tap.Workspace:

Package Downloads
Tap.Execution

Executes Tap workspace requests, flows, and test sets: HTTP transport, assertion evaluation, value extraction, and the sequential run engine. The engine behind both Tap Studio and the `tap-studio` CLI, so a verdict from CI and a verdict from the UI are the same computation.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.7.0-p.2 51 8/17/2026
0.7.0-p.1 62 8/16/2026
0.6.1 58 8/15/2026
0.6.0 61 8/15/2026
0.6.0-beta.1 51 8/14/2026
0.5.0-beta.6 52 8/9/2026
0.5.0-beta.5 53 8/8/2026
0.5.0-beta.4 55 8/8/2026
0.5.0-beta.3 52 8/8/2026
0.5.0-beta.2 52 8/7/2026
0.5.0-beta.1 66 7/11/2026