Workspaces

Navigate tools

nace locate, nace read-file and nace run-sql are the tools the document service's own search agent works with, for your own code agent: locate names the pages and tables that hold a piece of information, read-file reads them and run-sql queries the tables. For questions about the workspace as a whole, nace folder-metadata lists its folders and files and nace catalog queries the fields ingestion extracted from every document. Each answers at once, from the files in a workspace that are ingested, and prints a readable rendering of the document service's response (--json prints it whole). They are free; locates are limited to 150 per account every 10 minutes, and file reads, SQL queries, folder listings and catalog queries together to 600. Past that, a command exits 1 with 429 rate_limited, and stderr says when to run it again.

Each command works on one workspace: --workspace ID, else $NACE_WORKSPACE_ID, else the one nace workspace-use saved, else your account's only workspace. With none of these and several workspaces, it exits 2 with no workspace and lists them, so pick one first: nace workspaces lists each workspace's ID and name (nace workspace-create NAME makes one), and nace workspace-use ID saves it. See Choose a workspace.

To give a code agent the loop that uses them, install the agent skill. See Navigate tools for the routes.

A call that times out keeps running on the document service, so each command retries under the same key for up to 15 minutes and prints the first call's answer. The first locate after a workspace's files change can take a minute or more.

Locate

nace locate "monthly base rent in the first lease year" \
  --question "What is the monthly base rent for unit 12 in the first lease year?"
# locate id: loc_7f3a2c1d (new: add --locate-id loc_7f3a2c1d to later locates and reads for this question)
# Located for: monthly base rent in the first lease year
#
# [1] leases/unit-12.pdf — page 2 (agreement_1; score 1.00)  → `nace read-file leases/unit-12.pdf --pages 2 --locate-id loc_7f3a2c1d`
#     # Article 3. Rent and security deposit  3.1 Base Rent. Tenant will pay Base Rent of $9,600.00 per month ...
# ...
nace read-file leases/unit-12.pdf --pages 2 --locate-id loc_7f3a2c1d
nace locate --pointer "security deposit amount" --locate-id loc_7f3a2c1d
# locate id: loc_7f3a2c1d (leaving out the 12 pieces it already showed and the 1 reads made under it)

nace locate NEED prints its locate id on the first line, then the answer's text as the document service writes it: each page or span of lines, best first, with its score, the read that opens it and its text (the best pages in full, the rest by their opening lines), then the tables it rated, with their sql names and the columns to look at. Every command it names is written as nace runs it (nace read-file ... --locate-id ID, nace run-sql), so it runs as printed; the raw response's text uses service-specific command names and omits the locate id. See Locate information for the response; --json prints it whole, and the locate id line on stderr.

When the answer needs every file of a kind, such as a total over each invoice, nace locate --all "invoices from Acme in 2026" rates every file of that kind and lists the members by path, to read each. It is not a search: to find a document or a value, locate it without --all. When the budget ran out before rating every likely file, it says so: narrow the need to a folder, kind or period.

FlagWhat it does
--workspace IDThe workspace to locate in. See Choose a workspace.
-k NHow many pages to name, at most 24 (default 12).
--allThe need names a kind of file and every one is wanted (each invoice, every statement): the navigator rates each file of that kind and lists the members.
--question QUESTIONThe task's whole question, kept for later locates under the same locate id. Default: the id's, else the need.
--locate-id IDContinue this question's locate id, as an earlier locate printed it: leave out what it already showed or read. Default: start a new one.
--path-prefix, --prefix PATHOnly files under this folder.
--path POnly this file, by its path. Repeatable; with --path-prefix, both.
--pointerName every page by its opening lines only (default: the best pages in full). A task's later locates pass it, so page text does not pile up.

Locate ID

A locate ID holds what one question's search has already covered. Pass it to the later locates and reads for the same question, and you get two things:

  • Something new each time. A later locate leaves out the pages it already showed you and the ones you read, and says how many it left out.
  • Fewer dead ends. The locator is told which pages you read without finding the answer, so it looks elsewhere.

