Skip to content
CAI
Software that uses CAICheck a score

basecamp/kamal

62.1

Adequate · 22 September 2026

7.2k

lines of production code

Ruby

primary language

5

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

Kamal is a command-line tool for deploying containerized web applications to Docker servers with zero downtime. It manages the entire application lifecycle, including building images via various strategies, orchestrating container boot and health checks, and handling routing through a dedicated proxy. The system also supports external accessories, robust secrets management from multiple providers, and extensive deployment hooks for customization.

How it got here

2023 — Kamal rebrand and architecture rewrite

30 changes.

The project was rebranded from Mrsk to Kamal, involving a complete removal of the legacy library and Rake-based interface in favor of a new CLI-driven architecture. This period focused on rebuilding core components around kamal-proxy, implementing a robust configuration validation system, and establishing a comprehensive test suite to ensure the reliability of the new deployment lifecycle.

2024–2025 — modular CLI and secrets expansion

11 changes.

This period focused on refactoring the CLI into modular components for better host filtering and lifecycle management, while significantly expanding secrets management through a new extensible adapter framework supporting multiple providers. Concurrently, strict configuration validation was introduced alongside enhanced proxy and SSL capabilities to ensure robust deployment reliability.

Features

Add sensitive value redaction utility

A new Kamal::Utils::Sensitive class has been added to handle sensitive data, ensuring that values are automatically redacted in logs and YAML output. This utility integrates with SSHKit's redaction mechanism to prevent secrets from leaking into logs and provides safe string representation methods for both unredacted and redacted contexts.

lib/kamal/utils · high confidence

Introduce Kamal CLI with new deployment, build, and accessory management commands

This change introduces the core Kamal command-line interface, replacing the previous Traefik-based setup with a new architecture centered around kamal-proxy. The CLI now provides commands for booting, starting, stopping, and rebooting both application containers and external accessories, along with dedicated commands for building images (including a new \build dev\ command for local development), managing build locks, and handling registry authentication. It also adds a secrets management system with support for multiple vault adapters (OnePassword, LastPass, Bitwarden) and a new \server exec\ command for running ad-hoc commands on hosts. The deployment flow has been restructured to use kamal-proxy for routing, with new hooks for pre/post-deploy and boot events, and improved handling of stale containers and image pruning.

lib/kamal/cli · high confidence

Introduce extensible secrets adapter framework with initial provider support

The secrets management system has been refactored into a modular adapter architecture, introducing a base class that standardizes authentication, dependency checking, and secret retrieval. This change adds native support for retrieving secrets from AWS Secrets Manager, Google Cloud Secret Manager, Doppler, Enpass, LastPass, Passbolt, 1Password, and both standard and Secrets Manager modes of Bitwarden. It also includes a test adapter for integration testing. Users can now fetch secrets from these diverse providers using a unified command interface, with automatic CLI dependency validation and shell-escaped inputs for security.

lib/kamal/secrets/adapters · high confidence

New sample hooks for deployment lifecycle and environment setup

Added a comprehensive set of sample hook scripts in the \lib/kamal/cli/templates/sample\_hooks\ directory to allow users to customize various stages of the deployment process. These include pre- and post-hooks for app booting, deployment, proxy reboots, and app removal, as well as specific hooks for pre-build validation (checking git status and remote branches), pre-connect DNS warming, and Docker environment setup. The samples demonstrate how to integrate with external services like GitHub for build status checks and provide executable templates for common operational tasks.

_lib/kamal/cli/templates/sample\hooks · high confidence

Support for multiple secrets management providers

Users can now retrieve secrets from OnePassword, LastPass, Bitwarden, and GCP Secret Manager in addition to existing options. The system automatically maps provider aliases (such as '1password' to OnePassword and 'gcp' to GCP Secret Manager) to their respective adapters, allowing seamless integration with these external services.

lib/kamal/secrets · high confidence

Support inline Kamal secrets commands in dotenv variables

