tinka alpha
tinkaalpha

Environment variables

This guide covers the environment variables Tinka reads and sets. You will learn how to:

Overview

Tinka reads few environment variables of its own, and they come in three kinds:

Variables read through an Env's getters, such as e.Int("PORT", 3000), come from the real environment or from the Mode's .env files, and the real environment wins. Every other variable on this page is read from the real environment only, so setting it in a .env file has no effect. Configuration & Environment explains how .env files are found, merged and validated.

The Mode and .env files

The env package reads these two before anything else, because they decide which .env files the App reads. Both must come from the real environment.

APP_ENVstring

The App's Mode: development, test or production, in lowercase. Unset or empty means development. Any other value is a problem that e.Err() reports, and no .env file is read. A .env file that sets it to another Mode is reported too, since the value would have no effect. Production reads no .env file at all.

Commands read it the same way, through env.ParseMode. A destructive Command asks for confirmation in production and for any value ParseMode refuses, so a mistyped Mode never skips the guard. act generate:key prints the key instead of writing it in production, and fails with invalid_app_env for a value it doesn't know. act about shows the Mode, or invalid APP_ENV with the value it refuses.

ENV_PATHstring

The directory the .env files are read from. A relative path is resolved against the working directory, or against env.Dir when the App passes it; an absolute path is used as it is. Unset, the files are read from that directory itself. act generate:key writes the key into the .env file it finds there.

Any variable read through a getter also has a file form: when KEY is missing and KEY_FILE is set, the getter reads the value from the file KEY_FILE names. See Reading values from files.

The skeleton Starter kit's variables

An App created with tinka new --kit skeleton reads these in config/, and lists them in .env.example. tinka new copies .env.example to .env with a new APP_KEY, and writes a .env.test with a separate test key and LOG_LEVEL=error. The core Starter kit reads none of them: its tinka.New(tinka.HTTPConfig{}) listens on :3000.

PORTint

The port the App listens on, on every interface (HTTPConfig.Addr becomes ":" + PORT). Defaults to 3000. Under act serve it has no effect, because act serve passes the App its listener.

APP_URLURL

Where people reach the App, for the links it builds. An absolute URL with a scheme and a host. Defaults to http://localhost:3000.

APP_KEYsecret

The key that signs and encrypts cookies and signed URLs. Required: without it the App stops at boot, before it serves or runs a Command. Generate one with act generate:key. See The APP_KEY.

APP_DEBUGbool

Adds a server error's cause, and a panic's stack, to its response (HTTPConfig.Debug). Defaults to false; .env.example sets it to true for your machine. Production reads no .env file, so it stays off there unless you set it in the real environment.

LOG_LEVELstring

The least severe level the logger writes: trace, debug, info, warn, error or fatal, in lowercase. Defaults to info. Any other value is a problem the App reports at boot, with the others. See Log levels.

LOG_FORMATstring

How log records are written: json, text or pretty, in lowercase. Defaults to pretty in development and json in the other Modes. The kit's tests write text to the test's output whatever it says.

The kit's tests.App builds the App in the test Mode whatever APP_ENV says, so tests load .env.test over .env, and never .env.local.

Variables act sets for the App

act serve and Forwarding start other processes and pass them these variables. They are internal: never set them yourself, in a shell or in a .env file.

TINKA_DEV1

Set by act serve on the App it runs. Serve then skips HTTPConfig.DrainDelay on shutdown, since no load balancer needs draining, so restarts stay fast.

LISTEN_FDSint

The socket activation protocol, set by act serve on Unix systems such as Linux and macOS, and by systemd in production. When it's set, and LISTEN_PID is unset or names the App's process, Serve serves on the listener already open as file descriptor 3 instead of Addr. It must be 1: any other number makes Serve fail. Serve unsets both variables, so programs the App starts don't take the listener. See Socket activation.

LISTEN_PIDint

