Documentation · v0.5.0 · schema_version "1"
The CLI contract, as implemented.
Everything on this page describes implemented, tested behavior of Arcthis 0.5.0. Capabilities that are still on the roadmap are marked planned. The authoritative long-form guide is START.md in the repository.
Command grammar
One format-independent grammar. There are no ZIP-specific or TAR-specific top-level commands.
arcthis <command> <archive> [entry] [options]
The default workflow is access before extraction: inspect → tree/list → stat/read → extract only what you actually need. Full extraction is always an explicit operation.
Output contract
Strict stream separation makes Arcthis safe to drive from scripts and agents.
- stdout carries result data only. stderr carries diagnostics, warnings and progress.
--jsonselects machine output on commands with structured results;readalways emits raw entry bytes and rejects--json.- JSON and non-TTY output contain no ANSI decoration.
--no-colorandNO_COLORdisable color in a TTY. - A stdout
BrokenPipeis a successful early consumer stop —arcthis read a.zip big.bin | headexits 0. - Non-UTF-8 entry names are reported explicitly through
path_encoding; extraction refuses byte-escaped paths, so a different filename is never materialized.
Global options
Accepted before the subcommand, from arcthis --help.
| Option | Default | Meaning |
|---|---|---|
| --json | off | Emit stable machine-readable JSON where supported |
| --no-color | off | Disable terminal color decoration |
| --within <entry> | — | Traverse into this archive entry; repeat to descend through multiple archives (depth cap 8) |
| --max-nested-entry-size <bytes> | 268435456 | Maximum decoded bytes buffered for each nested archive entry |
| --password-file <path> | — | Read an archive password from this file; trailing CR/LF is removed. Passwords are never CLI values |
| --volume <path> | — | Append a byte-stream archive volume; repeat in exact volume order |
| --index-directory <path> | platform cache | Override the platform cache root used by persistent indexes |
Commands
Signatures from the CLI contract; descriptions from arcthis --help.
Show archive metadata, capabilities, and risk warnings. Reports entry counts, sizes, compression ratio, warnings as stable objects, and capability booleans such as random_access, solid and encrypted — enough for an agent to estimate the cost of an operation before paying it.
List archive entries in archive order, preserving duplicates. JSON adds an entries array of full entry objects.
Display archive entries as a file tree. JSON adds a recursive tree node array; implicit directories carry entry: null.
Show metadata for one archive entry: kind, size, compressed size, modification time, encryption, CRC-32 and a lightweight extension-based MIME guess. A missing path returns entry_not_found; a duplicate path returns collision because selection is ambiguous.
Stream one regular file entry to stdout. This is the composition primitive — archive contents pipe straight into the tools you already use:
arcthis read source.zip src/lib.rs | rg unsafe · arcthis read media.zip video.mp4 | ffprobe -i pipe:0
Find archive entries whose paths match a glob. Matching applies to full normalized entry paths and never reads entry content.
Search regular-file contents without extracting them. Literal (not regex) matching, streamed, with bounds: 16 MiB per entry, 10,000 matches, 1 MiB per retained line, and an 8 KiB NUL probe that skips binary files unless --binary is set.
Stream one entry through a cryptographic hash. SHA-256 is the default; SHA-512 is also implemented. The digest is lowercase hexadecimal.
Create, refresh, inspect, or delete a persistent entry metadata index. Indexes are treated as untrusted cache input and invalidated by source size and modification time.
Safely extract all entries or one selected regular file. A complete metadata preflight runs first; writes go to a sibling staging location and commit only after all entries succeed. Lifecycle flags: --dry-run, --delete-source, and exactly one of --overwrite / --skip-existing / --rename.
Safely extract every supported archive discovered in a directory. Work is bounded and parallel across independent archives, results are deterministically sorted, and a dry-run returns one typed plan per discovered archive.
Create and verify a supported archive or single-stream file. The temporary sibling archive is finalized, reopened through the normal archive interface, verified entry by entry, and only then committed. An output inside a directory source, and any source/destination alias, is rejected.
Verify archive structure and readable entry data in a full-stream pass. JSON adds a verification object with verified, entries_checked and bytes_checked.
Convert an archive through safe staged extraction and verified packing. Entry paths are preserved, extraction resource and path validation run before any materialization, and the target is verified before commit or any --delete-source.
Serve the bounded local Model Context Protocol frontend over stdio (feature build, MCP revision 2025-06-18). Nine read-only tools are always available; six extract/pack/convert plan/execute tools are advertised only with an explicit output policy. Source deletion requires both --allow-source-deletion and delete_source: true.
JSON & errors
Every successful structured response is one JSON document followed by a newline. Command-specific fields extend a shared envelope.
{ "schema_version": "1", "archive": { "path": "dataset.zip", "path_lossy": false, "format": "zip" }, "entry": { "archive_index": 42, // stable source order "path": "train/data.csv", "path_encoding": "utf8", // or "escaped_bytes" (%XX) "kind": "file", "size": 1048576, "compressed_size": 182341, "modified_time": "2026-08-27T12:00:00Z", "encrypted": false, "crc32": "c0ffee00", "mime_guess": "text/csv" // extension-based, never reads content } }
With --json, command errors are JSON on stderr and stdout stays empty:
{ "schema_version": "1", "error": { "code": "entry_not_found", "message": "archive entry was not found", "details": { "entry": "README.md" } } }
Stable error categories:
Exit codes
Deterministic mapping from error category to process exit status.
| Exit | Category |
|---|---|
| 0 | Success, including BrokenPipe consumer stop |
| 1 | General I/O error |
| 2 | CLI syntax/usage error from clap |
| 3 | unsupported_format |
| 4 | invalid_archive or corrupted_archive |
| 5 | entry_not_found |
| 6 | permission_denied |
| 7 | unsafe_path |
| 8 | resource_limit |
| 9 | collision |
| 10 | unsupported_operation, password categories |
| 11 | verification_failed |
| 12 | partial_failure |
Resource limits
Limits are enforced on the real write/decode path — not just warned about during inspection.
| Option | Default |
|---|---|
| --max-entries | 100,000 |
| --max-total-size | 16 GiB |
| --max-entry-size | 4 GiB |
| --max-compression-ratio | Disabled unless specified |
| --max-entry-duration-seconds | Disabled unless specified |
Safety defaults
The short version; exact guarantees and known limits live in docs/SECURITY.md.
- Path sanitization. One unified sanitizer rejects
.., absolute paths, Windows drive/UNC prefixes, NUL bytes, and links that could escape the destination. - No implicit links or special files. Symlinks, hardlinks and special files are not restored by default.
- Transactional writes. Staging plus commit; pack finalizes, reopens and verifies before the requested output appears.
- Alias and overlap checks. Destructive lifecycles reject source/destination filesystem aliases and ancestor/descendant overlap before writing.
- Delete-source last.
--delete-sourceruns only after perform → finalize → verify → commit; errors, interrupts and failed verifications preserve the source. Dry-runs never write or delete. - No secrets in argv. Passwords come from
--password-fileonly, and are redacted from library debug output.
Planned
Not implemented in v0.5.0 — listed here so agents never guess. Each requires matching library support, JSON schemas, tests and documentation before becoming public behavior. See ROADMAP.md.