Users can now use inline Kamal secrets commands within dotenv variables (e.g., $(kamal secrets get MY\_SECRET)). The system detects these specific commands and executes them via the Kamal CLI with the --inline flag, allowing secrets to be fetched and substituted directly in configuration files without requiring external scripts or pre-processing steps.

lib/kamal/secrets/dotenv · high confidence

Removals

Removal of legacy Rake-based deployment tasks

The legacy Rake-based deployment interface (mrsk:app, mrsk:traefik, mrsk:registry, and mrsk:deploy) has been removed. This deletes the rake tasks for pushing images, starting/stopping containers, managing Traefik, and initializing configuration stubs, along with the shared setup logic that loaded the deploy configuration and configured SSH. Users must now use the new CLI-based commands for these operations.

lib/tasks · high confidence

Removed legacy Mrsk library files

The \lib/mrsk\ directory has been completely removed, deleting the \Commands\, \Configuration\, \Engine\, and \Version\ modules. This eliminates the original Mrsk library implementation, which previously handled configuration loading, command generation, and Rails engine integration.

lib/mrsk · high confidence

Behavioural changes

Comprehensive configuration validation and structured configuration classes

The configuration system has been refactored into a set of dedicated classes (Accessory, Alias, Boot, Builder, Env, Logging, Output, Proxy, Registry, Role, Servers, Ssh, Sshkit, Volume) that enforce strict schema validation against defined examples. This change introduces robust validation for all configuration sections, ensuring that unknown keys, incorrect types, and invalid structures are caught early. It also standardizes how specific features like SSH, proxy settings, builder options, and environment variables are parsed and validated, improving reliability and error reporting for users defining their deployment configurations.

lib/kamal/configuration · high confidence

Healthcheck logic moved to CLI with new polling and barrier components

The healthcheck mechanism has been refactored to reside within the CLI layer, introducing a new Poller module that handles container readiness polling with configurable timeouts and readiness delays, alongside a Barrier class for synchronization and a dedicated Error class. This change consolidates healthcheck behavior as a CLI concern, removing previous external dependencies or steps, and ensures users experience a streamlined deployment process where container health is verified directly by the CLI using the new polling logic.

lib/kamal/cli/healthcheck · high confidence

Introduce Kamal-proxy as the new reverse proxy

The application now uses Kamal-proxy instead of Traefik for routing and load balancing. This change introduces new commands to manage the proxy lifecycle (run, start, stop, remove) and its configuration, including support for custom proxy images, network arguments, and boot configuration files. The proxy is deployed as a dedicated container within the 'kamal' network, and its configuration is persisted in a volume at /home/kamal-proxy/.config/kamal-proxy. Accessory deployments can now also interact with the proxy for deployment and removal operations.

lib/kamal/commands · high confidence

Kamal 2.12.0 release with OTel logging, DNS retries, and alias support

This release introduces OpenTelemetry (OTel) log shipping via a new output framework (file and OTel backends), adds DNS retry logic to prevent deploy interruptions on lookup failures, and supports CLI command aliases. It also includes a global KAMAL constant for SSHKit compatibility, updates the version to 2.12.0, and refactors configuration and secrets handling.

lib/kamal · high confidence

Library renamed from Mrsk to Kamal with new loading architecture

The library has been renamed from Mrsk to Kamal, replacing the previous module structure with a new entry point that utilizes Zeitwerk for autoloading and explicitly eager-loads the CLI namespace to ensure commands are available. This change also introduces a specific ConfigurationError class and requires active\_support, marking a shift in how the core library initializes and manages its components.

lib · high confidence

New modular CLI components for app boot, assets, SSL, and error pages

The app CLI has been refactored into dedicated modules: \Kamal::Cli::App::Boot\ now manages the container lifecycle with a barrier mechanism to ensure the primary role is healthy before other roles start, while \Kamal::Cli::App::Assets\ handles asset extraction and volume syncing. Additionally, \Kamal::Cli::App::SslCertificates\ enables uploading custom SSL certificates for roles using the proxy, and \Kamal::Cli::App::ErrorPages\ uploads custom error pages to the proxy container.

