jobs
Manages background ingest and import jobs within the Shared Sandbox. When ingest or import run is launched with --background, a job is created that runs asynchronously via a detached worker process. The jobs command provides operators with visibility into job lifecycle, progress, and per-file diagnostics.
Job records are stored durably in the local database. Workers emit periodic heartbeats so that stale jobs (whose worker process died) can be detected and recovered.
Usage
unsterwerx jobs <SUBCOMMAND>
Subcommands
| Subcommand | Description |
|---|---|
list | List recent jobs |
status | Show job details and progress |
stop | Request a running or paused job to stop cleanly |
pause | Request a running job to pause at the next safe checkpoint |
resume | Resume a paused job |
errors | Show error diagnostics for a job |
logs | Show all diagnostics (warnings and errors) for a job |
jobs list
Lists recent jobs with their type, status, progress, and queue time. Stale runs are automatically refreshed before listing.
unsterwerx jobs list [OPTIONS]
Options
| Option | Type | Default | Description |
|---|---|---|---|
--status | string | Filter by status: queued, running, stopping, paused, completed, failed, stopped, stale | |
--limit | integer | 20 | Maximum number of jobs to show |
--json | flag | Output as JSON via emit_json envelope |
Example
unsterwerx jobs list
ID Type Status Path Progress Queued At
------------------------------------------------------------------------------------------
a1b2c3d4 ingest completed .../path/to/documents 2873/2873 2026-03-31 14:25:52
e5f6a7b8 import running .../Downloads/chatgpt-export 142/580 2026-03-31 15:01:03
unsterwerx jobs list --status failed
unsterwerx jobs list --json
jobs status
Shows detailed information about a single job including timestamps, progress counters, associated import batches, and worker log path.
unsterwerx jobs status [OPTIONS] <ID>
Arguments
| Argument | Required | Description |
|---|---|---|
ID | Yes | Job ID or unique prefix (see ID prefix lookup) |
Options
| Option | Type | Description |
|---|---|---|
--json | flag | Output as JSON via emit_json envelope |
Example
unsterwerx jobs status a1b2
Job Details
══════════════════════════════════════════════════════════════
ID: a1b2c3d4-5e6f-7890-abcd-ef1234567890
Type: ingest
Mode: background
Status: completed
Input path: /path/to/documents
Source type: local
PID: 48231
Log: /home/operator/.unsterwerx/logs/a1b2c3d4-5e6f-7890-abcd-ef1234567890.log
Spec version: 2
Resume count: 0
Queued at: 2026-03-31 14:25:52
Started at: 2026-03-31 14:25:53
Heartbeat at: 2026-03-31 14:32:41
Completed at: 2026-03-31 14:32:42
Items total: 2873
Items processed: 2873
Items skipped: 0
Items error: 32
Import batches:
2e96772f
══════════════════════════════════════════════════════════════
jobs stop
Requests a running or paused job to stop cleanly. The worker will finish processing the current item and then exit. This is a cooperative signal, not a kill. The job transitions to stopping and then to stopped once the worker acknowledges.
unsterwerx jobs stop [OPTIONS] <ID>
Arguments
| Argument | Required | Description |
|---|---|---|
ID | Yes | Job ID or unique prefix |
Options
| Option | Type | Description |
|---|---|---|
--json | flag | Output as JSON via emit_json envelope |
Example
unsterwerx jobs stop e5f6
Stop requested for job e5f6a7b8 (status: stopping)
A stopped job can later be resumed with ingest --resume <ID> or import run --resume <ID>, which creates a new job that continues from where the stopped job left off.
jobs pause
Requests a running job to pause at the next safe checkpoint. The worker will finish the current item, write a checkpoint, and then wait. The job transitions to paused once the worker acknowledges.
Pause is not supported for retry_errors jobs.
unsterwerx jobs pause [OPTIONS] <ID>
Arguments
| Argument | Required | Description |
|---|---|---|
ID | Yes | Job ID or unique prefix |
Options
| Option | Type | Description |
|---|---|---|
--json | flag | Output as JSON via emit_json envelope |
Example
unsterwerx jobs pause e5f6
Pause requested for job e5f6a7b8 (worker will pause at next checkpoint)
jobs resume
Unpauses a paused job. The worker resumes processing from where it left off. This only works on jobs in paused status.
This is distinct from ingest --resume <ID> or import run --resume <ID>, which create a new job from a stale, stopped, or failed predecessor. jobs resume unpauses an existing paused worker in place.
unsterwerx jobs resume [OPTIONS] <ID>
Arguments
| Argument | Required | Description |
|---|---|---|
ID | Yes | Job ID or unique prefix |
Options
| Option | Type | Description |
|---|---|---|
--json | flag | Output as JSON via emit_json envelope |
Example
unsterwerx jobs resume e5f6
Resumed job e5f6a7b8
jobs errors
Shows error diagnostics recorded during a job. This is a shortcut for jobs logs --level error.
Each diagnostic records the file that caused the error, the NAC processing phase where it occurred, and a human-readable message.
unsterwerx jobs errors [OPTIONS] <ID>
Arguments
| Argument | Required | Description |
|---|---|---|
ID | Yes | Job ID or unique prefix |
Options
| Option | Type | Default | Description |
|---|---|---|---|
--level | string | error | Filter by severity: error, warn, or warning (overridden to error for this subcommand) |
--limit | integer | 100 | Maximum number of diagnostics to show |
--json | flag | Output as JSON via emit_json envelope |
Example
unsterwerx jobs errors a1b2
Diagnostics for job a1b2c3d4 (32 errors, 5 warnings)
Timestamp Level Phase Item Message
------------------------------------------------------------------------------------------
2026-03-31 14:28:01 error parse .../legacy-report.doc unsupported format: doc
2026-03-31 14:29:12 error canonical .../corrupted.pdf pdf extraction failed: no pages
jobs logs
Shows all diagnostics (both warnings and errors) recorded during a job. Diagnostics are recorded unconditionally for every warn/error event during processing, regardless of terminal output suppression.
unsterwerx jobs logs [OPTIONS] <ID>
Arguments
| Argument | Required | Description |
|---|---|---|
ID | Yes | Job ID or unique prefix |
Options
| Option | Type | Default | Description |
|---|---|---|---|
--level | string | Filter by severity: error, warn, or warning | |
--limit | integer | 100 | Maximum number of diagnostics to show |
--json | flag | Output as JSON via emit_json envelope |
Example
unsterwerx jobs logs a1b2 --limit 5
Diagnostics for job a1b2c3d4 (32 errors, 5 warnings)
Timestamp Level Phase Item Message
------------------------------------------------------------------------------------------
2026-03-31 14:27:55 warning parse .../spreadsheet.xlsx truncated to 10000 rows
2026-03-31 14:28:01 error parse .../legacy-report.doc unsupported format: doc
2026-03-31 14:28:33 warning canonical .../big-presentation.pptx slide count exceeds 500
2026-03-31 14:29:12 error canonical .../corrupted.pdf pdf extraction failed: no pages
2026-03-31 14:30:01 warning hash .../empty-file.txt zero-byte file skipped
unsterwerx jobs logs a1b2 --level warn
Key Concepts
Job Lifecycle
Every job follows a state machine with these transitions:
queued → running → completed
→ failed
→ stopping → stopped
→ paused → (resume) → running
→ stopping → stopped
running → stale (worker died without completing)
Terminal states: completed, failed, stopped, stale. No further transitions are possible from these states.
Stale Detection
A background worker writes periodic heartbeats to the database. If a worker process dies unexpectedly (crash, kill signal, system reboot), the job will have no recent heartbeat. When any jobs subcommand runs, stale detection is triggered automatically: jobs whose last heartbeat exceeds the configured threshold (ingest.stale_threshold_secs, default 120) are marked stale.
Stale jobs can be recovered with ingest --resume <ID> or import run --resume <ID>.
ID Prefix Lookup
All subcommands that accept a job ID also accept a unique prefix of that ID. For example, if job a1b2c3d4-5e6f-7890-abcd-ef1234567890 is the only job starting with a1b2, then a1b2 is sufficient:
unsterwerx jobs status a1b2
unsterwerx jobs stop a1b2
unsterwerx jobs errors a1b2
If the prefix is ambiguous (matches multiple jobs), the command returns an error asking for a longer prefix.
Resume vs. Unpause
There are two distinct "resume" operations:
jobs resume <ID>unpauses a paused job in place. The existing worker continues from its checkpoint.ingest --resume <ID>orimport run --resume <ID>creates a new job that picks up where a stopped, failed, or stale predecessor left off. The new job gets a fresh worker process and aresumed_from_idlink to the original.
Diagnostic Phases
Diagnostics record the NAC processing phase where each warning or error occurred:
| Phase | Description |
|---|---|
scan | File discovery and size filtering |
hash | SHA-256 content hashing |
register | Database registration and deduplication |
parse | Format-specific parsing (PDF, DOCX, XLSX, etc.) |
canonical | Canonical markdown extraction |
index | Full-text search indexing |
Notes
- All subcommands support
--jsonfor machine-readable output through theemit_jsonenvelope (same format as other Unsterwerx commands). - Stop and pause are cooperative signals. The worker finishes its current item before responding. There is no forced kill.
- Stop takes precedence over pause. If both are requested, the worker stops.
- Progress counters (
items_total,items_processed,items_skipped,items_error) use debounced writes to avoid excessive database contention. The values shown may lag slightly behind the worker's actual progress. - Background worker logs are written to
~/.unsterwerx/logs/<job-id>.log. Usejobs statusto see the exact log path. - Diagnostic records are retained according to
ingest.diagnostic_retention_days(configurable viaunsterwerx config set).