nace locate without --locate-id starts a new one and prints it first (locate id: loc_…); each task's first locate starts its own, so a new task, a parallel one or a sub-agent never inherits another's. Pass --locate-id loc_… to every later nace locate and nace read-file for the same question: the reads a locate names already carry it. A later locate keeps the first locate's --question. nace run-sql takes no locate id: tables are never left out. Without the flag nothing is left out, and each locate runs as a first one.

  • The id is kept on this machine, in a file beside the config file (under locate/ in ~/.nace), and is gone after 6 hours unused. An unknown or expired id, or one from another workspace, exits 2 before any request: start a new one.
  • Over 1,000 offered or read pieces, a locate exits 1 with 422 invalid_request: start a new locate id.

Read a file

nace read-file leases/unit-12.pdf --pages 2
nace read-file reports/notes.md --lines 120-180
nace read-file finance/tb.xlsx --component "Trial Balance" --lines 1-24
nace read-file a.pdf b.pdf --pages 1            # each under a `==> path <==` header

nace read-file PATH prints the file's text on stdout, and one footer line on stderr: read <path>, then, when they apply, | lines <a>-<b> of <n>, | pages <ranges>, | components: <names>, | omitted: <names> and | TRUNCATED (raise --max-chars, or scope with --component/--pages). When a span of lines starts inside a table, the table's header comes first, as [table lines <first>-<last>] <first>: <header>. Several paths are read together and printed in order, each under ==> <path> <==, with a blank line between; one that fails prints error: <path>: <status> [<code>] <message> on stderr, the rest still print, and the command exits 1. With --json, several paths print one JSON array of the reads that succeeded. A file that isn't ingested yet exits 1 with 409 file_not_ingested. See Read a file.

With --locate-id ID, a read that finished is recorded under that locate id, so its next nace locate leaves it out; without it, nothing is recorded.

FlagWhat it does
--workspace IDThe workspace to read from. See Choose a workspace.
--component COMPONENTOne tab or section.
--pages SPEC1-based pages, such as 3 or 1-5,8. Not for spreadsheets.
--lines A-BOnly these lines of what the read returns: A-B, A- (to the end), -B or A, 1-based and inclusive. It reaches text past --max-chars; the footer gives the line count.
--max-chars NThe most characters to return. Above 1,000,000 it is sent as 1,000,000.
--locate-id IDRecord this read under a locate id: its later locates leave it out.

Run a SQL query

nace run-sql "SELECT \"Account name\", Debit FROM tb_2026_09_trial_balance WHERE Debit > 10000"
# result table res_45eb9a76727d — 4 rows
#   Account name (VARCHAR) | Debit (DOUBLE)
#   {"Account name": "Cash - Fernhollow Bank operating", "Debit": "61422.18"}
#   ...
# note: 'res_45eb9a76727d' is a registered table — join or page it in your next run-sql call.
# sources: finance/tb.xlsx
nace run-sql "SELECT sum(Debit) FROM res_45eb9a76727d"

nace run-sql SQL runs one read-only SELECT (DuckDB dialect) over the workspace's tables and prints the result as result table <handle> — <n> rows, with , showing only the first <k> (preview cap; the full result is behind the handle) when the preview is cut and (duplicate — served from the stored result) when an identical query answered it; then the columns with their types, one JSON object per preview row, a note that the handle is a table your next query may read, and sources:. Table names come from nace locate; a query naming an unknown table exits 1 with 422 invalid_request, and the message lists the tables. --json adds a download link to the whole result as a Parquet file. See Run a SQL query.

FlagWhat it does
--workspace IDThe workspace to query. See Choose a workspace.

Describe a folder

