SIS CLI
Extract Guide
sis extract recovers the textual content of a document — the body/metadata text a human, a
renderer, a retriever, or a model would actually see — format-agnostically and without scoring or a
verdict. It is a provenance-aware, hostile-aware text extractor (a channel-aware extractor), not an
analysis command: it never decides whether content is malicious. Use sis scan/sis assess for
that.
When to use it
- Feed a document’s text into a RAG pipeline, a model, or a search index — with explicit channel selection and removal limits.
- See which text is visible vs. hidden/retrieval-only (the channels an injection hides in).
- Remove spans identified by the configured removal contracts before ingestion (
--safe), with a logged, deterministic removal contract.
Channels
Extraction is organised into typed channels. The default emits body,metadata; other classes are
counted but not emitted unless you ask for them:
body— text attributed to the body by the extractor; attribution is not rendering proofmetadata— title/author/XMP and other document metadataannotation— annotation/comment textembedded— text from embedded objectshidden— render-suppressed / retrieval-only text (the prime prompt-injection carrier). Counted by default, not emitted — select it explicitly (--channels hiddenor--include-hidden) to see it.code— script/macro textall— every class
Channels classified as hidden are emitted separately when selected. Classification can be incomplete:
the HTML limitation below shows that concealed text can also be attributed to body. Neither channel
labels nor removal counts alone establish what a renderer would show or what remains safe to ingest.
Common invocations
sis extract report.pdf # markdown (YAML frontmatter), body+metadata
sis extract report.pdf --format json # structured JSON (no frontmatter)
sis extract report.pdf --format text # plain text only
sis extract report.pdf --channels all --include-hidden # everything, hidden labelled
sis extract report.pdf --metadata-only # metadata channels only
Safe text (AI-ingestion)
--safe strips the spans flagged by the safe-text removal contracts: text carried by hidden or transformed
instruction carriers. Visible directive-like text is passed through unchanged. The analyser does not judge the
meaning of visible prose, so a visible “ignore previous instructions” is a non-verdict fact, not a removal;
filtering it is the consuming guard’s job. The result is a derivative with disclosed removals, not proof that
all harmful instructions were found:
sis scan doc.pdf --format json --emit json=report.json
sis extract doc.pdf --safe --from-report report.json # deterministic: contracts from the report
sis extract doc.pdf --safe # minimal inline analysis derives contracts
--from-report <REPORT>makes the removal deterministic (same bytes + options ⇒ identical output) by reading the contracts a priorsis scan --format jsonproduced. Use it only with the exact unchanged input that produced the report. The current extractor does not verify report/input identity; the caller must bind them. Keep both input/report digests and the build/options with the derivative.- Without
--from-report,--saferuns a minimal inline analysis to derive the contracts (the verdict is discarded). It fails closed if no contract source is available — it does not silently fall back to faithful extraction when contract acquisition fails. A successful contract acquisition still does not establish complete observation coverage. --safe-min-confidence <tentative|probable|strong|certain>(defaultprobable) is the minimum confidence of a flagged span to remove. Raising it can retain lower-confidence flagged spans; it does not raise the assurance of the remaining text.
Known HTML limitation: text from a render-hidden node can be retained in a body channel even with --safe/ai-ingest-safe, while removal telemetry reports applied removals. A removal count is not proof that the emitted text excludes every flagged instruction. Inspect the actual channels, and refuse the original or derivative when your ingestion policy cannot accept that uncertainty.
Named extraction profiles
sis extract sample.html --profile human-visible --format json
sis extract sample.html --profile ai-ingest-safe --format json
sis extract sample.html --profile analyst-full --format json
human-visible selects body/metadata; ai-ingest-safe selects those channels plus identified span removal; analyst-full selects all channel classes including hidden/code/embedded. The detector-substrate profile additionally exposes raw/non-content material. Profiles conflict with explicit --channels and --metadata-only. Profile names describe presets, not safety certification. Inspect the emitted removal and unavailable-channel records before ingestion.
Containers and batch
--members <inline|root-only|separate>projects container members (email attachments, archive entries, OOXML parts).inline(default) folds member channels into one document;separateemits one document per member (bounded by--max-depth, default 4);root-onlysuppresses members.--path <DIR> [--glob PATTERN] [--jobs N]batch-extracts every matching file, streaming JSONL (--format jsonl). Format is detected from content, not extension.
Determinism
Extraction is deterministic: the same bytes + the same options (+ the same removal-contract source and engine build) define the extraction conditions. Preserve removal records, coverage and input identity when comparing outputs. --posture is a recorded label; it does not select the inline scan policy. Do not infer cross-version or cross-environment equivalence from it.
Scoping to specific assets (--asset)
--asset <selector> scopes extraction to the assets matching an asset-path selector, extracting
each matched member as its own document instead of the whole root. It reuses the same selector engine
as sis query and the same channel/--safe/--format pipeline, applied per selected asset.
sis extract bundle.zip --asset "**/[format=ooxml]" --format json # just the OOXML members' text
sis extract report.pdf --asset "pdf:root" # the root document only
Do not combine --asset with --from-report: the asset path uses the live per-asset pipeline rather than the report-backed root path.
Single-file only (conflicts with --path batch and --members separate — the selector is the member
scoping). A no-match selector exits non-zero, and so does a selector that cannot be decided for a selected asset (it tests a field the asset never recorded): extraction refuses and acts on nothing rather than extract a partial selection. Deeply-nested members beyond the flat member seam report
status: unavailable. The selector grammar is in sis docs asset-graph.
What it does NOT do
- No verdict, no findings, no scoring — use
sis scan/sis assess. - No file rewrite — it emits text, not a sanitised document. To produce a cleaned file, use
sis sanitize(CDR).sis docs cdr.
Related guides
sis docs assess— the AI-ingestion decision that wraps safe-textsis docs cdr— produce a cleaned file (not just text)sis docs asset-graph— the--assetselector grammar (and/textinsis query)sis docs formats— which roots are supportedsis docs scan-config— analysis options (extract is analysis-free, but scan feeds--from-report)