sip-ladder
Generate SIP call-flow (ladder) diagrams from pcap files.
Reads a pcap, parses SIP messages, groups them into calls by Call-ID, and
renders the resulting message flow as either a Mermaid sequence diagram
(text, embeddable in Markdown) or a standalone SVG.
The diagram algorithm is ported from sngrep's
ncurses "Call Flow" view (src/curses/ui_call_flow.c), with one improvement:
sngrep treats every distinct IP:port as a separate actor column, so a proxy
listening on :5060 and originating on :5061 shows up twice. sip-ladder
uses Via and Contact headers to merge those into a single logical actor.
Install
uv tool install sip-ladder
# or, ad-hoc:
uvx sip-ladder trace.pcap -o flow.mmd
Example output
Given a pcap containing a basic INVITE flow, sip-ladder produces:
---
title: demo-1-simple@atlanta.example INVITE → 200
---
sequenceDiagram
autonumber
participant A as alice@192.0.2.10
participant B as 192.0.2.20:5060
A->>B: INVITE
B-->>A: 100 Trying
B-->>A: 180 Ringing
B-->>A: 200 OK (INVITE)
A->>B: ACK
A->>B: BYE
The pcap that produced this — plus a redirect call and a REFER-based transfer — lives in
examples/build_demo_pcap.py. Run it locally to regenerate:
uv run python examples/build_demo_pcap.py
# Produces examples/demo-call-flow.{pcap,mmd,svg}
GitHub, GitLab, Obsidian, and most modern Markdown viewers render the Mermaid block above as a sequence diagram. On platforms that don't (PyPI's README renderer, plain-text consumers), the fenced code block remains readable as-is.
CLI
sip-ladder trace.pcap # render all calls as Mermaid to stdout
sip-ladder trace.pcap -o flow.mmd # write Mermaid to file
sip-ladder trace.pcap -o flow.svg # extension drives format
sip-ladder trace.pcap --list # list calls without rendering
sip-ladder trace.pcap --call-id abc... # render just one call
Library
from sip_ladder import read_pcap, render_mermaid, render_svg
for call in read_pcap("trace.pcap"):
print(f"{call.call_id} {call.from_uri} -> {call.to_uri} ({call.final_response})")
open(f"{call.call_id}.mmd", "w").write(render_mermaid(call))
render_svg(call, f"{call.call_id}.svg")
Scope
In-scope for the initial release:
- Offline pcap analysis (UDP and best-effort TCP)
- SIP message parsing (RFC 3261 — common cases)
- Mermaid + SVG renderers
- Via-aware actor reconciliation
- Retransmit detection via CSeq match
Out-of-scope (deferred):
- Live capture (libpcap, HEP/EEP listener, sngrep subprocess streaming)
- RTP / MOS analysis
- TLS decryption
- SIP-over-WebSocket
- Interactive HTML
The architecture leaves clean seams to add these later without restructuring.
Source and contributions
- Repository: https://git.supported.systems/warehack.ing/sip-ladder
- Issues: https://git.supported.systems/warehack.ing/sip-ladder/issues
- Changelog: CHANGELOG.md
- API documentation: docs/API.md
The repo also includes an docs/agent-threads/ directory with the full
audit trail of cross-project design conversations — these are
intentionally excluded from the PyPI sdist (per a deliberate
"link, don't ship" policy) but are visible in git for anyone curious
about why specific design choices were made.
License
MIT — see LICENSE.
Metadata
Release files for sip-ladder 2026.5.25.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| sip_ladder-2026.5.25.6.tar.gz | 64.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sip_ladder-2026.5.25.6-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 97.4 kB
Release files / sip_ladder-2026.5.25.6.tar.gz
| Download URL | sip_ladder-2026.5.25.6.tar.gz |
|---|---|
| Size | 64.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0bc1fc2ca7e035052744f02669d920950c06e661784f88cdfc105db8f57e664f
|
|
BLAKE2b-256 checksum How to use checksums |
dcbcdb5bbd590a232c9c6771cb3c3ed2d80e21927271a81ed35d2947fb2c0dc3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"EndeavourOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / sip_ladder-2026.5.25.6-py3-none-any.whl
| Download URL | sip_ladder-2026.5.25.6-py3-none-any.whl |
|---|---|
| Size | 32.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
68a86ea1fe6a9f067cf238b6dc419edcc77573b7e120342aaabf1c284fec30e9
|
|
BLAKE2b-256 checksum How to use checksums |
253b6645bdb8d3fbd406cb7bebb64f3b08a81d063c4f065663c9a1d9cfe4c318
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"EndeavourOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for sip-ladder 2026.5.25.6
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.