cli/skills/proxyman/SKILL.md
Reverse-engineer HTTP APIs using Proxyman for macOS. Intercept, record, and export network traffic from CLI tools and apps (Node.js, Python, Ruby, Go, curl). Export as HAR (JSON) and analyze with jq. Use this skill when the user wants to capture, inspect, or reverse-engineer HTTP traffic from macOS applications.
npx skillsauth add remorses/kimaki proxymanInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Proxyman is a macOS proxy that intercepts HTTP/HTTPS traffic. Use it to reverse-engineer APIs: capture what an app sends, inspect headers and bodies, and build SDKs or integrations from the captured data.
Always run proxyman-cli --help and proxyman-cli <subcommand> --help
before using. The help output is the source of truth for all commands and
options. The CLI binary lives inside the app bundle:
/Applications/Proxyman.app/Contents/MacOS/proxyman-cli
Proxyman GUI must be running for the CLI to work. The CLI talks to the running app — it does not work standalone or headless.
open -a Proxyman
This is critical. Even though Proxyman auto-configures macOS system proxy settings, CLI tools and runtimes ignore them. You must set env vars so traffic routes through Proxyman (default port 9090):
HTTPS_PROXY=http://127.0.0.1:9090 \
HTTP_PROXY=http://127.0.0.1:9090 \
NODE_TLS_REJECT_UNAUTHORIZED=0 \
<your-command-here>
HTTPS_PROXY / HTTP_PROXY: route traffic through ProxymanNODE_TLS_REJECT_UNAUTHORIZED=0: accept Proxyman's SSL cert for Node.js appsREQUESTS_CA_BUNDLE or SSL_CERT_FILE may be needed instead--proxy http://127.0.0.1:9090 -k or set the env varsProxyman also has an "Automatic Setup" feature (Setup menu > Automatic Setup) that opens a pre-configured terminal with all env vars set. But for scripting and agent use, set the env vars explicitly as shown above.
proxyman-cli clear-session Clear current captured traffic
proxyman-cli export-log [options] Export captured traffic to file
proxyman-cli export [options] Export debug tool rules (Map Local, etc)
proxyman-cli import --input <file> Import debug tool rules
proxyman-cli proxy on|off Toggle macOS system HTTP proxy
proxyman-cli breakpoint enable|disable Toggle Breakpoint tool
proxyman-cli maplocal enable|disable Toggle Map Local tool
proxyman-cli scripting enable|disable Toggle Scripting tool
proxyman-cli install-root-cert <file> Install custom root cert (requires sudo)
-m, --mode <mode> all | domains (default: all)
-o, --output <path> Output file path (required)
-d, --domains <domain> Filter by domain (repeatable, only with -m domains)
-f, --format <format> proxymansession | har | raw (default: proxymansession)
Always use -f har for agent workflows. HAR is JSON and works with jq.
The CLI can report "Exported Completed!" before the file is actually written.
Add sleep 3 after export-log before reading the file:
proxyman-cli export-log -m all -o capture.har -f har
sleep 3
jq '.log.entries | length' capture.har
This is the primary use case. Example: figuring out how Claude Code talks to the Anthropic API.
# 1. Make sure Proxyman is running
open -a Proxyman
# 2. Clear previous traffic
proxyman-cli clear-session
# 3. Run the target app through the proxy
HTTPS_PROXY=http://127.0.0.1:9090 \
HTTP_PROXY=http://127.0.0.1:9090 \
NODE_TLS_REJECT_UNAUTHORIZED=0 \
claude -p "say hi" --max-turns 1
# 4. Export captured traffic as HAR
proxyman-cli export-log -m all -o capture.har -f har
sleep 3
# 5. Filter for the domain you care about
jq '[.log.entries[] | select(.request.url | test("anthropic"))]' capture.har
jq '[.log.entries[].request.url] | map(split("/")[2])
| group_by(.) | map({domain: .[0], count: length})
| sort_by(-.count)' capture.har
jq '.log.entries[] | select(.request.url | test("api.example.com"))' capture.har
jq '[.log.entries[] | select(.request.url | test("api.example.com")) | {
method: .request.method,
url: .request.url,
status: .response.status
}]' capture.har
jq '.log.entries[] | select(.request.url | test("v1/messages")) | {
url: .request.url,
method: .request.method,
status: .response.status,
request_headers: [.request.headers[] | {(.name): .value}] | add,
request_body: (.request.postData.text | fromjson? // .request.postData.text),
response_body: (.response.content.text | fromjson? // .response.content.text)
}' capture.har
Useful for large payloads — see the shape without the bulk:
jq '.log.entries[] | select(.request.url | test("v1/messages"))
| .request.postData.text | fromjson
| {model, max_tokens, stream,
system_count: (.system | length),
messages_count: (.messages | length),
tools_count: (.tools | length),
messages: [.messages[] | {role, content_type: (.content | type)}]
}' capture.har
jq '.log.entries[] | select(.request.url | test("api.example.com"))
| {url: .request.url, auth: (.request.headers[] | select(.name == "authorization") | .value)}' capture.har
jq '[.log.entries[] | select(.response.status >= 400) | {
url: .request.url,
status: .response.status,
error: .response.content.text
}]' capture.har
If you only care about one domain, filter at export time to get a smaller file:
proxyman-cli export-log -m domains --domains 'api.anthropic.com' -o anthropic.har -f har
Multiple domains:
proxyman-cli export-log -m domains \
--domains 'api.anthropic.com' \
--domains 'mcp-proxy.anthropic.com' \
-o anthropic.har -f har
Proxyman needs to decrypt HTTPS to see request/response bodies. For Node.js
apps, NODE_TLS_REJECT_UNAUTHORIZED=0 handles this. For system apps and
browsers, install and trust the Proxyman root certificate:
proxyman-cli install-root-cert <path-to-cert>Without SSL proxying enabled for a domain, you'll see the connection but not the decrypted body content.
development
Opinionated TypeScript npm package template for ESM packages. Enforces src→dist builds with tsc, strict TypeScript defaults, explicit exports, and publish-safe package metadata. Use this when creating or updating any npm package in this repo.
documentation
Best practices for creating a SKILL.md file. Covers file structure, frontmatter, writing style, and where to place skills in a repository. Use when the user wants to create a new skill, update an existing skill, write a SKILL.md, or asks how skills work.
documentation
Best practices for creating a SKILL.md file. Covers file structure, frontmatter, writing style, and where to place skills in a repository. Use when the user wants to create a new skill, update an existing skill, write a SKILL.md, or asks how skills work.
tools
Centralized state management pattern using Zustand vanilla stores. One immutable state atom, functional transitions via setState(), and a single subscribe() for all reactive side effects. Based on Rich Hickey's "Simple Made Easy" principles: prefer values over mutable state, derive instead of cache, centralize transitions, and push side effects to the edges. Resource co-location in the same store is also valid when lifecycle management is safer that way. Also covers state encapsulation: keeping state local to its owner (closures, plugins, factory functions) so it doesn't leak across the app, reducing the blast radius of mutations. Also covers event sourcing: keeping a bounded event buffer and deriving state with pure functions instead of mutable flags, making event handlers easy to test and reason about. Use this skill when building any stateful TypeScript application (servers, extensions, CLIs, relays) to keep state simple, testable, and easy to reason about. ALWAYS read this skill when a project uses zustand/vanilla for state management outside of React.