Skip to content

Logs ​

Every service's output goes into one stream, each line labelled with its service:

13:53:32 [api     ] listening on 3001
13:53:32 [web     ] VITE ready in 431 ms
13:53:33 [worker  ] [INFO] job picked up
13:53:33 [worker  ]   id: 42

Every label is padded to the longest one the session can show (its services, its infra services and stackctl's own), so every line's text starts in one column. A service added mid-session widens them all.

stderr lines are red. In the terminal UI, f filters the stream by any text, ignoring case and accents: type a service's name to see only that service.

JSON logs are formatted for you ​

Plain text passes through untouched. A line that is a JSON log (Go's slog, pino, winston) is shown as a colored [LEVEL] message, with its other fields listed below:

{"time":"2026-07-13T13:53:32Z","level":"INFO","msg":"listening","port":3002}
[INFO] listening
  time: 2026-07-13T13:53:32Z
  port: 3002

So a service can log JSON in every environment, with no NODE_ENV branch in its logger. There is nothing to configure. To map numeric levels, hide a field or format non-JSON output, see the logs options.

Timestamps ​

Each line is stamped with the local time. The terminal UI adds the date only when two days are on screen together. Turn the stamps off on screen with logs.timestamps. The log file always has them.

stackctl's own lines ​

stackctl writes to the same stream, in gold, under labels of its own:

LabelWhat it logs
[stackctl]The session: its mode, why each dependency runs, startup failures, shutting down.
[control]Commands received over the control API.
[infra]Docker Compose's output.
[infra:<service>]One infra service's output, its callbacks included.
16:41:20 [stackctl] [INFO] api: runtime dep of web
16:41:22 [control ] [INFO] restart
16:41:22 [control ]   service: api

Log files ​

Every session writes its whole stream to a file, timestamps included, colors removed:

node_modules/.stackctl/modes/<mode>/logs/<timestamp>-<pid>-<n>.log

Each session gets a new file, and so does each sctl exec and sctl run. Earlier files are kept. --log-dir <dir> writes them somewhere else.

Reading a session's log ​

From another terminal, without disturbing the session:

bash
sctl logs               # print the current session's log
sctl logs -f            # print it, then follow new lines
sctl logs --path        # print only the file's path
sctl logs --mode test   # the test session's

Ctrl+C stops the following, never the session. With no session running, it shows the last one's log. See sctl logs.

Released under the MIT License.