| name | trellis |
| description | Control the Trellis development environment - check service status, view logs, restart services, run workflows, and switch worktrees |
Trellis Development Environment Control
Use trellis-ctl to interact with the running Trellis instance. It auto-discovers the API URL by walking up from the current directory looking for trellis.hjson. If server.public_url is set, it's used verbatim; otherwise the URL is built from server.host, server.port, and server.tls_cert/tls_key. Set server.public_url when bind address ≠ connect address — for example, binding to a Tailscale IP with a cert issued for the Tailscale hostname. In Trellis-managed terminal sessions, TRELLIS_API is set automatically (using the same resolution) and takes precedence over the config file. You can also pass -config <path> or set TRELLIS_CONFIG to point at a specific config file.
Important: Always use the -json flag for structured output that's easier to parse:
trellis-ctl -json status
trellis-ctl -json logs backend -n 50
trellis-ctl -json workflow list
Available Commands
Service Status
Check the status of all services or a specific service:
trellis-ctl status
trellis-ctl status backend
States: running, stopped, crashed, starting, stopping
Service Logs
View logs from a service or log viewer:
trellis-ctl logs backend
trellis-ctl logs backend -n 50
trellis-ctl logs backend -f
trellis-ctl logs -viewer nginx
trellis-ctl logs -list
Service vs Log Viewer:
trellis-ctl logs <service> - Local service logs. If the service has logging.parser configured, logs are parsed for filtering by level/field.
trellis-ctl logs -viewer <name> - Remote log viewers (SSH, file, command sources). Always parsed.
Filtering Options
trellis-ctl logs backend -since 1h
trellis-ctl logs backend -since 30m
trellis-ctl logs backend -since 6:30am
trellis-ctl logs backend -since 14:00
trellis-ctl logs backend -until 7:00am
trellis-ctl logs backend -level error
trellis-ctl logs backend -level warn+
trellis-ctl logs backend -level warn,error
trellis-ctl logs backend -grep "timeout"
trellis-ctl logs backend -grep "(?i)error"
trellis-ctl logs backend -field host=prod1
trellis-ctl logs backend -field status=5*
trellis-ctl logs backend -grep "error" -B 5
trellis-ctl logs backend -grep "error" -A 10
trellis-ctl logs backend -grep "error" -C 3
trellis-ctl logs -viewer api-logs -grep "started" -B 10 -since 6:00am -until 7:00am
Output Formats
trellis-ctl logs backend -json
trellis-ctl logs backend -jsonl
trellis-ctl logs backend -csv
trellis-ctl logs backend -raw
trellis-ctl logs backend -format '{{.timestamp}} {{.level}}: {{.message}}'
Statistics and Management
trellis-ctl logs backend -stats
trellis-ctl logs backend -clear
trellis-ctl logs backend -open
trellis-ctl logs backend -url
When debugging crashes, look for:
- Panic traces (goroutine stack)
- Fatal errors
- The last error message before exit
Service Control
Start, stop, or restart services:
trellis-ctl start backend
trellis-ctl stop backend
trellis-ctl restart backend
Workflows
List, describe, and run workflows:
trellis-ctl workflow list
trellis-ctl workflow describe <id>
trellis-ctl workflow run <id>
trellis-ctl workflow run <id> --arg=value
trellis-ctl workflow status <id>
Discovering and running workflows with inputs:
trellis-ctl workflow describe find-email
trellis-ctl workflow run find-email --date=2024-01-15 --id=12345
Workflow inputs are validated server-side against configured patterns and allowed values. Invalid inputs return an error without executing the workflow.
Worktrees
List and switch git worktrees:
trellis-ctl worktree list
trellis-ctl worktree activate main
Switching worktrees will:
- Stop all services
- Re-expand config templates with new paths
- Restart all services
Events
View recent system events:
trellis-ctl events
trellis-ctl events -n 20
Notifications
Send notification events to alert the user:
trellis-ctl notify "Task completed"
trellis-ctl notify "Need API credentials" -type blocked
trellis-ctl notify "Build failed" -type error
When to notify:
done - Task completed successfully, user can review the results
blocked - Stuck and need user input to continue
error - Something failed that needs attention
Users can subscribe to these events via WebSocket (/api/v1/events/ws?pattern=notify.*) or view them with trellis-ctl events.
Crash Reports
View crash reports that are automatically captured when services fail:
trellis-ctl crash list
trellis-ctl crash newest
trellis-ctl crash <id>
trellis-ctl crash delete <id>
trellis-ctl crash clear
Each crash report contains:
- Service name and exit code
- Trace ID of the request that caused the crash (if detected)
- Worktree context (name, branch, path)
- Log entries from all services filtered by the trace ID
- Summary statistics (entry count by source and level)
The JSON output includes an entries array with parsed log entries:
{
"id": "20260117-143201.234",
"service": "backend",
"exit_code": 2,
"trace_id": "req-abc123",
"entries": [
{
"timestamp": "2026-01-17T14:32:01Z",
"source": "backend",
"level": "error",
"message": "panic: nil pointer dereference",
"fields": {...},
"raw": "..."
}
]
}
Distributed Tracing
Two separate commands (note the hyphen difference):
trace - Execute a new trace search
trace-report - View/manage saved trace reports
Execute a Trace Search (trace)
trellis-ctl -json trace <id> <group>
trellis-ctl -json trace abc123 api-flow
trellis-ctl -json trace abc123 api-flow -since 1h
trellis-ctl -json trace abc123 api-flow -since 10am -until 11am
The JSON output includes an entries array with all matching log lines:
{
"name": "trace-abc123-20260117-103045",
"trace_id": "abc123",
"status": "completed",
"entries": [
{
"timestamp": "2026-01-17T10:30:01Z",
"source": "nginx-logs",
"level": "info",
"message": "GET /api/groups/123 200",
"fields": {"request_id": "abc123", "path": "/api/groups/123"},
"raw": "..."
}
]
}
View Saved Trace Reports (trace-report)
trellis-ctl -json trace-report <name>
trellis-ctl -json trace-report -list
trellis-ctl -json trace-report -groups
trellis-ctl trace-report -delete <name>
Time input formats: 1h, 30m (duration), 6:00am, 14:30 (clock time), 2025-01-10 (date), 2025-01-10 6:00am (date+time), today, yesterday, now
Date ranges are inclusive: When using a date without a time, start means beginning of day (00:00:00) and end means end of day (23:59:59). To search only one day, use the same date for both -since and -until.
Trace groups are configured in trellis.hjson under trace_groups, defining which log viewers to search together. Example:
trace_groups: [
{ name: "api-flow", log_viewers: ["nginx-logs", "api-logs", "db-logs"] }
]
Service Tracing (Dev Environment)
When services have logging.parser configured (directly or via logging_defaults), a services trace group is auto-generated that searches all service log buffers:
trellis-ctl -json trace "req-123" services -since 1h
trellis-ctl -json trace-report -groups
This requires no configuration — svc:<name> log viewers are created automatically from each service's in-memory ring buffer.
Common Workflows
After Making Code Changes
- Build the code (your normal build process)
- Check if service auto-restarted:
trellis-ctl status
- If crashed, check logs:
trellis-ctl logs <service> -n 100
Debugging a Crash
- Check service status:
trellis-ctl status <service>
- View crash report:
trellis-ctl -json crash newest - includes trace ID and filtered logs
- View recent logs:
trellis-ctl logs <service> -n 200
- Check AI context file (if configured) for crash details and trace info
- Fix the issue and rebuild
- Verify:
trellis-ctl status <service>
Switching to a Different Branch
- List worktrees:
trellis-ctl worktree list
- Activate:
trellis-ctl worktree activate <name>
- Wait for services to restart
- Verify:
trellis-ctl status
Debugging Across Dev Services
When a request touches multiple services locally:
trellis-ctl -json trace "req-abc123" services -since 1h
Investigating a Production Error
When asked to investigate an error seen in production logs:
-
Run a trace to gather all related log entries:
trellis-ctl -json trace <trace_id> <group> -since <time>
Example: trellis-ctl -json trace XXXX-XXXX-12345 web -since 10am
-
Parse the JSON output - The trace returns entries with:
timestamp - When it occurred
source - Which log viewer (nginx, api, db, etc.)
level - Log level (error, warn, info)
message - The log message
fields - Parsed fields (request path, user ID, etc.)
raw - Original log line
-
Analyze the request flow - Entries are sorted by timestamp, showing the request path through the system. Look for:
- The initial request (often from nginx/load balancer)
- Application processing steps
- Database queries
- The error and where it occurred
- Any context from surrounding log lines
-
Read the relevant source code - Use file paths and function names from the logs to find the code that generated the error.
-
Notify when done:
trellis-ctl notify "Investigation complete - found the issue in handler.go:142"
Example investigation:
trellis-ctl -json trace req-abc123 web -since 9:30am -until 10:30am
trellis-ctl notify "Found issue: group lookup fails when ID contains special chars"
Querying Production Data
When you need to fetch data from production databases to understand an issue:
-
Discover available workflows that can query production:
trellis-ctl workflow list
trellis-ctl workflow describe <workflow-id>
-
Run the workflow with validated inputs:
trellis-ctl -json workflow run db-fetch --table=users --id=12345
Workflow inputs are validated against configured patterns and allowed values before execution, ensuring safe queries. For example, a workflow configured with:
allowed_values: ["users", "groups", "messages"] for table
pattern: "^[0-9]+$" for ID
Will reject attempts to query unauthorized tables or pass malformed IDs.
Example: Investigating a user issue
trellis-ctl -json trace req-abc123 api-flow -since 1h
trellis-ctl -json workflow run db-fetch --table=users --id=12345
trellis-ctl notify "User 12345 has invalid subscription_tier causing the error"