CLI concepts
The CLI keeps a small set of files in your repository and orchestrates AWS calls around them. Once you know what each file holds and when its values are read, every command is predictable.
- Name the files the CLI keeps — manifest, lockfile, stage files — and the ledger it writes
- Trace how the service name becomes every AWS resource name
- Know the three forms an
envvalue takes, and when each is resolved - Read stage values from ordinary ASP.NET Core configuration
The files
<service root>/ ← where you run kanject├── kanject-cli/│ ├── manifest.json ← service identity, entries, dependencies, preview policy│ ├── manifest.lock.json ← each dependency pinned to a commit (sync output)│ └── stages/│ ├── dev.json ← region, profile, stack, bucket, env│ └── prod.json└── template.json ← your SAM template; deploy derives one per stages3://<artifactBucket>/_ledger/ ← deployment history, outside git Everything under kanject-cli/ lives in git, so reviewers see every change. The deployment ledger lives in S3, so every deploy is auditable independently of the working copy. For a service from kanject new, the service root is the API project folder, src/<Name>.Api/. Field-by-field detail is in the Manifest Reference.
Service identity
manifest.json → service.name is the identifier everything downstream derives from: the CloudFormation stack ({stage}-{service}), the artifact bucket ({stage}-{service}-artifacts), the Parameter Store path (/{service}/{stage}/), and the ledger. The name is normalized to lowercase and hyphens, and must start with a letter.
Stages
A stage is a deployment target: typically dev and prod, but qa-eu or canary work just as well. Every stage in manifest.json → aws.stages has a matching kanject-cli/stages/<stage>.json with its region, profile, stack, artifact bucket, Parameter Store path and env map. kanject new starts a service with dev only; kanject init on an existing project creates dev, stage and prod unless you pass --stages. Add one later with kanject add stage <name>.
Configuration and secrets
Configuration layers the standard ASP.NET Core way — appsettings.json for defaults, appsettings.<Environment>.json for overrides — with the stage file's env on top. An env value takes one of three forms:
# Plain string — applied to the function as-isASPNETCORE_ENVIRONMENT=Development# Parameter Store reference — resolved at deployDATABASE_URL=param:DATABASE_URL# Secrets Manager reference — resolved at deployJWT_SIGNING_KEY=secret:acme-analytics/dev/jwt#key kanject aws deploy resolves every reference once, at deploy, and applies the result to the function's environment variables. The function never calls Parameter Store or Secrets Manager itself, so cold starts stay fast. Your code reads the values through the default IConfiguration, and the Section__Key naming maps a flat variable onto a nested key:
// stages/prod.json — the env block carries references, never values{ "env": { "ASPNETCORE_ENVIRONMENT": "Production", "Auth__UserPoolId": "param:COGNITO_USER_POOL_ID", "Auth__ClientSecret": "secret:acme-analytics/prod/cognito#clientSecret" }} Only the reference is committed, never the value. Applying merges: values your template sets survive, and stage values win on a clash. A service that loads its own configuration at startup can deploy with --bake-secrets false, which applies nothing. kanject env --env <stage> shows a stage's bindings without calling AWS.
Cross-repo dependencies
Shared libraries in sibling repositories are declared in manifest.json → dependencies[] with a git URL, ref and project path. kanject sync pins each one to a commit in manifest.lock.json, clones it into .kanject/cache/, and wires it in through generated MSBuild imports, so your .csproj files are never edited and nothing is packed into a NuGet package. See Dependencies.
Deployment ledger
Every successful deploy appends an entry to the ledger in the stage's artifact bucket: the published version, the commit, who deployed it, and hashes of the env values. The ledger is the source of truth for audit and rollback: kanject aws rollback reads it and points the stage at an earlier release without rebuilding, and records that as a new entry. See Deployment.
What Kanject CLI does NOT own
dotnet new— the CLI calls it with the template pack it ships, and doesn't replace it.dotnet build/dotnet test— vanilla. The CLI doesn't proxy them.dotnet lambda deploy-serverless— the Lambda deploy backend. The CLI prepares its inputs, then calls the AWS-supplied tool.- Your SAM template —
template.jsonis yours; deploy derives a per-stage copy from it. - Your CI provider —
pipeline upprovisions CodePipeline; for GitHub Actions or GitLab, you write the workflow. - Your application code — the CLI adds its own files beside it, such as
kanject-cli/, but never edits your code.
- The CLI keeps
manifest.json,manifest.lock.jsonand one file per stage underkanject-cli/, plus an append-only deployment ledger in S3. service.nameis the identifier every AWS resource name derives from.envvalues are plain strings,param:references, orsecret:references, resolved once at deploy and applied to the function;--bake-secrets falseopts out.- Your code reads them through the default
IConfiguration;Section__Keynames map onto nested keys. syncpins cross-repo dependencies and wires them in through generated MSBuild imports; the ledger powers audit and rollback.