Overview
Config as code supports TypeScript and Go.shipd.config.ts holds flag definitions written with defineFlags, .shipd/config.json holds optional project settings for the CLI, and src/generated/flags.ts holds the types the CLI generates from the definitions. Go definitions live in shipd.config.go, and Go accessors default to internal/flags/flags_gen.go. This page is the contract for these formats. For what shipd push does with them, see shipd push.
shipd.config.ts
The file must default-export the result ofdefineFlags. The CLI loads it with jiti, so TypeScript runs without a build step. It lives in the project root by default. Override the location with configFile in .shipd/config.json or --flags-config.
Go ShipdConfig
Importgithub.com/alasti-company/useshipd.com/sdks/go/config. It’s part of the Go SDK module, so go get github.com/alasti-company/useshipd.com/sdks/go installs both, and it has no dependencies on the runtime client. ShipdConfig is a named map so flag keys can appear directly in a composite literal; each value is a FlagDefinition struct:
__proto__. At most 500 flags are accepted. Deprecated becomes lifecycle: "deprecated"; omitted tags normalize to []. Disabled preserves an intentionally disabled environment fallthrough.
CLI loading. The CLI reads shipd.config.go directly and automatically generates Go accessors. Define an exported var Config = config.ShipdConfig{...} in a self-contained Go file inside your module. The CLI evaluates that file with Go; imported packages and helper declarations in the same file are supported. It does not load sibling Go files, so keep application dependencies in imported packages. Do not define main in the definition file. shipd pull rewrites the Go definitions and regenerates accessors; review the resulting diff because comments and helper code are replaced.
Defaults. Defaults validates and returns a detached map for shipd.Options.Defaults; numbers decode as float64. Mutating that map does not change the definitions. Unlike the generated flags.Defaults() helper, this method returns an error because the definitions have not yet been validated.
Mutation. A ShipdConfig literal remains editable. Methods validate its current values each time; do not mutate it concurrently with validation or extracting defaults.
shipd.config.json
A language-neutral document withversion: 1 and a flags object. The CLI validates every entry with the same sync schema as TypeScript. This optional format can be authored directly; Go projects use shipd.config.go.
shipd.config.json
tags defaults to [], lifecycle defaults to "active", and description is optional. deprecated: true is accepted as shorthand for a deprecated lifecycle when lifecycle is omitted. Pull writes normalized lifecycle values and preserves the optional disabled field for intentionally disabled environment fallthrough.
Discovery checks shipd.config.ts, shipd.config.go, then shipd.config.json. Set configFile or --flags-config to select a file explicitly. Pull preserves the selected format.
defineFlags
Validates flag definitions, normalizes them for the CLI, and keeps flag keys and variant names as literal types.Record<string, FlagDefinition>
required
An object whose keys are flag keys and whose values are flag definitions.
FlagsConfig<T>: { version: 1, flags: { [key]: NormalizedFlag } }.
Errors. Throws a Zod validation error, or Error('flag key "__proto__" is reserved'), when a definition breaks a validation rule. The CLI reports load failures as Failed to load config <path>: <message> with exit code 1.
defineFlags is exported only from shipdit/config, not from the shipdit root.
Definition types
Fields
"boolean" | "variant" | "number" | "json"
required
The value type. Selects the SDK reader:
isEnabled, getVariant, getNumber, or getJson.boolean | string | number | JSON value
required
The value the target environment’s fallthrough serves. On every
shipd push, if default differs from the target environment’s current fallthrough, push sets that fallthrough to default, replacing a fallthrough edited in the dashboard (including a weighted split). Other environments are untouched. Run shipd pull first, or update default, to keep a dashboard edit. See Field scope.readonly [string, ...string[]]
Required for
variant flags, ignored otherwise. Write it as const so variant names stay literal types.string
Shown in the dashboard.
readonly string[]
Labels for filtering in the dashboard. Normalized to
[] when omitted.boolean
true sets the flag’s lifecycle to deprecated. Omitted or false means active.shipd.config.ts; set them in the dashboard.
Normalized output
Validation rules
defineFlags checks these at runtime when the file loads. The CLI and the server re-check them before a diff or push.
A JSON value is
null, a boolean, a string, a finite number, an array of JSON values, or a plain object of JSON values. TypeScript authoring rejects functions, undefined, symbols, symbol keys, class instances (including Date and Map), NaN, Infinity, and circular references.
Flag keys have no other format rule. new-checkout, checkout.v2, and max_retries are all valid. For naming advice, see Name and retire flags.
For TypeScript definitions, the variant check also runs at compile time. This is a type error:
Field scope
A flag definition is shared by every environment in the project. Its default is not.
When push creates a flag,
<env> gets the flag enabled with its fallthrough set to default. Every other environment gets the flag disabled with a disabled fallthrough. The full rules, including what happens when default changes on an existing flag, are in shipd push.
shipd pull reads the other way: it writes each flag’s default from the target environment’s fallthrough.
Project settings file
.shipd/config.json holds optional project settings for the CLI. The CLI finds it by walking up from the current directory. Point to another file with --config <path>. Flags and SHIPD_* environment variables override it; it overrides the global config written by shipd login. See Configuration precedence.
.shipd/config.json
typesLanguage selects TypeScript (src/generated/flags.ts) or Go (internal/flags/flags_gen.go) default output. typesOut can only be set here; shipd types gen -o overrides it for one run. Do not put credentials in this file. Use SHIPD_API_KEY or shipd login.
Generated Go accessors
With Go input ortypesLanguage: "go", push, pull, and type generation write one function per flag, key constants, named variant string types and constants, and Defaults() map[string]any. Number accessors return float64; JSON accessors return any.
Go names use the alphanumeric parts of keys in PascalCase. Names that do not begin with an uppercase Unicode letter receive a Flag prefix. Flag and variant names that collide with another generated declaration cause a validation error. Package names must be valid ASCII Go identifiers and cannot be keywords or _.
Generated accessors use the canonical Go SDK module path. Go variants are named string types, not closed unions. See Go output for usage.
Generated types
shipd push, shipd pull, and shipd types gen write typesOut from the local TypeScript, Go, or JSON config. Unless overridden by typesLanguage or typesOut, TypeScript and JSON use src/generated/flags.ts, while Go uses internal/flags/flags_gen.go. The file is overwritten on every run. Do not edit it by hand. See Generate flag types.
src/generated/flags.ts
Pass
FlagDefinitions as the type argument to createClient<FlagDefinitions>() from shipdit or shipdit/client, and to createShipdReact<FlagDefinitions>() from shipdit/client/react. Without it, any string key type-checks.
Related: shipd push · Define flags in code · Generate flag types · SDK reference