Candle is a process manager designed for local development, worktrees, and AI agents.
Other process managers (like pm2) are built to run on production backends, but they
can be overcomplicated for local development. Candle aims to be your favorite process
manager for running services locally during development.
A few things that Candle does well:
When running a command like candle start, it will automatically find the settings for
the current directory's project (similar to other tools like git). This helps keep
the interface simple.
This design fits naturally with worktrees - each worktree is already a separate directory, so Candle will launch separate services for separate worktrees.
Candle makes sure that each service is only launched as one process at a time (per directory)
Candle detects when the CLI is being launched by a coding agent, and it will always use
non-blocking responses (where the shell prints something and exits immediately) for
agents, which works better for them. Agents can use candle log ... to fetch & search the
console logs for any running service.
Candle ships with a few other QOL features. One example is candle wait-for-log... which blocks
until a service has printed a certain message (for example, "Now serving on port ..."). This
is useful for CI jobs and integration tests that need to launch a service and wait till it's ready.
Another one is candle list-ports which uses the OS
to detect what ports the service(s) are using, and candle open-browser which uses port
detection to open a web browser to a locally running service.
Supported on macOS and Linux, on both x86_64 and arm64.
With Homebrew:
brew install facetlayer/tap/candle
Run:
curl -fsSL https://raw.githubusercontent.com/facetlayer/candle/main/install.sh | sh
This downloads the latest release for your
platform, and installs into ~/.local/bin. No Rust toolchain needed.
Confirm it worked:
candle --version
If that prints command not found, you may need to add ~/.local/bin to your PATH. Add this
to your shell profile (~/.zshrc, ~/.bashrc) and open a new terminal:
export PATH="$HOME/.local/bin:$PATH"
To install somewhere else, use --bin-dir:
curl -fsSL https://raw.githubusercontent.com/facetlayer/candle/main/install.sh | sudo sh -s -- --bin-dir /usr/local/bin
git clone https://github.com/facetlayer/candle.git
cd candle && ./install-local.sh
If installed with the script:
curl -fsSL https://raw.githubusercontent.com/facetlayer/candle/main/install.sh | sh -s -- --uninstall
If installed with Homebrew:
candle kill-all
brew uninstall candle
Initialize a .candle.json file in the root directory of your project.
candle setup-project
Add services:
candle add-service <service name> --shell <shell command> --root <optional root directory>
Launch it:
candle start # all services
candle start [service name] # one services
List all CLI commands.
candle start
candle start [service name(s)]
Launch the service(s).
If no service names are provided: then launch all services in the project.
If the service(s) are already running then the existing instances are killed first.
If called in interactive mode (see "interactive mode detection" below), start will
then start watching the service and printing console messages. Press Ctrl-C to leave this mode.
Options:
--watch- Force interactive mode: watch logs after starting.--bg- Force non-interactive mode: exit once started.
Alias for candle start.
Similar to start but only starts the service(s) if they are not already running.
If the service is running already, this command is a no-op.
$ candle ls
List all services for this project directory, including running and inactive services.
candle watch
candle watch [service name(s)]
Start watching the logs for the service(s)
This will interactively print any log messages from the service as they happen.
If no service names are provided: Watch every process in the project (including
any processes that are launched after watch is started)
If multiple services are being watched, then the output lines will include prefixes
that looks like [<service name>] ...
Example:
$ candle watch frontend backend
[backend] Backend server now listening on port 3000
[frontend] Web server available at http://localhost:8080
Show the recent logs for the given service.
If [name] is not provided: Show recent logs across all services in the project directory.
Options:
--count <number>- Number of log lines to show (default: 100).--start-at <id>- Only show logs after this log ID. Useful for pagination.
candle kill
candle kill [service name(s)]
Kill named service(s)
If no service names are provided: Kill all services for this project directory.
candle restart
candle restart [service name(s)]
Restart running service(s) for this current directory.
If no service names are provided: Restart all running services for this project directory
candle wait-for-log [service name] --message [message]
Waits until the service has printed text to stdout or stderr that includes [message].
This command is meant especially for CI jobs. In the CI context you often need to wait until a service has fully launched before moving on to the next step.
Example usage:
# Start the api server
candle start api
# Wait until it is ready
candle wait-for-log api --message "server now listening"
# Now run tests
npm run test
The command will continue to wait until a certain timeout. The timeout defaults to 30 seconds and can be
set on the command line as --timeout [seconds].
The pattern of calling start then wait-for-log will do what you expect: it will wait
for the most recent process instance to print the log message, and won't be triggered if a
previous recent run has the same message.
candle list-ports
candle list-ports [service name(s)]
Uses the operating system to detect and list the active open ports for running services.
This command searches Candle managed processes and also child processes. It uses lsof
to find to find TCP ports that are in a LISTEN state
If no [names] are provided: Show ports for all running services in the current project.
candle open-browser
candle open-browser [service name(s)]
Attempts to detect the listening port for a target service, then opens a web
browser to http://localhost:<port> for that service.
The port is auto-detected using the same logic as list-ports.
The open-browser command isn't perfect, and it can be confused by certain
situations (such as if your service has multiple listening ports). But in
most simple cases it works pretty well.
Create a new .candle.json config file in the current directory.
candle add-service [service name] --shell [command]
candle add-service [service name] --shell [command] --root [root directory]
Add a new service to the nearest .candle.json config file.
If the config file doesn't exist yet, it will be created.
Other CLI commands that are not typically used:
Run Candle in MCP mode, using stdin as the transport.
Note that it's now recommended for coding agents to use the candle CLI over Bash,
instead of using the MCP server. But this is provided as an option.
List all processes (across the entire system) that were launched by Candle.
Kill all processes (across the entire system) that were launched by Candle.
Like list-ports but shows open ports for all Candle-managed processes across the entire system.
Delete the database stored in ~/.local/state/candle.
This command can help if the database is corrupted or it needs a full SQL schema rebuild.
Warning: If there are any existing processes, then running erase-database will leave those processes 'orphaned'
(they will still be running but they won't be tracked by Candle). It's recommended to run candle kill-all
before doing this.
Several Candle commands have different behavior depending if they are running in an interactive or non-interactive context.
Candle uses interactive mode only when:
- Stdout is a TTY. Piping or redirecting output (
candle start | tee log.txt) makes it non-interactive. - And, no coding-agent environment variables are detected. If any are, Candle assumes an agent is driving the CLI. This is "agent mode".
Candle currently checks for these environment variables to detect a coding agent: CLAUDECODE,
GEMINI_CLI, CURSOR_AGENT.