Keep local values in env files
On your machine, a pack's settings and secrets live in env files at the
pack's root. kindgi dev reads .env, then .env.local; a name in both
takes its value from .env.local.
ORDERS_APP_URL=http://localhost:3000kindgi dev says which files it read when it starts:
✓ env files: .env, .env.local — 4 name(s) for the packWhat reads them
Section titled “What reads them”Under kindgi dev, the env files are two things at once.
The pack service's environment. Your tools' code runs in the pack service, and every name in the env files is in its environment:
import { defineTool } from '@kindgi/sdk/define';import type { ToolId } from '@kindgi/sdk/types';import { z } from 'zod';
const defined = defineTool({ id: 'my-pack.order-link' as ToolId, description: 'Returns the link to an order in the back office.', version: '0.1.0', input: z.object({ orderId: z.string() }), output: z.object({ url: z.string() }), effects: [], mutating: false, handler: async ({ orderId }) => { const base = process.env.ORDERS_APP_URL; if (base === undefined) throw new Error('ORDERS_APP_URL is not set'); return { url: `${base}/orders/${orderId}` }; },});
if (defined.kind === 'err') throw new Error(defined.error.message);export default defined.value;import os
from pydantic import BaseModel, Field
from kindgi import tool
class OrderRef(BaseModel): order_id: str = Field(alias="orderId")
class Link(BaseModel): url: str
@tool(id="my-pack.order-link", mutating=False)def order_link(ref: OrderRef) -> Link: """Returns the link to an order in the back office.""" return Link(url=f"{os.environ['ORDERS_APP_URL']}/orders/{ref.order_id}")Call it from my-pack.link, a one-step flow:
kindgi runs start --flow=my-pack.link --input='{"orderId":"ord_1001"}' "flowId": "my-pack.link", "flowVersion": "0.1.0", "status": "completed", … "output": { "url": "http://localhost:3000/orders/ord_1001" },Nothing else reaches it: a variable exported in the shell you start
kindgi dev from isn't in the pack service's environment, and neither is a
KINDGI_* name, from anywhere. Save an env file and the pack service
restarts with the new values.
The local secrets store. Tools' declared secrets, HTTP tools'
credentials, model providers' keys and MCP endpoints' credentials resolve in
an environment; under kindgi dev it's local, and local is these files.
kindgi secrets set … --env=local writes to .env.local
(Store a secret).
See what's set
Section titled “See what's set”kindgi env list --env=local Environment: local Env file: .env Env file: .env.local Reveal: NO (redacted; --reveal to show)
4 key(s): HTTPBIN_TOKEN de**********23 [.env.local] INVENTORY_TOKEN in**************56 [.env.local] ORDERS_APP_URL ht*****************00 [.env] RECEIPT_SIGNING_KEY a6************************************************************83 [.env.local]Values are redacted; --reveal prints them to a terminal, never to a pipe or
a file.
Read other files
Section titled “Read other files”To read more files, list them in the pack's config, lowest precedence first:
// in kindgi.config.tsdev: { envFiles: ['.env', '.env.development', '.env.local'] },# in pyproject.toml[tool.kindgi.dev]envFiles = [".env", ".env.development", ".env.local"]kindgi dev reads the list when it starts: restart it after a change.
✓ env files: .env, .env.development, .env.local — 6 name(s) for the packKeep them out of git
Section titled “Keep them out of git”The files hold secrets. Make sure your .gitignore covers them:
.env.env.*!.env.exampleThe Python template's .gitignore has these lines. A TypeScript pack made
with kindgi init 0.1.0 has no .gitignore (its lines landed in
.npmignore): add one.