lib/kamal/cli/app · high confidence

Rebrand from Mrsk to Kamal and introduce documentation generation

The project has been renamed from Mrsk to Kamal, reflected in the main executable (bin/kamal), the release script (bin/release) which now builds and pushes the kamal gem, and the internal module structure. Additionally, a new bin/docs script has been added to generate Markdown documentation from YAML configuration sources, and the test runner (bin/test) has been updated to use Rails plugin testing infrastructure.

bin · high confidence

Rebuilt builder command architecture with new builder types and options

The builder command layer has been completely restructured into distinct builder implementations (Base, Local, Remote, Hybrid, Cloud, Pack, and Clone) to support a wider variety of build configurations. Users can now utilize Cloud builders (Docker Build Cloud), Hybrid builders (combining local and remote contexts), and Pack-based builds (Cloud Native Buildpacks) alongside the existing local and remote Docker buildx builders. The changes introduce support for new build options including provenance attestations, SBOM generation, SSH arguments, and specific build targets. Additionally, the system now supports building from a local git clone with submodule recursion, allows pushing build outputs to different destinations (not just the registry), and provides better handling of registry credentials and builder inspection for remote setups.

lib/kamal/commands/builder · high confidence

Refactored app command structure and enhanced logging and execution capabilities

The app command module has been reorganized into distinct concerns (Assets, Containers, Execution, Images, Logging, Proxy) to improve maintainability. Users gain more granular control over application logs, with new options to filter by specific container IDs, configure line counts, set time ranges, and apply grep patterns with context. The \kamal exec\ command now supports running detached commands, piping input, and executing within the kamal network with custom environment variables. Additionally, asset extraction and synchronization logic has been extracted into a dedicated module, and proxy interactions are now managed through a specialized proxy command interface.

lib/kamal/commands/app · high confidence

Refactored proxy configuration with minimum version requirement

The proxy configuration logic has been restructured into dedicated \Boot\ and \Run\ classes to manage container lifecycle and runtime settings. This change enforces a minimum \kamal-proxy\ version of 0.9.2, ensuring compatibility with new features like custom TLS certificate support and configurable logging. Users will now see explicit version checks and updated default behaviors for HTTP/HTTPS port publishing and bind IP handling.

lib/kamal/configuration/proxy · high confidence

Refined host and role filtering logic in Commander

The host and role selection logic in the Commander has been refactored to ensure that primary role hosts are consistently sorted to the front of the list. The new \Specifics\ class introduces stricter filtering for accessory and proxy hosts, ensuring they respect explicit \--hosts\ and \--roles\ filters, and adds a dedicated \app\_hosts\ accessor. This change corrects previous issues where accessory hosts were incorrectly filtered out by role checks and ensures more predictable ordering and scoping of hosts during deployment commands.

lib/kamal/commander · high confidence

Removal of legacy command classes for App, Registry, and Traefik

The \Mrsk::Commands::App\, \Mrsk::Commands::Registry\, and \Mrsk::Commands::Traefik\ classes have been removed from the codebase. This eliminates the previous implementation of Docker commands for building, pushing, pulling, and managing application containers, registry authentication, and the Traefik reverse proxy. Users relying on these specific command structures will need to adapt to the new command execution patterns introduced in the refactored system.

lib/mrsk/commands · high confidence

Strict configuration validation for Kamal deployments

Kamal now enforces strict validation rules on deployment configurations, providing immediate feedback for common setup errors. Users must specify exactly one host or role source for accessories, ensure proxy SSL certificates include both a certificate and private key, and provide a valid host when enabling automatic SSL. The builder configuration now requires an explicit architecture setting, restricts cache types to 'gha' or 'registry', and prevents disabling local builds without a remote builder. Additionally, environment variables must follow a structured format with 'clear', 'secret', or 'tags' keys, and registry credentials are validated to ensure they are either a string or a single-item array for secret lookups.

