
Company News
Socket Joins New OpenJS Program to Fund Node.js Security Work
Socket is joining the OpenJS Security Stewardship Program to fund Node.js vulnerability research, maintainer remediation, and security releases.
@deckflow/deckparse
Advanced tools
Parse any document into an agent-operable representation. Parse once, convert repeatedly: PDF, PPTX, DOCX, Keynote and URLs into durable IR artifacts and Markdown.
Parse any document into an agent-operable representation.
DeckParse turns documents into durable IR artifacts and derives views from them. Parse once — then convert, again and again, without ever re-reading the source.
deckparse doc.pdf # document → IR artifact (doc/)
deckparse convert doc/ # artifact → markdown view, no re-parse
deckparse convert doc.pdf -o doc.md # one-shot: portable markdown, images localized
It is the Parse pillar of the DeckFlow family: DeckRender turns documents into pixels, DeckParse turns them into state an agent can hold on to.
npx -y @deckflow/deckparse@latest doc.pdf
npm install -g @deckflow/deckparse
The CLI and Node.js entry require Node.js 18 or newer. Frontend applications use the separate browser entry.
parse document → IR artifact the only parsing action; produces IR, never markdown
convert IR artifact → view --to markdown (v1); never re-parses the source
deckparse doc.pdf is parse. The artifact it leaves behind is the point:
doc/
├── ir.json the parsed document model, server response verbatim
├── assets/ images by persistent identity
├── manifest.json source hash, cloud references, what exists where
└── views/markdown/ written by convert, never by parse
--json reports "engine": "local-cache" so scripts can verify instead of assume.reusedParse: true is asserted, not hoped). The IR stays convertible for 7 days; after that, a clear ir_expired error says exactly what to re-run.--keep-remote-images opts out).deckparse formats
| Input | parse → IR | convert → markdown | flags |
|---|---|---|---|
.pdf | ✅ versioned IR (stable node ids, bbox, schemaVersion) | ✅ | --profile fast|balanced|quality, --password, --no-images, --anchors |
.pptx | ✅ | ✅ | --split-pages |
.docx | ✅ | ✅ | |
.key | ✅ | ✅ | --stay-image-area-rate, --split-pages |
| http(s) URL | ✅ | ✅ | --mode source|runtime |
.doc .ppt .xls(x) .pages .numbers | ❌ | ❌ | clear error + a way out |
Unsupported pairs fail with a hint, never an approximation.
$ deckparse convert doc/ --json
{
"ok": true,
"op": "convert",
"engine": "cloud",
"format": "pdf",
"taskId": "t_abc123",
"reusedParse": true,
"outputs": [{ "file": "doc/views/markdown/index.md", "bytes": 48213 }],
"warnings": [],
"durationMs": 728
}
Errors carry a stable error.code and a distinct exit code:
| exit | error.code | meaning |
|---|---|---|
| 2 | usage_error | bad flags, or a flag that cannot apply to this input |
| 3 | unsupported | unsupported extension or --to target |
| 4 | auth_error | credential rejected or expired |
| 5 | input_error, ir_not_found, ir_expired, ir_schema_unsupported, ir_invalid, asset_error | fixable by the caller — each carries a hint saying how |
| 6 | backend_error | task failed; includes the taskId for follow-up |
| 7 | not_implemented | reserved verbs (extract, modify, export) |
| 8 | quota_error | guest quota exhausted — deckparse auth login |
Credentials live in ~/.deckflow/credentials and are shared with every DeckFlow CLI — log in once through DeckParse, DeckRender or DeckHTML and the others pick it up:
deckparse auth login
deckparse config list # every value, and exactly where it came from
Environment variables win over stored files: DECKPARSE_API_KEY → DECKFLOW_API_KEY → DECKHTML_API_KEY (and DECKPARSE_TOKEN / DECKPARSE_API_BASE / DECKPARSE_SPACE_ID likewise). Each field resolves independently — when something authenticates oddly, deckparse config list shows which file or variable is responsible.
Where parsing happens: all parsing runs in the DeckFlow cloud — the document is uploaded over HTTPS, parsed there, results downloaded back. Nothing in v1 keeps a document on your machine. If your documents cannot leave your machine, DeckParse is not for you yet.
import { parse, openArtifact } from '@deckflow/deckparse';
const doc = await parse('doc.pdf', { profile: 'quality' });
doc.irKey; // the cloud reference convert consumes
await doc.convert(); // view materialized into the artifact
await doc.convert({ anchors: true }); // pdf: provenance comments carrying node ids
// Days later, in another process — no cloud call to reopen:
const same = await openArtifact('doc/');
await same.convert({ splitPages: true });
extract, modify and export are reserved verbs on the same handle — the roadmap runs Parse → Extract → Modify → Export → render-verified round trips.
npm install @deckflow/deckparse
import { createClient } from '@deckflow/deckparse/browser';
const client = createClient({
apiBase: 'https://app.deckflow.com/v1',
token: userAccessToken, // user-scoped credential approved for browser use
// onUnauthorized: async () => refreshUserAccessToken(),
});
// file is the File selected by an <input type="file">.
const controller = new AbortController();
const doc = await client.parse(file, {
signal: controller.signal,
timeout: 300, // seconds; only bounds task waiting, not upload time
onProgress(event) {
if (event.phase === 'upload') console.log(event.progress); // 0..1
else console.log(event.taskId, event.status); // available after submission
},
});
const ir = await doc.ir(); // in-memory server response; no filesystem access
const view = await doc.convert();
console.log(view.markdown, view.images);
// The source is not uploaded or parsed again.
await client.convert({ irKey: doc.irKey }, { strict: true });
Inputs are File, { file: Blob | Uint8Array | ArrayBuffer, name: string }, or { url: 'https://…' }. Bare paths, stdin, unnamed Blobs and Node-only options such as out/force are rejected before any request. PDF parse options (profile, password, includeImages), Keynote's stayImageAreaRate, URL mode, and Markdown options (anchors, splitPages, strict) keep their Node names. Format-specific flags are checked when the input/document format is known.
parse() returns a BrowserParsedDocument with taskId, type, irKey, irSchemaVersion, ir() and convert(). Conversion returns BrowserConvertResult: markdown, optional markdownPages, images, format, schemaVersion, taskId and reusedParse: true. It does not return local paths, create artifact directories, cache documents between calls, or download all images. A markdownError is an error, never successful placeholder content.
apiKey option. Direct cloud access requires credentials and permissions intended for browser users; issuing short-lived/scoped credentials is a backend responsibility, not a feature this SDK creates.apiBase: '/api/deckparse'. The proxy must preserve the upstream API paths, authorize each operation/space, protect cookie-authenticated mutations against CSRF, and keep secrets server-side. Omitting token is appropriate only for such a proxy or intentionally permitted guest access. The SDK does not add a backend service.onUnauthorized once. Return a nonempty token string for the same user; account/default-space changes require an explicit new client. Failed refreshes reject with auth_error; they never switch to a guest identity/space. Task-creation POSTs are not automatically replayed on ambiguous network failures or gateway errors. Files of at least 4 MiB are uploaded first and referenced by fileId; that reduces large request failures but is not a server-side idempotency guarantee.X-Auth-Token, X-Auth-UUID, Content-Type and response-event-stream; multipart uploads need Access-Control-Expose-Headers: ETag. API credentials must not be forwarded to signed storage URLs. Production permissions/CORS must be verified for your deployment; localhost tests cannot certify them.Every browser parse/convert accepts signal, onProgress, timeout (seconds), useEventStream and pollInterval (milliseconds). Upload progress reports completed upload work, not a guaranteed continuous byte-level progress stream; small inline uploads report completion after the request succeeds. Aborting stops the client's HTTP requests, uploads and waiting; it does not cancel or refund a cloud task that was already submitted. An aborted call preserves the signal's abort reason (normally AbortError). Do not automatically call parse() again after an uncertain submission failure.
Keep the task id from onProgress. Other operation errors use DeckParseError with stable code, hint and, once known, taskId:
const task = await client.getTask(savedParseTaskId);
if (task.status === 'completed') {
// Retrieve a view of the completed parse without another upload/parse.
const view = await client.convert({ taskId: task.id });
}
Operations may specify spaceId without changing the client's default; document handles keep their parse space for later conversions. When recovering an operation in a different space, pass that same spaceId to getTask() and to a subsequent by-reference convert().
Cloud IR references currently have a 7-day retention period; doc.ir() retaining a local snapshot does not extend it. Image ref values are signed, expiring URLs for temporary preview, not permanent links. Persisting/offline-exporting assets is an explicit application concern. Treat document content as untrusted and sanitize rendered Markdown/HTML in your display layer.
The browser entry is framework-independent ESM and safe to import during SSR. It targets modern browsers with Fetch, Web Crypto, Blob/File and AbortController; use HTTPS (localhost is suitable for development). It still uploads documents for cloud parsing — browser support does not mean offline/on-device parsing.
pnpm install
pnpm check # typecheck + unit + integration + build
pnpm check:browser # DOM-only types + HTTP integration + browser export checks
pnpm browser:smoke # open the printed localhost URL for real-browser checks
# conformance drives the built CLI against a real backend:
DECKPARSE_API_BASE=… DECKPARSE_TOKEN=… \
CONFORMANCE_PDF=sample.pdf CONFORMANCE_PPTX=sample.pptx pnpm conformance
The browser bundle and declarations are self-contained: consumers need no Node polyfills, bundler aliases or dependency patches. Until the upstream browser fix is published, source builds apply a version-pinned pnpm patch that adds the browser entry to @deckops/sdk; the existing upstream Node entry is unchanged. Commit patches/ and the lockfile together and use pnpm install --frozen-lockfile for reproducible builds. See patch maintenance.
Browser tests use a local fake API and synthetic bytes; they verify transport contracts, not real document parsing quality or production CORS. pnpm browser:smoke serves its page and API on separate localhost origins to exercise preflights, signed uploads and response-header visibility in a real browser.
The --json envelope, error codes, exit codes, artifact layout and the shared credential file format are public contracts. Changing any of them is a breaking change; note it in CHANGELOG.md.
MIT © DeckFlow
FAQs
Parse any document into an agent-operable representation. Parse once, convert repeatedly: PDF, PPTX, DOCX, Keynote and URLs into durable IR artifacts and Markdown.
The npm package @deckflow/deckparse receives a total of 84 weekly downloads. As such, @deckflow/deckparse popularity was classified as not popular.
We found that @deckflow/deckparse demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.

Company News
Socket is joining the OpenJS Security Stewardship Program to fund Node.js vulnerability research, maintainer remediation, and security releases.

Security News
Two compromised GitHub Actions were re-enabled with malicious tags intact, exposing thousands of downstream repositories to Mini Shai-Hulud.

Research
/Security News
A malicious Firefox extension fetches its payload after installation to evade detection, steal Google session cookies, and automate account takeover.