# Logs commands

> Read a deployed project's logs from the terminal with helix logs, listing and searching recent executions and opening one execution in full.

`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

```bash
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` |

```bash
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.

:::tip{title="Finding a log message"}
`--search` matches the execution's route, status, actor, trace ID, and error text, not the text of your `ctx.log` lines. To find a message, narrow the list by route, time window, or `--errors`, then open the execution.
:::

## helix logs get

```bash
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](/documentation/getting-started/building-with-claude/).

## 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` |

---

Canonical: https://helix.tray.ai/documentation/reference/cli/logs/
Any link on this page is available as markdown by appending .md to its URL.
Full corpus: https://helix.tray.ai/documentation/llms-full.txt