lib/kamal/configuration/validator · high confidence

Updated default deployment and secrets templates

The default \deploy.yml\ template now uses \valkey/valkey:8\ for the Redis accessory instead of the previous image, sets the builder architecture default to \amd64\, and includes updated comments and examples for SSL, asset bridging, and environment variable injection. The \secrets\ template has been refreshed to provide clearer instructions and examples for reading credentials from environment variables, external commands, and secret managers like 1Password or LastPass, while explicitly warning against storing raw credentials in the file.

lib/kamal/cli/templates · high confidence

Test coverage

Added configuration tests for Kamal components; Added integration test configuration for accessory file and directory permissions; Added integration test environment for nested Docker daemons; Added integration test hooks for Kamal deployment lifecycle; Added integration test infrastructure for load balancer; Added integration tests for Kamal secrets interpolation; Added shared Docker infrastructure for integration tests; Added test fixture for integration testing; Added test fixtures for dynamic file expansion and environment variable injection; Added tests for environment tag configuration and secret aliasing; Added tests for proxy boot configuration and run object equality; Added tests for secrets adapters; Initial CLI test suite for Kamal commands; Initial test coverage for core command generators; Initial test suite for core Kamal components; Integration test deployer environment setup; Integration test suite for Kamal deployment lifecycle.

Dependencies

Add Rails edge gemfile for CI testing

A new gemfile has been added to the project to pin dependencies to the latest development version of Rails (specifically railties and activesupport from the main Rails repository). This change enables the continuous integration build matrix to test the gem against the upcoming Rails edge release, ensuring forward compatibility with future framework versions.

gemfiles · high confidence

Rename gem from mrsk to kamal and expand dependencies

The project has been renamed from mrsk to kamal, replacing the mrsk gemspec with a new kamal gemspec that defines the product as a tool to deploy web apps in containers to Docker servers with zero downtime. This change significantly expands the runtime dependencies beyond the previous railties and sshkit requirements, adding activesupport, net-ssh (\~\> 7.3), thor, dotenv (\~\> 3.1), zeitwerk, ed25519, bcrypt\_pbkdf, concurrent-ruby, and base64. Development dependencies have also been updated to include debug, minitest (\< 6), mocha, and rubocop-rails-omakase, while the test group's byebug dependency was removed.

(dependencies) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

