Skip to content

klim init

Scan your project directory to detect which CLI tools it uses, then generate a .klim.yaml team manifest.

Terminal window
klim init [flags]
FlagDescription
--allInclude all installed tools (skip project detection)
--min-versionInclude minimum version constraints (>=X.Y)
--nameProject name for the manifest
--forceOverwrite an existing .klim.yaml (klim refuses by default to protect a team-shared file). When --force is overwriting an existing manifest, klim refuses to write an empty result on three paths: (a) --all is used and no tools are installed at all; (b) project detection ran but matched no project files; (c) project detection found tools but none of them are installed yet. The existing manifest is preserved untouched in all three cases. A dangling .klim.yaml symlink also counts as “existing” for the safety check; --force is required to write through it (the symlink itself is preserved — see Symlinks below).

klim scans your project for tool references in:

  • DockerfilesFROM, RUN commands
  • package.json — scripts, devDependencies
  • go.mod — Go module dependencies
  • CI workflows — GitHub Actions, GitLab CI, CircleCI
  • Helm charts — Chart.yaml, values.yaml
  • Terraform — .tf files
  • Bicep — .bicep files
  • pyproject.toml — Python project config
  • Makefile — build targets
  • docker-compose.yaml — service definitions
  • And 30+ more file types

Only tools that are both detected AND installed are included, so versions can be pinned accurately.

Terminal window
# Auto-detect from project files
klim init
# Include all installed tools (no detection)
klim init --all
# Pin minimum versions
klim init --min-version
# Set project name
klim init --name my-project
# Overwrite an existing .klim.yaml
klim init --force

Creates a .klim.yaml file in the current directory:

name: my-project
tools:
- name: kubectl
version: ">=1.28"
- name: helm
- name: docker
optional:
- name: k9s

If you keep .klim.yaml as a symbolic link (e.g. to a shared template), klim init --force writes through the link to the target file rather than replacing the link with a regular file. This works even when the link is dangling — the target file is created on first write as long as the target’s parent directory already exists. A link like .klim.yaml → ../shared/missing/manifest.yaml will fail with ENOENT if ../shared/missing/ doesn’t exist; klim does not auto-create parent directories under shared mounts. Symlink chains are followed by the OS up to its own limit (Linux 40 hops, Windows configurable); cycles surface as the OS-level error your platform produces (e.g. ELOOP on Linux, ERROR_CANT_RESOLVE_FILENAME on Windows) — klim doesn’t translate these.

When a .klim.yaml already exists as a regular file (or as a symlink to an existing target), klim init --force preserves its current mode bits, ownership, ACLs (POSIX and Windows), extended attributes, and inode — the file is rewritten in place rather than replaced. A manually-restricted manifest (e.g. chmod 600 .klim.yaml because the manifest contains sensitive tool/version data) keeps those bits across re-inits. Hardlinks pointing at the manifest stay live. For freshly-created manifests klim requests mode 0644; the actual mode is whatever the OS produces after applying the process umask (typically 0022, giving 0644) — on a system with umask 0077 you’ll see 0600 instead, and Windows does not honor POSIX bits 1:1. Note: when --force overwrites a dangling symlink, the target file is being created for the first time, so there is no prior metadata to preserve and the requested mode + umask rule applies.