Constructdocs
section · guides

Use the inbox

Drop a file, watch the daemon classify it into R&D triage, drive the queue.

3 min read·guides / cookbook / use-the-inbox

The inbox watcher monitors one or more directories and automatically ingests new files into your knowledge base. It runs every two minutes as part of the embed daemon.

Drop a fileinbox/ any supported formatEmbed daemondetects within ~1s extracts textclassifyRdIntakeClassifyfilename routing rules + R&D triageKnowledge store.construct/knowledge/<subdir>/.construct/intake/Triage packetowner · chain · confidence

Default inbox directory

The single canonical drop zone is inbox/ at the project root (ADR-0045 §C):

inbox/

Drop any file there and it will be processed within two minutes.

Drop convention (atomic handoff). To avoid the watcher reading a half-written file, assemble it under inbox/.staging/ and then atomically rename it into inbox/. The watcher ignores dotfiles and inbox/.staging/, and skips any top-level file whose size is still changing — so a partial drop is never consumed.

inbox/ is the only drop zone. There is no .construct/inbox/ or docs/intake/ zone — drop everything into inbox/.

Add extra directories

Set CX_INBOX_DIRS to a colon-separated list of additional paths:

# In ~/.config/construct/config.env
CX_INBOX_DIRS=/Users/you/Downloads/construct-inbox:/Volumes/shared/team-docs

All directories are watched in addition to inbox/: you cannot disable the default.

Supported file types

The inbox watcher accepts any file that can produce extractable text:

  • Plain text / Code: .md, .txt, .rst, .adoc, .json, .yaml, .yml, .toml, .js, .mjs, .ts, .tsx, .jsx, .py, .go, .rs, .sh, .bash, .html, .css, .csv, .tsv, .xml, .env, .conf, .ini, .sql, .log
  • Transcripts: .vtt (WebVTT), .srt (SubRip), .lrc (lyrics), .transcript: Zoom, Teams, meeting recordings
  • Office documents (via docling): .docx, .xlsx, .pptx, .odt, .ods
  • Rich text (via docling): .doc, .rtf
  • Legacy iWork/Office (via docling): .xls, .ppt, .pages, .numbers, .key
  • PDF (via docling, layout-aware + built-in OCR): .pdf
  • Audio / Video (via whisper.cpp, brew install whisper-cpp): .mp3, .wav, .m4a, .mp4, .mov, .avi, .mkv, .flac, .ogg, .webm, .m4v

This includes things like meeting notes, exports, specs, ADR drafts, research notes, recordings, and uploaded documents, as long as the file type is extractable.

Extraction backends. The default adapter strategy extracts plain PDF and DOCX through Node-native optional dependencies (unpdf, mammoth), so everyday ingest needs no Python and no system extractor on PATH; when those deps are absent it degrades to the system extractors (pdftotext, textutil). High-fidelity extraction — layout-aware tables, built-in OCR for scanned PDFs, legacy Office — runs through a docling Python sidecar provisioned automatically via uv; select it per ingest with --with-docling (or the docling-remote strategy). Audio/video routes through whisper.

Binary files that cannot be read as text are skipped with a warning observation.

50 MB hard cap: files above this are skipped silently.

How routing works

Files are routed to a typed subdirectory of .construct/knowledge/ based on filename patterns:

Filename patternKnowledge subdirectory
adr-NNN-*decisions/
*runbook*, *how-to*how-tos/
*customer*, *feedback*external/
*postmortem*, *incident*internal/
Everything elseinternal/ (default)

Avoid re-processing

The watcher tracks which files it has already seen by recording a content hash. Editing a file causes it to be re-ingested. Renaming a file also triggers re-ingestion.

Check what was ingested

construct knowledge index

Or use the dashboard Knowledge tab.

Docs lane promotion

When a file lands in inbox/, Construct ingests it into .construct/knowledge/ and observations as usual. If the repo already has a matching docs lane such as docs/notes/meetings/, templates/docs/prds/, or templates/docs/rfcs/, the watcher also writes a promoted markdown copy into that lane for review and incorporation.

R&D triage on every file

After ingestion, the daemon classifies each file via classifyRdIntake and writes a triage packet to .construct/intake/pending/<id>.json. Inspect and drive the queue with construct intake list / show / done / skip / reopen. For non-trivial signals, generate a task graph with construct graph from-intake <id>.

A full walkthrough of the triage taxonomy (intake types, R&D stages, recommended chains, recommended actions) lives in Concepts: Intake and triage. Session-start surfaces the most recent pending packets with a one-line triage summary per entry.