# `sirdas` CLI

Same engine as the web app and the MCP server, from the terminal. No network, no accounts, no telemetry.

## Install

```bash
npx sirdas factura.pdf       # nothing to install but Node 20+
npm i -g sirdas              # or keep it around
```

From source:

```bash
git clone https://github.com/Brayan15p/SIRDAS-APP-PDF.git && cd SIRDAS-APP-PDF
npm install && npm run build -w packages/core -w packages/mcp -w packages/cli
node packages/cli/dist/main.js --help     # or: npm link -w packages/cli
```

## Commands

```
# Start here: reads any file end to end (PDF, scan, DOCX, XLSX, PPTX, HTML, EPUB, CSV, EML, PNG/JPG)
sirdas <file>
sirdas leer      <file> [--json] [--no-anonymize] [--no-ocr] [--max-tokens 1500] [-o out.md]

sirdas convertir <file.docx|xlsx|pptx|odt|epub|html|csv|eml|rtf> [--json] [-o out.md]
sirdas separar   <batch.pdf> [-d dir] [--json]        # one PDF per document inside a batch
sirdas formulario <file.pdf> [--json]                  # filled form fields and checkboxes
sirdas classify  <file.pdf> [--json]                   # factura, contrato, historia_clinica…
sirdas revisar   <folder> [--sin-nombres]              # run everything over real files, report without content

sirdas pages     <file.pdf> delete|extract|rotate [--pages "2, 4-6"] [--angle 90] [-o out.pdf]
sirdas number    <file.pdf> [--format "Página {n} de {total}"] [--position bottom-right] [--skip-first 1]
sirdas watermark <file.pdf> --text CONFIDENCIAL [--opacity 0.15]
sirdas protect   <file.pdf> [--no-print] [--no-copy] [--no-edit] [-o out.pdf]   # asks for the password, or SIRDAS_PASSWORD
sirdas unlock    <file.pdf> [-o out.pdf]

sirdas markdown  <file.pdf> [--no-anonymize] [--json] [-o out.md] [--force]
sirdas ocr       <scan.pdf> [--lang spa+eng] [--lang-path dir] [--no-anonymize]
sirdas ocr --download-models [--lang spa]   # once; then it works offline
sirdas anonymize [file.txt] [--json] [--map map.json]  # reads stdin when no file
sirdas restore   [file.txt] --map map.json            # puts the real data back
sirdas chunks    <file.pdf> [--max-tokens 2000] [--json] [-d dir]
sirdas tables    <file.pdf> [--csv|--markdown|--json] [-d dir] [--delimiter ";"]
sirdas compare   <before.pdf> <after.pdf> [--all] [--json] [--ignore-case]
sirdas info      <file.pdf> [--json]
sirdas merge     <a.pdf> <b.pdf> [...] -o out.pdf [--force]
sirdas split     <file.pdf> [--ranges "1-3, 5, 8-end"] [-d dir] [--force]
sirdas compress  <file.pdf> [-o out.pdf] [--force]   # lossless

# Training data (all local, no model is ever called)
sirdas dataset       <a.pdf|b.docx|c.html> [...] [--format text|chat|prompt-completion|alpaca|sharegpt|langchain|llamaindex|embeddings]
                     [--hf]   # train/validation/test.jsonl + Hugging Face README.md
                     [--max-tokens 2000] [--no-anonymize] [--no-dedupe]
                     [--strip-boilerplate] [--split] [--seed s]
                     [--template "..."] [--system "..."]
                     [-d dir] [--no-meta] [--json]
sirdas dedupe        <a.pdf> <b.pdf> [...] [--threshold 0.8] [--json]
sirdas boilerplate   <a.pdf> <b.pdf> [...] [--min-words 5] [--json]
sirdas contamination <train.pdf> [...] --against <eval.pdf> [--n 13] [--json]
sirdas rl            <a.pdf> [...] [--max-per-table 10] [--lang es|en] [-o f.jsonl]
sirdas rl --reward-fn                                # the Python reward function
sirdas mcp                                           # start the MCP server over stdio
```

`md` is an alias of `markdown`.

## Conventions agents can rely on

- **Exit codes:** `0` success · `1` usage error (bad flags, missing input, refusing to overwrite) · `2` the file could not be processed (password-protected, damaged, not a PDF). The reason is printed to **stderr** in one sentence.
- **stdout is the payload.** `markdown` prints Markdown; with `--json` it prints one JSON object (`markdown`, `pages`, `tokens_estimate`, `anonymized`, `redacted`, `has_text`, `source`). Progress and warnings go to stderr.
- **Anonymization is on by default** for `markdown`; `--no-anonymize` keeps the original data.
- **Never overwrites** an existing file without `--force`.
- `anonymize --json` includes the placeholder→value `mapping`; keep it local.

## The anonymize → AI → restore round trip

Nothing is ever deleted. The original PDF is untouched and the mapping — which holds the real values — stays on your machine.

```bash
# 1. Anonymize, keeping the mapping
sirdas markdown historia.pdf --json | jq -r .markdown > anonima.md
sirdas anonymize anonima.md --map mapa.json > anonima-final.md

# 2. Send anonima-final.md to any model, then restore its answer locally
cat respuesta-de-la-ia.txt | sirdas restore --map mapa.json
```

A name always comes back whole: placeholders map to the complete original value, never a fragment.

## Examples

```bash
# Markdown for an LLM, personal data replaced
sirdas markdown historia.pdf > historia.md

# Structured output for a script
sirdas markdown contrato.pdf --json | jq '.tokens_estimate, .redacted'

# Anonymize a snippet before pasting it anywhere
echo "Paciente: Ana Gómez, C.C. 52.123.456" | sirdas anonymize

# Split the first three pages and the last one
sirdas split informe.pdf --ranges "1-3, 8-end" -d ./partes

# Pull an invoice's line items into a spreadsheet (CSV carries a BOM for Excel)
sirdas tables factura.pdf --delimiter ";" -d ./tablas

# Split a long document into chat-sized pieces
sirdas chunks informe.pdf --max-tokens 2000 -d ./partes

# Merge, then shrink losslessly
sirdas merge a.pdf b.pdf -o todo.pdf && sirdas compress todo.pdf
```
