Metadata-Version: 2.4
Name: plunger-cli
Version: 0.5.2
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Rust
Classifier: Topic :: Software Development :: Testing
Classifier: Topic :: Internet :: WWW/HTTP
License-File: LICENSE
Summary: Plunger: send HTTP requests from a desktop app, the command line or an MCP server for AI agents, with secrets kept out of agent output.
Keywords: http,api,rest,mcp,curl,agent
Home-Page: https://github.com/metamug/plunger
License: MIT
Requires-Python: >=3.8
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Changelog, https://github.com/metamug/plunger/blob/main/CHANGELOG.md
Project-URL: Documentation, https://github.com/metamug/plunger/blob/main/docs/agents.md
Project-URL: Homepage, https://github.com/metamug/plunger
Project-URL: Issues, https://github.com/metamug/plunger/issues
Project-URL: Source, https://github.com/metamug/plunger

<h1 align="center">  <img src="docs/images/plunger.svg" alt="A plunger" width="24"> Plunger</h1>

<p align="center"><strong>Unclog your API.</strong></p>

<p align="center">
  <strong>Your AI agent calls the API. Plunger shows you what it actually sent and what came back.</strong>
</p>

<p align="center">
  A tiny native API inspection tool for developers who just want to see what their pipeline is actually doing.<br>
  Make the request. See the JSON. Move on.
</p>

<p align="center">
  <a href="https://github.com/metamug/plunger/actions/workflows/ci.yml"><img src="https://github.com/metamug/plunger/actions/workflows/ci.yml/badge.svg?branch=main" alt="CI status"></a>
  <a href="https://github.com/metamug/plunger/releases/latest"><img src="https://img.shields.io/github/v/release/metamug/plunger?color=4a6fdc&label=release" alt="Latest release"></a>
  <a href="https://github.com/metamug/plunger/releases"><img src="https://img.shields.io/github/downloads/metamug/plunger/total?color=2ea44f&label=downloads" alt="Downloads"></a>
  <a href="LICENSE"><img src="https://img.shields.io/github/license/metamug/plunger?color=blue" alt="MIT license"></a>
  <img src="https://img.shields.io/badge/platform-Windows%2010%20%7C%2011-0078d4" alt="Platform: Windows 10 and 11">
  <a href="docs/agents.md"><img src="https://img.shields.io/badge/MCP-server-8a5cf6" alt="MCP server"></a>
  <img src="https://img.shields.io/badge/built%20with-Rust-dea584?logo=rust&logoColor=white" alt="Built with Rust">
  <a href="https://github.com/metamug/plunger/stargazers"><img src="https://img.shields.io/github/stars/metamug/plunger?style=flat&color=e3b341" alt="GitHub stars"></a>
</p>

<p align="center">
  <a href="https://apps.microsoft.com/detail/9P7WRKLN6WHR"><strong>Get it from the Microsoft Store</strong></a>
  &nbsp;·&nbsp; <a href="https://github.com/metamug/plunger/releases/latest/download/plunger-windows.zip">Windows zip</a> (about 3.6 MB, no installer, not code-signed)
  &nbsp;·&nbsp; <a href="https://github.com/metamug/plunger/releases/latest/download/plunger-linux-x86_64.tar.gz">Linux</a> (command line and MCP server tested; the window is not yet)
  &nbsp;·&nbsp; <a href="LICENSE">MIT license</a>
</p>

<p align="center">
  <img src="docs/images/demo.gif" alt="Pasting a curl command into Plunger, importing it and sending it; the JSON response appears as a collapsible tree" width="960">
</p>

<p align="center">
  <img src="docs/images/plunger-ui-demo.gif" alt="Sending a request from Plunger's window, then an AI agent calling the API over MCP: each call appears live in the history tagged MCP, the token it saved stays hidden, and Authorization: Bearer {{token}} keeps its placeholder." width="960"><br>
  <sub>The real app: every request an agent sends appears in your window, tagged <code>MCP</code>, with secrets kept hidden. <a href="docs/agents.md">Setup and details</a>.</sub>
</p>

## Why?

Sometimes you don't need another platform. You just need to see what the API returned.

AI can write the code. AI can build the pipeline. We still look at the diff before we push. We still look at the logs when something feels wrong. And we still look at the JSON when an API doesn't do what we expected.

Seeing is believing. Plunger is for the moment between "I think it works" and "I can see it works."

<p align="center">
  <img src="docs/images/plunger.svg" alt="A plunger" width="110"><br>
  <em>We wanted a plunger. So we made one.</em>
</p>

## What is Plunger?

A small desktop app that sends an HTTP request and shows you what came back.