nace workspace-use <workspace_id>                      # once: the workspace the commands below describe
nace folder-metadata                                  # the root: counts, categories, subfolders, a page of files
nace folder-metadata invoices --recursive --kind document
nace folder-metadata --status failed                  # what did not ingest
nace folder-metadata --names-only                     # every path in the workspace, one per line

nace folder-metadata [DIR...] describes each folder, / by default: how many files it holds, their counts per category and ingestion status, one line per subfolder, and one page of its files with their status, size, category and kind. It covers the folder's own files unless a narrow (--category, --status, --kind, --name-contains) or --recursive is given. --names-only prints only the paths, every one in scope over as many pages as it takes, up to 10,000.

FlagWhat it does
--workspace IDThe workspace to describe. See Choose a workspace.
--recursiveThe whole subtree. Not with --no-recursive.
--no-recursiveThe folder's own files only, even when narrowed. Not with --recursive.
--category CATEGORYOnly files in this category, as an earlier listing names it.
--status STATUSOnly files in this ingestion status, such as failed.
--kind KINDOnly files of this kind: document, table or media.
--name-contains TEXTOnly files whose path contains this text, case-insensitively.
--page-size NFiles listed per page, up to 500. Default: 100.
--start-after PATHResume the listing after this path, the last one the previous page printed. One folder only.
--names-onlyEvery path in scope, one per line, over all pages, and nothing else on stdout. When none match, stdout is empty and stderr says no files; a list cut short says so on stderr too.

Query the metadata catalog

nace workspace-use <workspace_id>   # once: the workspace the commands below query
nace catalog
# invoice (74 records): ...
#   total_amount (money): ...
nace catalog "SELECT source_path, page_start, total_amount FROM invoice WHERE total_amount > 50000"
# 3 rows
#   source_path | page_start | total_amount
#   {"source_path": "files/7263950-IN/invoice.pdf", "page_start": 1, "total_amount": 51200.0}
#   ...

nace catalog prints the fields ingestion extracted from every document as tables: catalog_document, with a row per document section or tab, and one table per document type the workspace holds (invoice, contract, ...) with its typed fields, each with its record count, followed by the types that have no records here. nace catalog SQL runs one read-only SELECT (DuckDB dialect) over them and prints <n> rows, the columns, then one JSON object per row; at most 200 rows come back, and a longer result adds , cut: narrow the WHERE or page with LIMIT/OFFSET. Cells over 300 characters are cut in the text; --json prints them whole.

FlagWhat it does
--workspace IDThe workspace to query. See Choose a workspace.

Agent skill

nace skill install --agent claude-code     # write both skills to ~/.claude/skills
nace skill drex-search                     # print one
nace skill drex-workspace

nace skill [NAME] prints an agent skill that ships with the CLI, so it always matches the commands you have installed. NAME is drex-search, the default: the locate, read-file and run-sql loop, plus folder-metadata and catalog for questions about the workspace as a whole; or drex-workspace: create a workspace, upload and ingest, check it, and save it for later sessions. Neither sends a request or needs a key. The skill's frontmatter carries the CLI's version as metadata.nace-cli-version.

nace skill install [NAME...] --agent AGENT writes each skill, both by default, to <NAME>/SKILL.md in the agent's skills folder, and prints wrote <path> on stderr, or up to date: <path> when the file already matches. Run it again after you upgrade the CLI. See Agent skills for each agent's folder.

FlagWhat it does
--agent {claude-code,codex,cursor,pi,hermes,agents}Required. The agent whose skills folder to write to; agents is the Agent Skills folder, ~/.agents/skills, that other agents read.
--projectWrite to the project's folder, under the current directory, instead of your user folder.

When a copy the CLI would write, in an agent's user folder or the current directory's project folder, is older than the CLI, nace locate, nace read-file, nace run-sql, nace folder-metadata and nace catalog print one line on stderr naming it and the nace skill install command that updates it. Until some agent has both skills installed, nace workspace-create and nace workspace-use print one line on stderr suggesting nace skill install --agent AGENT.

On this page