Score

  • CAI 59 → 62 (+2.9)
  • Rubric changed (rubric-2026.08.19 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 89 → 93 (+4.8)
  • Architecture 100 → 78 (-22.1)
  • Maturity 42 → 48 (+6.1)
  • Readiness 61 → 66 (+4.6)
  • Security 83 → 87 (+3.5)

Resolved (12)

  • Coverage not included — suite not readable by the collector
  • Dependency hygiene not measured — dependency manifest found but not parsed for hygiene
  • Duplicated block (15 lines × 2) (lib/kamal/sshkit_with_ext.rb)
  • Duplicated block (17 lines × 2) (lib/kamal/cli/main.rb)
  • Medium CVE: [GHSA redacted] (Gemfile.lock)
  • Medium IaC: CKV_DOCKER_3 (Dockerfile)
  • Medium vulnerability: [GHSA redacted] (Gemfile.lock)
  • Medium vulnerability: [GHSA redacted] (Gemfile.lock)
  • No exposed public API
  • Off-boarding risk: anonymized user #1
  • Test reliability not included
  • Utils.optionize (cognitive 16) (lib/kamal/utils.rb)

New (19)

  • Both take no arguments. However, Kamal.Cli.App.remove_container(version) takes an argument. The Proxy CLI does not allow specifying a container version to remove, implying it only removes the current/active one or all. This is a functional inconsistency in capability between App and Proxy CLIs.
  • CLI layer exposes a method that takes a specific container name/version, while the underlying Command layer method takes no arguments. This suggests the CLI is handling the resolution of the container ID or version internally before calling the command, or the command signature is incomplete/misleading regarding its actual behavior (e.g., it might remove all containers or require state).
  • Change coupling: local.rb ↔ remote.rb (lib/kamal/commands/builder/local.rb)
  • Documentation: no installation or build instructions (README.md)
  • Documentation: no usage examples (README.md)
  • Duplicated block (16–17 lines × 2) (lib/kamal/cli/main.rb)
  • Duplicated block (16–17 lines × 2) (lib/kamal/sshkit_with_ext.rb)
  • FixmeComment (lib/kamal/cli/app.rb)
  • FixmeComment (lib/kamal/cli/app.rb)
  • Hotspot: lib/kamal/cli/app.rb (lib/kamal/cli/app.rb)
  • Low CVE: [GHSA redacted] (Gemfile.lock)
  • Medium IaC: WD-DOCKER-0003 (Dockerfile)
  • Medium IaC: WD-DOCKER-0011 (Dockerfile)
  • Off-boarding risk: anonymized user #1
  • Orphaned files with no living knowledge
  • Outdated: zeitwerk
  • Same inconsistency as remove_container. The CLI method accepts a name argument, but the Command method does not. This creates a disconnect in the API contract between the CLI interface and the command implementation.
  • The method dev is present in both CLI and Command layers. However, dev is not a standard CRUD operation like push, pull, create, remove. It appears to be a development-specific helper. Its presence in the public Command API surface suggests it might be intended for external use, but its naming is ambiguous compared to standard operations.
  • While signatures match here, Kamal.Cli.App.remove() exists alongside Kamal.Cli.App.remove_container(version). The general remove likely removes the whole app, but the existence of specific removal methods for containers/images in CLI vs the broader remove in App suggests a fragmented cleanup API. More critically, Kamal.Cli.App.remove_containers() (plural) exists without arguments, while remove_container (singular) takes an argument. This is consistent internally, but contrasts with Accessory where the singular CLI method took an arg but the command did not.

Changes since last survey

  • 29 commits — 24 feature/other, 5 fixes

By area

  • (repo) — 16 commits
  • lib/kamal — 6 commits
  • test/integration — 3 commits
  • (root) — 1 commit
  • .github/workflows — 1 commit
  • test/cli — 1 commit
  • test/fixtures — 1 commit

Notable commits

  • fix: Fix accessory ERB files losing env on multi-host uploads
  • fix: Merge pull request #1878 from matthewbjones/fix/builder-tests-host-arch
  • fix: Merge pull request #1880 from basecamp/fix-1790-require-bind-host
  • fix: Merge pull request #1923 from martinblech/codex/fix-destination-pruning
  • fix: Merge pull request #1947 from basecamp/integration-fix
  • change: Bump the github-actions group across 1 directory with 7 updates
  • change: Check the superseded accessory image on every host
  • change: Fail the integration deployer setup loudly
  • change: Honor --since and --lines when following accessory logs
  • change: Honor --since when following app logs
  • change: Keep .claude out of the Docker build context
  • change: Merge pull request #1879 from a-chacon/implement-app-remove-hooks
  • change: Merge pull request #1914 from basecamp/dependabot/github_actions/github-actions-545eaaaea5
  • change: Merge pull request #1915 from mudge/log-following
  • change: Merge pull request #1920 from igor-alexandrov/update-dependencies
  • change: Merge pull request #1921 from igor-alexandrov/dockerfile-skip-dev-gems
  • change: Merge pull request #1932 from ron-shinall/update-poller-text
  • change: Merge pull request #1933 from BetterAndBetterII/cursor/accessory-erb-env-race-1880
  • change: Merge pull request #1937 from franzejr/honor-since-when-following-app-logs
  • change: Merge pull request #1943 from basecamp/dockerignore-claude
  • …and 9 more

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

basecamp/kamal was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 22 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit fd335d803b8436863bb2cbbfc5e73e175e5fe0cc — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-be726e82e277.