- **Request:** GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS. Params, headers and a Bearer token field.
- **Body:** JSON, form-urlencoded, raw text, or multipart form-data with real file uploads.
- **Response:** status, time and size, the headers, and the body as a collapsible JSON tree. Copy it or save it to a file.
- **Variables:** `{{name}}` anywhere in the request, plus `{{$uuid}}`, `{{$timestamp}}`, `{{$randomInt}}` and `{{$env:NAME}}` for reading an OS environment variable at send time. A request with an undefined variable is refused, never sent with the placeholder in it.
- **Import and export:** paste a curl command (bash or Windows cmd, including `-F` uploads) or a PowerShell `Invoke-WebRequest` / `Invoke-RestMethod` command, such as DevTools' Copy as cURL or Copy as PowerShell; or open a HAR file. Copy any request back out as curl (bash), curl (Windows cmd) or PowerShell with **Ctrl+Shift+C** or **File > Export request**, shown with syntax highlighting.
- **Keep what matters:** local history, named saved requests (Ctrl+S) and tabs (Ctrl+T).
- **Local HTTPS:** skip certificate checks for a self-signed dev server, with a warning that stays visible while it's on.
- **Behind a proxy:** Plunger uses your system proxy settings and the `HTTP_PROXY`, `HTTPS_PROXY` and `NO_PROXY` environment variables.
- **Find it again:** the sidebar filter searches your whole history and saved requests by URL, method, name or status; right-click a value in a JSON response to copy its path or value.

It's a native program, not a web page, so it reaches whatever your machine can reach: `localhost`, a dev box on your network, an API that sends no CORS headers.

## For AI agents

**See the JSON, even when an AI sent the request.**

Plunger is built to be driven safely by AI agents, not just clicked by people. The same `plunger.exe` is also a command-line API client and an MCP server, so an agent like Claude Code sends requests through Plunger's engine instead of running curl. No account, no cloud, no telemetry: now safe for your agents too.

One exe. Human GUI, agent CLI, agent MCP. The same safety guarantees in every mode.

```json
{
  "mcpServers": {
    "plunger": { "command": "C:\\Tools\\plunger\\plunger.exe", "args": ["mcp"] }
  }
}
```

<p align="center">
  <img src="docs/images/mcp-claude-code-demo.gif" alt="Claude Code, asked to fetch a joke through Plunger's send_request tool, calling the tool and printing the result; each call shows up live in Plunger's history on the right, tagged MCP." width="900">
</p>

<p align="center"><sub>Real Claude Code, using Plunger over MCP, unedited. See <a href="docs/agents.md">docs/agents.md</a> for the setup and a look at the raw protocol traffic.</sub></p>

Run `plunger install` (or **File > Set up AI agents...** in the window) to register the MCP server in Claude Code, Cursor, Kiro, Codex, Windsurf, VS Code or Gemini CLI and write the always-on steering that tells the agent to use Plunger instead of curl. See [docs/agents.md](docs/agents.md).

### Why not just let the agent run curl?

1. **Undefined-variable safety.** Plunger refuses to send a request with an undefined `{{variable}}`. curl will happily send the placeholder text.
2. **Credential isolation.** The agent writes `{{token}}` and never sees the value. Secrets you've chosen to remember are kept in Windows Credential Manager and filled in by Plunger; if a server echoes one back, it comes back as `[redacted:token]`.
3. **Shared human and agent history.** You testing in the window and an agent testing from the command line read and write the same saved requests and history.
4. **Structured, typed output.** Status, timing, size, headers and the parsed JSON body come back as separate fields, not text the agent has to pick apart.
5. **A local audit trail.** Every agent request lands in the history you see in the window, tagged `MCP` or `CLI`, as it happens. curl leaves no record unless you build the logging yourself.

Tools: `send_request`, `import_curl`, `list_saved_requests`, `get_history`, `list_variables`, `export_curl`. From a terminal: `plunger send "Saved request name"`, `plunger send --url ...`, `plunger history`. Setup, every tool and option, exit codes and the fine print are in [docs/agents.md](docs/agents.md).

## Small by design

