CLI Configuration

The Heartlock CLI is a single-binary Go client that authenticates via the browser, fetches project secrets from the API, and injects them as environment variables into a child process — mirroring infisical run.

Installing

Pre-built binaries for Linux and macOS (amd64 and arm64) are attached to every release:

https://yena.dev/Jouleworks/heartlock/releases/latest/

Install or upgrade with the download script:

curl -fsSL https://yena.dev/Jouleworks/heartlock/raw/branch/main/scripts/download.sh | bash

This detects your OS and architecture, downloads the latest binary, and places it on your PATH. To inspect the script first:

https://yena.dev/Jouleworks/heartlock/raw/branch/main/scripts/download.sh

Building from source

cd cli
go mod tidy
make build          # produces ./bin/heartlock

Other Make targets:

Target

Description

build

Build ./bin/heartlock for the host platform

run

Build then run with ARGS="...", e.g. make run ARGS="whoami"

test

go test ./...

vet

go vet ./...

tidy

go mod tidy

release

Cross-compile linux+darwin / amd64+arm64 into dist/

clean

Remove bin/ and dist/

Commands

heartlock login [--server URL] [--force|-f]

Browser-based authentication. Starts a local callback server on an ephemeral port, opens the browser to <server>/cli/login?callback=http://localhost:<port>/callback, captures the service token delivered by the redirect, validates it against /auth/me/, and persists it.

If a stored token already exists for the resolved server, login first verifies it. When it is still valid, login prints the account and exits without opening a browser. When the server rejects it (revoked/expired), login automatically re-runs the browser flow.

Use --force (or -f) to skip the check and re-authenticate regardless.

Note

Any command that receives a 401 response clears the stored token for that server automatically, so the next heartlock login performs a fresh sign-in.

heartlock whoami

Prints the currently authenticated user (calls /auth/me/).

heartlock projects

Lists projects accessible to the authenticated user (NAME / SLUG / ROLE).

heartlock environments --project <slug|id>

Lists environments for a project. --project accepts a slug (looked up against the projects list), a name, or a UUID.

heartlock secrets --project <slug|id> --env <slug|id>

Lists secrets as a table (KEY / VALUE / COMMENT).

--reveal

Show plaintext values (values are masked with •••••••• by default).

--env-only

Print KEY=value, one per line, suitable for shell sourcing.

heartlock run --project <slug|id> --env <slug|id> [-- command args...]

Fetches secrets via the export endpoint and execs the child command with them injected into the environment.

--preserve-env

Existing environment variables win; fetched secrets only fill in variables that are not already set. Without this flag, fetched secrets override existing variables.

The -- separator distinguishes Heartlock flags from the command and its arguments. Exit status is the child’s exit status. Signals (SIGINT, SIGTERM) are forwarded to the child.

heartlock import-env [--project <slug|id>] [--env <slug|id>] [file]

Reads a .env file and stores each KEY=value as a secret in the target environment. --project / --env fall back to default_project / default_env from the config file.

-f/--file

Select the source file; defaults to .env. Use - to read from stdin.

--overwrite

Update the value of variables that already exist instead of skipping them.

--dry-run

Parse and print the plan without writing anything.

Existing variables are skipped unless --overwrite is given; a 403 response means your role lacks write access.

heartlock logout

Removes the stored token for the active profile.

heartlock config [--server URL]

Shows the current server, active profile, login state, and config path. With --server URL, sets the default server for the active profile.

Configuration file

The configuration lives under the OS user-config directory in a heartlock subdirectory:

OS

Path

Linux

~/.config/heartlock/config.json

macOS

~/Library/Application Support/heartlock/config.json

Windows

%AppData%\heartlock\config.json

The file is created with permissions 0600. Example structure:

{
  "server": "http://localhost:8082",
  "default_project": "web",
  "default_env": "dev",
  "active_profile": "default",
  "profiles": {
    "default": {
      "server": "http://localhost:8082",
      "token": "<SERVICE_TOKEN>",
      "user": { "id": "...", "email": "you@example.com" }
    }
  }
}

Warning

The token is stored in plaintext in config.json for the current version. Integration with the OS keychain / credential store is a planned improvement.

Configuration precedence

Overrides are resolved from highest to lowest priority:

  1. Flags: --server, --token

  2. Environment: HEARTLOCK_SERVER, HEARTLOCK_TOKEN

  3. Active profile: server / token in the named profile

  4. Top-level config: server key

  5. Built-in default: http://localhost:8082

API endpoints used by the CLI

All under <server>/api/v1/, authenticated with a Bearer token via Authorization: Bearer <token>:

Method & Path

Used by

GET /health/

login (reachability check)

GET /auth/me/

login, whoami

GET /projects/

projects, slug resolution

GET /projects/{project_id}/environments/

environments, env resolution

GET /projects/{project_id}/environments/{env_id}/secrets/

secrets

GET /projects/{project_id}/environments/{env_id}/secrets/export/

run

POST /projects/{project_id}/environments/{env_id}/secrets/

import-env (create)

PATCH /projects/{project_id}/environments/{env_id}/secrets/{secret_id}/

import-env (update)