CLI reference
The Rust binary is the source of truth for viewer startup.
dcmview [OPTIONS] <PATH> [PATH ...]At least one DICOM file or directory path is required in normal use. Repeat paths to combine inputs in one temporary viewer.
Options
Section titled “Options”| Option | Default | Description |
|---|---|---|
<PATH>... |
required | DICOM file or directory to inspect. |
-p, --port <PORT> |
0 |
HTTP port. 0 asks the operating system for an available port. |
--host <ADDR> |
127.0.0.1 |
Interface to bind. Non-loopback values send the access token and DICOM data over unencrypted HTTP. |
--unix-socket <PATH> |
none | Listen on a private Unix domain socket instead of TCP. Linux and macOS only. Conflicts with --host and --port. |
--no-token |
off | Serve the API without the access token, with a warning. For use behind a proxy that already authenticates. |
--no-browser |
off | Print the viewer URL instead of opening the default browser. |
--timeout <SECONDS> |
none | Exit after this many seconds without API or browser requests once the scan ends. |
--cache-budget <BYTES> |
704MiB |
Total memory for cached display, raw, and overlay frames, such as 256MiB. Minimum 16MiB. |
--no-recursive |
off | Scan only the top level of input directories. |
--annotations <CSV> |
none | Load an EMBED-style ROI CSV into memory without modifying it. |
--filter <FIELD=VALUE> |
none | Include only matching DICOM metadata; repeatable. |
--mask |
off | Replace patient identifiers in everything the viewer displays, for screen sharing. Display only: files are not modified and this is not de-identification. Fixed for the session. |
-h, --help |
— | Print help. |
-V, --version |
— | Print the version. |
--startup-json and --vscode-bridge-client exist for wrapper and VS Code integration. They are hidden and are not ordinary user-facing options.
v0.3.0 removed --tunnel, --tunnel-host, and --tunnel-port. Passing them is now a command-line error. Forward the viewer port from your local machine instead; see Inspect a study over SSH.
Access token
Section titled “Access token”Every request under /api requires Authorization: Bearer <token>. One token is generated at startup from 32 bytes of operating-system randomness, written as 43 base64url characters, and lasts for the life of the process. The printed links carry it as #token=…, so opening the viewer needs no extra step. Treat those links as credentials.
| Setting | Behavior |
|---|---|
DCMVIEW_TOKEN |
Environment variable that fixes the token instead of generating one. It must be non-empty and use only A-Z a-z 0-9 - . _ ~. An invalid value stops startup without echoing it. A fixed token is not rate-limited, so make it long and random. |
--no-token |
Generates no token, prints links without a fragment, and warns that the API is open to anything that can reach the listener. Use it only behind a proxy that already authenticates. |
Setting DCMVIEW_TOKEN together with --no-token is a startup error, even when the variable is empty. The token is never accepted as a command-line argument.
The token does not encrypt anything, and when dcmview opens the browser itself the operating system’s opener receives the launch link as a process argument. On a host shared with other accounts, prefer --no-browser or --unix-socket. See ephemeral state and network security.
Unix socket mode
Section titled “Unix socket mode”--unix-socket <PATH> serves the viewer through a Unix domain socket instead of a TCP port, for a shared server with SSH forwarding. It needs an explicit path; there is no default location.
dcmview --unix-socket ~/dcmview/scan.sock ./study- The parent directory must belong to your effective user and must not be group- or other-writable. If it is missing,
dcmviewcreates that one directory with mode0700; its own parent must already exist. An unsafe directory is refused before any existing socket is touched. - The socket has mode
0600, and a connection is accepted only when its peer user ID matches the server’s. - A mode
0600<socket file name>.lockfile holds an exclusive lock for the server’s lifetime. The directory therefore needs a filesystem that supports file locks; some network filesystems do not. - A live socket is reported as already in use. A regular file, symlink, or other non-socket entry at the path is refused and left untouched. A socket that refuses connections is treated as stale and replaced.
- The socket and its lock file are removed on graceful shutdown. A forced kill can leave a stale socket.
Socket mode conflicts with --host and --port, always runs the local viewer even from a VS Code terminal or workspace folder, and never opens a browser. The viewer routes, the access token, and --timeout behave as they do over TCP. Forwarding the socket needs OpenSSH 6.7 or newer on both ends. Windows builds reject the option, and Python view() and the VS Code extension do not offer it. See Use a private Unix socket on a shared server.
Frame cache memory
Section titled “Frame cache memory”--cache-budget <BYTES> sets one total for the server’s display, raw, and overlay frame caches:
dcmview --cache-budget 256MiB ./studyA value is a whole byte count, such as 268435456, optionally followed by KiB, MiB, or GiB in any letter case and without a space. Fractions, signs, decimal suffixes such as MB, and totals below 16MiB are rejected.
The total is split among the display, raw, and overlay caches in the proportions of their defaults of 256, 384, and 64 MiB. A frame larger than its cache’s share is served without being retained. Without the option the defaults apply, 704 MiB in total.
This limits retained frames, not total process memory. It does not cover decoding and responses in flight, the file catalog, annotations, or the tag, semantic-context, and value-mapping caches. Browser memory is separate.
Display masking
Section titled “Display masking”--mask starts a masked session for a shared or recorded screen. Patient identifiers are replaced in everything the viewer displays: patients show as numbered pseudonyms, dates are shifted, instance UIDs are hashed, and identifying attributes show [masked]. The mode is fixed for the process, and replacements differ on every run. To see unmasked values, start the viewer again without --mask.
Metadata filters
Section titled “Metadata filters”Each filter field can be written as its snake_case name or as its DICOM keyword, in any letter case:
| Name | DICOM keyword |
|---|---|
patient_id |
PatientID |
patient_name |
PatientName |
study_description |
StudyDescription |
study_date |
StudyDate |
study_uid |
StudyInstanceUID |
series_description |
SeriesDescription |
series_number |
SeriesNumber |
series_uid |
SeriesInstanceUID |
modality |
Modality |
Values use case-insensitive substring matching, and repeated filters use AND semantics. An unknown field is rejected with an error that lists both spellings.
dcmview \ --filter Modality=CT \ --filter patient_id=phantom \ ./studyReadable DICOM objects that fail a filter are counted as filtered rather than skipped.
Startup output
Section titled “Startup output”After binding its port, dcmview prints an SSH forwarding hint, the link to open through that forward, the viewer URL, and how to stop it:
dcmview: (on a remote server? run on your local machine: ssh -L <port>:localhost:<port> user@host)dcmview: then open http://localhost:<port>/#token=<session-token>dcmview: server running at http://127.0.0.1:<port>/#token=<session-token>dcmview: press Ctrl+C to stopBoth links end in the #token=… fragment that carries the access token. Under --no-token they have no fragment.
With --unix-socket, the message names the socket instead:
dcmview: listening on <socket path>dcmview: on your local machine run: ssh -L 8080:<socket path> user@hostdcmview: then open http://localhost:8080/#token=<session-token>dcmview: press Ctrl+C to stopThe URL is available before discovery finishes. When the scan completes, a summary reports the number of files loaded, skipped files broken down by reason, filtered files, and active filters.
dcmview also prints warnings on standard error:
- If the host is not a loopback address, that plain HTTP does not encrypt the access token or sensitive DICOM data. Under
--no-tokenthe warning says instead that the endpoints are unauthenticated. - Under
--no-token, that the API is open to anything that can reach the listener. - If the browser cannot be opened, that you should open the launch URL manually. The opener’s own error text is not printed, because it could contain the launch URL.
Set RUST_LOG to control logging on standard error. For example, RUST_LOG=dcmview=debug lists every skipped file and the reason it was skipped. Logs can contain file paths; redact them before sharing.
Idle timeout
Section titled “Idle timeout”--timeout counts idle time only after the scan has finished, so a long scan never uses up the timeout. After that, API and browser requests reset the clock. The timeout is a cleanup aid, not an access control.
Exit behavior
Section titled “Exit behavior”The command exits non-zero when startup validation fails, including an invalid DCMVIEW_TOKEN or an unusable socket path, no valid DICOM files are discovered, the server cannot bind, or an owned integration returns a failure. Once running, Ctrl+C, idle timeout, or an integration stop request begins graceful shutdown and cancels or joins discovery work. Stop signals are registered before the URL is printed, so an immediate Ctrl+C also shuts down cleanly.
Individual unreadable files, unsupported pixel layouts, and request-scoped decode errors do not normally stop a mixed dataset viewer.
Python module command
Section titled “Python module command”The Python package’s module command and console scripts pass their arguments unchanged to the resolved binary:
python -m dcmview_py [OPTIONS] <PATH> [PATH ...]python -m dcmview_py, dcmview, and dcmview-py accept exactly the options above; --help and --version are the binary’s own. They follow the same VS Code routing rule as the binary, wait for the viewer to exit, and return its exit status. See the Python reference for programmatic sessions.