Built in Rust with [egui](https://github.com/emilk/egui) because we wanted a small, fast, native application. No webview, no bundled browser: one exe of about 7 MB, which is also a command-line client and an MCP server for AI agents.

No account to create. No cloud to sync to. The only network traffic is the requests that get sent, by you or by an agent you've connected: no analytics, no telemetry, no update checks. History and saved requests live in one local folder, `%APPDATA%\Plunger\data`. Bearer tokens and secret variables are never written to a file unless you tick "remember", which keeps them in Windows Credential Manager. Credential-looking headers are blanked before history is saved. Details are in the [privacy policy](docs/privacy.md).

## Open source

Plunger is MIT licensed. Read it, build it, change it.

A few promises, so you know what you're picking up:

- It will never require an account.
- It will never add telemetry.
- Existing features will never move behind a paywall.

## Screenshots

<table>
  <tr>
    <td width="50%"><img src="docs/images/hero.png" alt="Plunger with four request tabs, saved requests and history in the sidebar, query params in sync with the URL, and a JSON response"><br><sub>Request, response, JSON. Saved requests and history on the left.</sub></td>
    <td width="50%"><img src="docs/images/form-data.png" alt="A multipart form-data request with a text field and a file field, and the server's echo of the upload"><br><sub>Multipart uploads with real files.</sub></td>
  </tr>
  <tr>
    <td><img src="docs/images/variables.png" alt="The Variables tab with a base URL and a masked secret token, used as {{base}} in the URL"><br><sub>Variables, with secrets masked and kept off disk.</sub></td>
    <td><img src="docs/images/undefined-variables.png" alt="A request refused because {{base}} and {{token}} are not defined"><br><sub>Undefined variables stop the request instead of leaking a placeholder.</sub></td>
  </tr>
  <tr>
    <td><img src="docs/images/import-curl.png" alt="The Import a curl command dialog with a pasted curl command"><br><sub>Paste a curl command; it becomes a request.</sub></td>
    <td><img src="docs/images/local-https.png" alt="The Options tab with TLS certificate verification skipped and a visible warning"><br><sub>Local HTTPS with self-signed certificates.</sub></td>
  </tr>
  <tr>
    <td colspan="2" align="center"><img src="docs/images/light-theme.png" alt="Plunger in the light theme" width="50%"><br><sub>Light theme too.</sub></td>
  </tr>
</table>

## Install

**Microsoft Store** (signed by Microsoft, no warning, updates itself; it can trail the newest release by a few days): [get it here](https://apps.microsoft.com/detail/9P7WRKLN6WHR), or

```powershell
winget install 9P7WRKLN6WHR --source msstore
```

**Scoop:**

```powershell
scoop bucket add metamug https://github.com/metamug/scoop-bucket
scoop install plunger
```

**pip / uv (Windows, Linux, macOS), from 0.5.1:**

```bash
pip install plunger-cli       # puts a `plunger` command on your PATH
pipx install plunger-cli      # same, in its own environment (use this if pip says "externally-managed-environment")
uvx plunger-cli mcp           # or run the MCP server without installing anything
```

**Zip:**

1. [Download `plunger-windows.zip`](https://github.com/metamug/plunger/releases/latest/download/plunger-windows.zip) and unzip it anywhere.
2. Run `plunger.exe`.

Windows 10 or 11, 64-bit. The zip isn't code-signed yet, so Windows may say "Windows protected your PC": click **More info**, then **Run anyway**. Or [build it yourself](#build-from-source).

To update the zip, replace the exe. To remove it, delete the exe and `%APPDATA%\Plunger`.

## Usage

1. Paste a URL, or import a curl command.
2. Press **Ctrl+Enter**. While a request is in flight, press **Escape** to cancel waiting for it.
3. Read the response.

Press **Ctrl+L** to focus the URL field and select its contents.

Press **Ctrl+F** to search the response body: **Enter** and **Shift+Enter** (or Next / Prev) step through the matches, **Esc** closes the box.

With multiple request tabs, **Ctrl+Tab** moves to the next tab and
**Ctrl+Shift+Tab** moves to the previous one. Cycling wraps at either end.

## Build from source

```bash
rustup toolchain install stable-x86_64-pc-windows-gnu
rustup default stable-x86_64-pc-windows-gnu
# plus mingw-w64 (gcc, windres, dlltool) on PATH, e.g. from WinLibs or MSYS2

cargo build --release     # target/release/plunger.exe
cargo test
```

Set `PLUNGER_DATA_DIR` to run against a throwaway data folder instead of your real history.

## Contributing

Issues and pull requests are welcome. Before adding a feature, ask: does this help someone quickly see what an API is doing? Would someone open Plunger specifically for it? If yes, it probably belongs. Accounts, sync, collaboration and platform features don't.

- [CONTRIBUTING.md](CONTRIBUTING.md): what fits, how to build, how to send a change.
- [design.md](design.md): how it's built and why.
- [SECURITY.md](SECURITY.md): how to report a vulnerability privately.
- [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) and the [CHANGELOG](CHANGELOG.md).

Run `cargo test` and `cargo clippy --all-targets` before sending a PR. Maintainers: releases are GitHub releases with `plunger-windows.zip` attached (push a `v*` tag).

---

<p align="center">We didn't want another ecosystem. We wanted a plunger. <img src="docs/images/plunger.svg" alt="A plunger" width="14"><br><strong>Unclog your API.</strong></p>

