PROTOLENS(1)
okay so welcome to protolens(1), bestie β it lives in section 1 of the General Commands Manual, aka the place where user commands hang out. This is the whole tour, no skips, no cuts. π
β¨ NAME β¨
protolens β a terminal viewer that decodes, navigates and extracts binary protobuf messages. literally the whole point π«Ά
π¦ SYNOPSIS π¦
protolens [--descriptor-set] [-I|--proto-root] [-t|--type] [--raw]
[--indent] [--min-score] [-j|--jobs] [--theme]
[--override-preview-byte-budget] [--load-overrides] [--assume-binary]
[--eager-read] [--script] [--no-script] [--no-packing-penalty]
[--script-height] [-h|--help] [-V|--version] <BLOB> [subcommands]
πΈ DESCRIPTION πΈ
It's an interactive TUI. You point it at a binary protobuf, and it decodes it, lets you navigate around it, and pulls raw bytes out. That's the vibe check and it passes β¨
Want shell completion? Say less β here's how for each shell:
- bash:
source <(PROTOLENS_COMPLETE=bash protolens) - zsh:
source <(PROTOLENS_COMPLETE=zsh protolens) - fish:
PROTOLENS_COMPLETE=fish protolens | source
π OPTIONS π
--descriptor-set <DESCRIPTOR_SET>β theFileDescriptorSetused for root-type determination and type resolution. It can be a raw binaryFileDescriptorSetor a#@ prototext-formatFileDescriptorSet. It shares its env var withprototext/reproto(spec 0090), so one singlePROTOTEXT_DESCRIPTOR_SETcovers the whole toolset, no cap. May also be specified with thePROTOTEXT_DESCRIPTOR_SETenvironment variable.-I,--proto-root <PROTO_ROOT>β root directory that.protosource files get resolved against forv's jump-to-definition (spec 0144). It shares its env var naming withPROTOTEXT_DESCRIPTOR_SET(spec 0090), and it's set externally by the internalprototoolspackage embedding this repo. When neither this nor the env var is set, it falls back to<stub>/proto/next to--descriptor-set(<stub>= the descriptor-set path with its extension stripped β the same stubreproto --schema-db-outuses), if that directory exists (spec 0155 G2). Still fully optional, bestie βvreports a message rather than failing at startup when no root is found either way. May also be specified with thePROTOTEXT_PROTO_ROOTenvironment variable.-t,--type <TYPE>β the root message type. If you omit it, it's inferred automatically from--descriptor-set(which requires ahopcroft.rkyvscoring graph sitting next to it); and if inference is unavailable or inconclusive, the blob is rendered with no known type. π--rawβ skip root-type inference entirely and open the blob with no type at all, as raw wire bytes (spec 0168). Inference is the one startup phase whose cost scales with the size of the schema database rather than the blob, so on a large descriptor set this is the fast way in; it's also the way to look at a blob whose inferred type is wrong. You can still pick a type interactively afterwards, via the override pane.--indent <INDENT>[default:2] β number of spaces per nesting level in the rendered text.--min-score <N>[default:0] β the lowest score an inferred root type may have and still be used (spec 0389). It's an integer, negative allowed, oranyfor no floor. Below it, the blob opens with no type, same as on a tie; the override pane still lists every candidate though. A score is matches minus weighted penalties, so a negative one means the type contradicts the bytes more than it explains them π. Ignored with--typeand--raw. Shares its env var withprototext. May also be specified with thePROTOTEXT_MIN_SCOREenvironment variable.-j,--jobs <JOBS>[default:80] β your CPU budget for root-type inference (spec 0217). Inference is the one startup phase whose cost scales with the size of the schema database rather than the blob, and it divides cleanly: the candidate types are partitioned and swept in parallel. π§
This is a ceiling for the whole session, not a target. It gets clamped to the number of CPUs actually available to the process (which respects a cgroup quota and an affinity mask), and while the TUI is running, one thread of it is left to the main loop. Defaults to every available CPU; 1 restores the single-threaded sweep.
--theme <THEME>[default:system] β the syntax-highlighting color palette (spec 0116 Β§9).systemprobes the terminal's actual background once at startup and resolves todarkorlight. π
Possible values:
darklightsystem
--override-preview-byte-budget <OVERRIDE_PREVIEW_BYTE_BUDGET>[default:4096] β the max number of interior bytes of a live-preview override candidate handed to the renderer (spec 0174). It guards against a structurally mismatched candidate type making the recursive-descent decoder mis-parse arbitrary bytes into a pathologically large synthetic tree while you're just browsing candidates π. A truncated preview ends with a...line. A confirmed override is always rendered completely, no matter what this value says.--load-overrides <LOAD_OVERRIDES>β a previously-saved override collection (spec 0117 Β§4 YAML, the same file:save-overrideswrites) to apply when the TUI opens. A target-hash mismatch is a warning (to stderr), not a hard error (spec 0354 S3). A missing file or malformed YAML is a hard error π.
Only applicable to the interactive TUI (no subcommand). For batch override loading, see export --load-overrides.
--assume-binaryβ take the blob for wire bytes without even looking (spec 0216 S29).
Normally, a file whose first 13 bytes are #@ prototext: gets decoded from the textual form instead. This says don't, for the rare binary blob that happens to begin with those exact bytes.
--eager-readβ read the blob into memory instead of mapping it (spec 0216 S29). π
A large binary blob is mapped, which keeps its pages evictable rather than making them the process's own. The cost? The file must not change underneath the session: truncating it, or losing the network filesystem it lives on, turns a read into a SIGBUS rather than an error at startup. Use this for a blob that cannot be trusted to hold still.
Mapping is declined by itself for a small blob and for anything that isn't a regular file, so you only need this for the case the size test can't see.
--script <SCRIPT>β a guided walk through the blob to load (spec 0271). A missing or malformed file is a hard error.
With no --script, the blob path with its extension replaced by .script is loaded if it exists.
--no-scriptβ do not look for a script beside the blob (spec 0271 S1).--no-packing-penaltyβ don't charge records whose packing contradicts the schema's declaration (spec 0371). By default such a record scores net zero, which is right when blobs and schemas come from the same build; turn it off for a corpus whose writers ignore the declaration.--script-height <SCRIPT_HEIGHT>β rows for the script pane, overriding its computed height: the script's tallest step, at most a third of the terminal (spec 0400 S1).-h,--helpβ print help (see a summary with-h).-V,--versionβ print version.<BLOB>β the binary protobuf to decode. π
π SUBCOMMANDS π
protolens-export(1)β export one node's rendering (or, for the two descriptor formats, its synthetic schema) and exit, without entering the interactive TUI.protolens-quit(1)β run every startup phase and exit, without entering the interactive TUI (spec 0198) β this is the startup-time benchmark target. β±οΈprotolens-script(1)β apply every step of the loaded script and write what each one produced, without entering the interactive TUI (spec 0271 S14).protolens-help(1)β print this message or the help of the given subcommand(s).
β VERSION β
v0.3.4
π¦ ENVIRONMENT π¦
PROTOLENS_COMPLETEβ when set tobash,zsh, orfish, print a shell completion script to stdout and exit. β¨PROTOLENS_GEN_MANβ when set to a directory, write this man page there asprotolens.1and exit.
π EXAMPLES π
Open a blob, inferring its root type from the descriptor set
protolens --descriptor-set schemas.desc message.binpb
Open a blob as raw wire bytes, skipping inference
protolens --raw message.binpb
Export one node without entering the TUI
protolens --descriptor-set schemas.desc message.binpb export /1/2
Enable bash completion
source <(PROTOLENS_COMPLETE=bash protolens)
π SEE ALSO π
prototext(1), reproto(1), protoscan(1)
and that's the whole page, bestie β no notes left behind π«Ά this one's from the User Commands corner of the General Commands Manual, page protolens, and yeah it's literally called PROTOLENS(1) in the header and the footer both. go decode something iconic π
π¦ where this page comes from
- nixpkgs unstable: protolens 0.3.4
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms