helix logs reads the execution logs of your deployed project without opening the dashboard (v1.7.0 and later). On its own it lists recent executions, newest first, with flags to search them, keep only failures, or narrow the time window. helix logs get <executionId> prints one execution in full: the request, every operation it ran, your ctx.log lines, and any error.
Both commands read the platform, not your local dev server. What helix dev prints stays in that terminal, and what a deployed function logs never reaches it, so pick the one that matches where the request ran.
Before you start
The commands need a deployed project: a projectId and a workspaceId in the config file, which a first helix deploy writes for you. Without them the command stops before it asks for a login and points you at helix deploy, helix project set, or helix workspace select.
Both commands accept --config <path> to read another target’s project, for example helix logs --config helix.production.config.ts --errors. The HELIX_CONFIG environment variable has the same effect; the flag wins when both are set.
helix logs list
helix logs
helix logs list
The two forms are the same command. Each row is one execution, meaning one invocation of a function: an HTTP request that reached the app, or one run of a scheduled job. The default page is the 20 most recent executions from the last seven days.
| Flag | What it does |
|---|---|
--search <text> | Keep only executions whose route, status, actor, trace ID, or error text contains this text. The match is literal and case-sensitive, and it does not look inside individual log lines |
--since <when> | Keep only executions started at or after this time. Takes an ISO timestamp (2026-01-31T12:00:00Z) or how long ago (45s, 15m, 2h, 3d). Default: seven days ago |
--until <when> | Keep only executions started at or before this time, in the same formats. --since must not be later than --until |
--errors | Keep only failed executions |
--limit <n> | Executions per page, from 1 to 100. Default 20 |
--cursor <cursor> | Continue from the cursor printed under the previous page |
--json | Print the page as JSON instead of a table |
--config <path> | Config file to read the project from, instead of ./helix.config.ts |
helix logs --errors --since 1h # what failed in the last hour?
helix logs --search "POST /api/reports" # every call to one route this week
helix logs --since 2026-10-01 --until 2026-10-02 --limit 100
The table has one row per execution, with the error summary on a second line under a failed one, then the count and the command for the next page:
Started Status Duration Trigger Route / job Execution ID
──────────────────────────────────────────────────────────────────────────────────────
2026-10-06T09:41:12.408Z error 1.2s http POST /api/reports 0a8c1f6e-9b2d-4c3a-8e1f-1a2b3c4d5e6f
↳ TypeError: Cannot read properties of undefined (reading 'records')
2026-10-06T09:40:58.113Z success 312ms http GET /api/reports 7c1e2d3b-4a5f-4b6c-9d7e-8f9a0b1c2d3e
2026-10-06T09:40:00.021Z success 2.4s schedule nightly-sync 3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7
3 executions (newest first). Details: helix logs get <executionId>
More: helix logs list --cursor eyJzdGFydGVkQXQiOiIyMDI2LTEwLTA2VDA5OjQwOjAwLjAyMVoifQ
Status is success, error, cancelled, or timeout. The trigger is http for a request and schedule for a job run, and the last column is the ID to pass to helix logs get. When nothing matches, the command says so and suggests widening --since or dropping a filter.
helix logs get
helix logs get <executionId>
Prints one execution in full. The ID is the UUID from the last column of helix logs list; the command rejects anything else before it contacts the platform. It accepts --json and --config <path> with the same meaning as on list.
The output starts with a header, then the tree of operations the execution ran, in the order they happened. Which operations appear depends on what the function did: an HTTP request has an http operation under the function, a scheduled run does not, and a function with no ctx.log calls shows no log lines.
➜ Execution ID: 0a8c1f6e-9b2d-4c3a-8e1f-1a2b3c4d5e6f
➜ Status: error
➜ Started: 2026-10-06T09:41:12.408Z
➜ Duration: 1.2s
➜ Trigger: http POST /api/reports
➜ Actor: user alice@acme.com
➜ Deployment ID: 4f2b8c1e-9d3a-4e77-b5c0-6a1f8e2d4b90
➜ Trace ID: 9b3c7d1e2f4a5b6c7d8e9f0a1b2c3d4e
➜ Error: TypeError: Cannot read properties of undefined (reading 'records')
Operations:
• function POST /api/reports — error (1.2s)
input: {"range":"last-7-days"}
• http POST /api/reports → 500 (1.2s)
request: {"range":"last-7-days"}
response: {"error":"Internal Server Error"}
· [INFO] Building report
{"range":"last-7-days"}
• externalApi GET salesforce → 401 (250ms)
auth: salesforce_prod
response: {"error":"INVALID_SESSION_ID"}
error: HTTPError: Response code 401 (Unauthorized)
· [ERROR] Report failed
{"stage":"fetch"}
| Operation | What the line shows |
|---|---|
function | The invocation itself, with its status, duration, and previews of the input and the output |
http | The inbound request: method, route, response status, and previews of the request and response |
externalApi | An outbound call made with ctx.http: service, method, response status, the auth alias used, and previews of the request and response |
auth | A credential lookup, by alias |
log | One ctx.log call, marked with ·: its level, message, and the metadata object you passed |
Previews are cut at 200 characters so a large payload cannot flood the terminal. An operation that failed carries its error type, message, and up to five lines of stack trace. If the platform capped the number of operations it returned, a warning under the tree says the tree is incomplete.
JSON output
--json on either command prints the same data the table and tree are built from, for scripts and agents. The list page carries executions, pageInfo, and nextCursor, which is null on the last page. Each execution has these fields:
| Field | Meaning |
|---|---|
executionId | The ID to pass to helix logs get |
traceId | The trace this execution belongs to |
deploymentId | The deployment that served it |
triggerType | http or schedule |
routeOrJob | The route for a request (POST /api/reports), the job name for a schedule run |
status | success, error, cancelled, or timeout |
startedAt | ISO timestamp |
durationMs | Wall-clock duration in milliseconds |
actor | Who initiated it: a type, and where known an id, name, and email |
errorSummary | Present on a failed execution |
helix logs get --json adds operations, a flat array linked by parentId, where each entry has an id, type, name, status, durationMs, a payload object whose shape depends on the type, and an error when one was recorded. It also adds operationsTruncated, which is true when the tree was capped. Reading the JSON is how to see a payload the preview cut short.
From a coding agent
The CLI’s MCP server offers the same two reads as tools, so an agent working without a terminal can answer “what failed in production?” and debug one request. tray_list_executions takes search, since, until, errorsOnly, limit, and cursor, and returns the list page; pass its nextCursor back as cursor for older executions. tray_get_execution takes an executionId and returns the execution with its operations. Both use the saved login without prompting. The scaffolded project instructions already point the agent at helix logs first and these tools when no terminal is available. See Building with Claude Code.
Errors
| Message | What to do |
|---|---|
No projectId in helix.config.ts | Deploy once with helix deploy, or helix project set <uuid> for a project that already exists |
No workspaceId in helix.config.ts | Run helix workspace select, or helix workspace set <id> if you know it |
Project ... was not found in workspace ... | The config file’s projectId and workspaceId don’t match. Check them, or pass --config for the target you meant |
Execution ... was not found in project ... | The ID is wrong, or the execution is older than the retention window. Check it with helix logs list |
Invalid --since value ... | Use an ISO timestamp or a duration ago such as 15m, 2h, or 3d |