The process the listener in LISTEN_FDS is meant for. systemd sets it; act serve doesn't.

TINKA_DEV_ADDRstring

Set by act serve on Windows, which can't pass a listener to another process: the address Serve listens on instead of Addr. Serve reads it on every system whenever it takes no listener from LISTEN_FDS.

TINKA_DEV_TOKENsecret

Set by act serve on Windows, next to TINKA_DEV_ADDR. The App proves with it that it, and not another program that bound the port first, is answering. Serve unsets it at once.

TINKA_LAUNCHED1

Set by Forwarding on the process it starts: the App's binary, the version of act an App's go.mod pins, or the Tinka repo's own tooling. It stops that process from forwarding again.

GOWORKoff

Set to off for every go build and go test that act runs, and shown in the commands act build and act test print, so a go.work file elsewhere in the tree can't change what the App is built from.

CGO_ENABLED0 or 1

Set by act build: 0, or 1 with --cgo. --target sets GOOS and GOARCH the same way. These replace your own values for that build.

act caches the App's binary and builds it again when its sources change, or when one of these Go variables does: GOFLAGS, GOOS, GOARCH, GOAMD64, GOARM64, GOEXPERIMENT, CGO_ENABLED, CC, GOTOOLCHAIN, GOPROXY and GOPRIVATE.

Agent mode and agent detection

Every Command decides between output for people and a single JSON result. --json always wins; otherwise these variables decide, in order. See When Agent mode turns on.

TINKA_AGENTbool

1 or true forces Agent mode, and 0 or false turns it off, in any case. Any other value is ignored, and agent detection decides.

AI_AGENTstring

The name of the agent running the Command, such as claude-code. Any name turns Agent mode on, and so do 1 and true. An empty value, 0 and false count as unset, so the variables below are still checked: use TINKA_AGENT=0 to turn Agent mode off.

AGENTstring

The same as AI_AGENT, checked after it.

When neither names an agent, Tinka turns Agent mode on if any of the variables below is set, to any value, even an empty one; only TERM_PROGRAM needs the value shown. The last four also appear in terminals that people type into, because editors set them for their integrated terminal, so they only count when stdin is not a terminal.

Terminal output

Commands style their output only when stderr is a terminal. Two variables turn the styling off. See Control colors.

NO_COLORstring

Any non-empty value turns colors off, in Commands' output and prompts and in the logger's pretty format.

TERMstring

dumb turns colors off in Commands' output, and makes prompts that move the cursor ask for a number instead. The logger's pretty format doesn't read it.

An App's own Command can also read a flag from a variable you choose with f.Env, such as f.Env("batch-size", "IMPORT_BATCH_SIZE"), and the command line wins over the variable. Tinka's own Commands bind no flag to a variable. See Read flags from the environment.

Tests

TINKA_UPDATE1

Exactly 1 makes golden-file assertions write the file instead of comparing with it: AssertGolden in tinkatest, for a response body, and clitest.Signatures, for the signatures of an App's Commands. Review the change before committing the file. See Assert on the response and Keep signatures stable.

Where act keeps its files

act records trusted Apps in tinka/trusted-apps under your user config directory. It keeps the binaries it builds for Forwarding, and the locks of --isolated runs, under tinka/ in your user cache directory. Go finds both directories from the environment, the config directory first:

When Go can't find the cache directory, Forwarding fails with no_cache_dir. See Error codes.

Installing during the alpha

During the alpha the Tinka repository is private, and Go's public module proxy can't download it. Set Go's GOPRIVATE so the go command downloads every github.com/mucolabs module straight from GitHub, bypassing GOPROXY and the checksum database for them:

Terminal
go env -w GOPRIVATE=github.com/mucolabs/*

git must also be able to authenticate to GitHub. Without both, go install fails, and tinka new fails with install_failed after creating the App. See Installation.

See also: Configuration & Environment, Agent mode, Error codes, Commands, Development environment setup