# dsct
[](https://github.com/higebu/dsct/actions/workflows/ci.yml)
[](https://crates.io/crates/dsct)
[](https://docs.rs/dsct)
[](https://blog.rust-lang.org/2025/06/26/Rust-1.88.0/)
`dsct` is a packet dissector CLI for LLMs and large captures.
It is built around two ideas:
- machine-readable output by default
- predictable memory use on big `pcap` / `pcapng` files
`dsct read` streams packet records as JSONL, `dsct stats` scans captures in a single pass, and the optional TUI opens large files with memory mapping and on-demand dissection instead of decoding the whole capture up front.
## Why dsct
### LLM-friendly by default
- `dsct read` emits JSONL packet records
- `dsct stats`, `dsct list`, `dsct fields`, `dsct version`, and `dsct schema` emit JSON
- errors, warnings, and progress updates are structured JSON on stderr
- capabilities and schemas can be discovered from the CLI itself
### Works well on large captures
- `read` and `stats` process captures one packet at a time
- stdin is supported, so `tcpdump -w - | dsct ...` works naturally
- no human-oriented table parsing is required before automation can start
### MCP server built in
`dsct mcp` starts a [Model Context Protocol](https://modelcontextprotocol.io/) server over stdio. AI agents can call tools like `dsct_read_packets` and `dsct_get_stats` directly, without shelling out to the CLI.
### Low-memory TUI for large files
The optional TUI is designed for large captures too:
- capture files are opened with memory-mapped I/O
- indexing starts from packet headers instead of fully decoding every packet
- packet list rows are dissected on demand for visible rows
- the selected packet is decoded in detail only when needed
- the hex view reads directly from the mapped file
## Claude Code / Copilot CLI plugin
Install as a plugin via the marketplace to get the MCP server and the
`analyze-packets` skill automatically:
**Claude Code**
```bash
claude plugin marketplace add higebu/dsct
claude plugin install dsct@dsct
```
**GitHub Copilot CLI**
```bash
copilot plugin marketplace add higebu/dsct
copilot plugin install dsct@dsct
```
## Installation
CLI only:
```bash
cargo install --path .
```
With the optional TUI:
```bash
cargo install --path . --features tui
```
## Quick start
Get a capture overview:
```bash
dsct stats capture.pcap
```
Read packets as JSONL:
```bash
dsct read capture.pcap
```
By default, `dsct read` outputs at most **1 000 packets**. Use `--count` to
change the limit or `--no-limit` to remove it:
```bash
dsct read capture.pcap --count 50
dsct read capture.pcap --no-limit
```
Filter packets:
```bash
dsct read capture.pcap -f dns --count 10
dsct read capture.pcap -f "dns AND dns.qr = 'Query'"
```
Filter expressions use SQL syntax with `AND`, `OR`, `NOT`, parentheses, and
comparison operators (`=`, `!=`, `>`, `<`, `>=`, `<=`):
```bash
dsct read capture.pcap -f "dns OR (tcp AND ipv4.src = '10.0.0.1')"
dsct read capture.pcap -f "tcp.dst_port > 1024 AND NOT dns"
```
Sample evenly across the capture:
```bash
dsct read capture.pcap --sample-rate 100
dsct read capture.pcap -f dns --sample-rate 10 --count 50
```
Read from a pipe:
```bash
tcpdump -w - -c 1000 | dsct read -
tcpdump -w - -i eth0 udp port 53 | dsct read - -f dns
```
Inspect available fields and schemas:
```bash
dsct fields dns
dsct schema read
```
Open the TUI for a large file (when built with `--features tui`):
```bash
dsct tui capture.pcap
```
In the TUI, press `?` to open the built-in help overlay and `q` to quit.
## Typical workflow
```bash
# 1. Discover supported protocols
dsct list
# 2. Inspect available filter fields
dsct fields dns
# 3. Read matching packets as JSONL
dsct read capture.pcap -f "dns AND dns.qr = 'Query'" --count 20
# 4. Get capture-wide statistics
dsct stats capture.pcap --top-talkers
```
## Commands
| Command | What it does |
| --- | --- |
| `dsct read <FILE>` | Stream packet records as JSONL |
| `dsct stats <FILE>` | Emit capture statistics as JSON |
| `dsct list` | List supported protocols as JSON |
| `dsct fields [PROTOCOL...]` | List filterable fields as JSON |
| `dsct schema [COMMAND]` | Show JSON Schema for command output |
| `dsct version` | Show version and capability information as JSON |
| `dsct mcp` | Start an MCP server over stdio |
| `dsct tui <FILE>` | Open the interactive TUI for a capture file (`tui` feature only) |
Run `--help` on any command for the full option list.
## MCP tools
`dsct mcp` exposes the following tools over the Model Context Protocol:
| Tool | Description |
| --- | --- |
| `dsct_read_packets` | Dissect packets from a pcap/pcapng capture file. Returns an array of dissected packet objects with protocol layers and fields. |
| `dsct_get_stats` | Get protocol statistics from a capture file. Returns packet counts, timing, protocol distribution, and optional deep analysis. |
| `dsct_list_protocols` | List all supported protocols with their specification references and layer information. |
| `dsct_list_fields` | List available field names for protocols. Fields can be used with `dsct_read_packets` for filtering. |
| `dsct_get_schema` | Get the JSON schema for command output formats (`read` or `stats`). |
### Key parameters
**`dsct_read_packets`**: `file` (required), `filter`, `count`, `offset`, `packet_number`, `decode_as`, `esp_sa`, `verbose`
**`dsct_get_stats`**: `file` (required), `protocol`, `top_talkers`, `stream_summary`, `top`, `decode_as`, `esp_sa`
**`dsct_list_fields`**: `protocol`
**`dsct_get_schema`**: `command` (`"read"` or `"stats"`)
### Configuration example
Add `dsct` to your MCP client (e.g. Claude Desktop):
```json
{
"mcpServers": {
"dsct": {
"command": "dsct",
"args": ["mcp"]
}
}
}
```
### Default limits
When `count` is omitted, `dsct_read_packets` returns at most **1 000 packets**
(configurable via `DSCT_MCP_DEFAULT_COUNT`). `dsct_get_stats` processes the
entire capture by default. All tool calls are subject to a per-execution
timeout; on timeout the server returns a JSON-RPC error and no partial output
is sent.
### Environment variables
Resource limits can be tuned via environment variables:
| Variable | Default | Description |
| --- | --- | --- |
| `DSCT_MCP_DEFAULT_COUNT` | 1000 | Default packet count when `count` is not specified |
| `DSCT_MCP_TIMEOUT` | 300 | Timeout per tool execution in seconds |
| `DSCT_MCP_WRITE_BUFFER_SIZE` | 65536 | Stdout write buffer size in bytes |
| `DSCT_MCP_MAX_FILE_SIZE` | 10737418240 | Maximum capture file size in bytes |
## Output
`dsct read` emits one JSON object per line:
```jsonl
{"number":1,"timestamp":"2024-01-15T10:30:00.123456Z","length":74,"original_length":74,"stack":"Ethernet:IPv4:UDP:DNS","layers":[{"protocol":"Ethernet","fields":{"dst_mac":"ff:ff:ff:ff:ff:ff","src_mac":"00:11:22:33:44:55","ethertype":"IPv4(2048)"}},{"protocol":"IPv4","fields":{"src":"10.0.0.1","dst":"10.0.0.2","protocol":"UDP(17)"}},{"protocol":"UDP","fields":{"src_port":12345,"dst_port":53}},{"protocol":"DNS","fields":{"id":4660,"qr":"Query","opcode":"QUERY(0)","questions":[{"name":"example.com","type":"A(1)","class":"IN(1)"}]}}]}
```
The other commands emit a single JSON object or array on stdout.
## Supported protocols
The default build currently includes 50+ protocol dissectors across link, network, transport, tunneling, and application layers.
Use `dsct list` to see the exact protocol set in your build.
## Errors
Errors and warnings are emitted as structured JSON on stderr.
Example:
```json
{"error":{"code":"file_not_found","message":"failed to open capture file: test.pcap"}}
```
Exit codes:
| Code | Meaning |
| --- | --- |
| `0` | Success |
| `1` | General error |
| `2` | Invalid arguments |
| `3` | File not found or permission denied |
| `4` | Invalid capture format |
## License
Licensed under either of [Apache License 2.0](LICENSE-APACHE) or [MIT License](LICENSE-MIT) at your option.