Instance and Resource Naming
Contributor reference for how jackin names containers, images, derived Docker resources, on-disk state, lock files, and role repos.
All naming logic lives in crates/jackin-runtime/src/instance/naming.rs (container names, instance IDs, role-family matching) and crates/jackin-runtime/src/runtime/naming.rs (image tags, derived resource names, display formatting).
Container name
Every fresh launch claims a unique, DNS-safe container name:
jk-{instance_id}-{workspace_compact}-{role_compact} ← saved workspace
jk-{instance_id}-{role_compact} ← ad-hoc launch (no workspace)Components:
| Component | Value | Rules |
|---|---|---|
jk- | Fixed prefix | Identifies all jackin-managed Docker resources |
instance_id | 8 chars | Crockford base32, cryptographically random, collision-resistant |
workspace_compact | Variable | Original workspace name with non-alphanumeric characters stripped, lowercased |
role_compact | Variable | Role name with non-alphanumeric characters stripped, lowercased |
Budget: The total base name must fit within 58 characters so that {base}-dind stays within Docker's 63-character DNS label limit. The budget for workspace and role combined is 58 - 2 (jk) - 8 (id) - 3 (separators) = 45 characters. If the two compact components together exceed 45 characters they are split evenly and each is truncated with a 4-character SHA-256 suffix to keep the result deterministic.
Examples:
jk-1vft0hkh-chainargosblockchainnodes-agentbrown
└─ workspace: chainargos-blockchain-nodes
└─ role: agent-brown
jk-1vft0hkh-agentbrown
└─ ad-hoc launch, no workspace
jk-1vft0hkh-scentbird-thearchitect
└─ workspace: scentbird
└─ role: the-architectDerived Docker resources
Every container launch also creates three Docker resources derived by appending a suffix to the base name:
Role container: {base}
DinD sidecar: {base}-dind
Docker network: {base}-net
TLS certs vol: {base}-dind-certsExample:
jk-1vft0hkh-chainargosblockchainnodes-agentbrown
jk-1vft0hkh-chainargosblockchainnodes-agentbrown-dind
jk-1vft0hkh-chainargosblockchainnodes-agentbrown-net
jk-1vft0hkh-chainargosblockchainnodes-agentbrown-dind-certsDNS-sensitive environment variables (DOCKER_HOST, JACKIN_DIND_HOSTNAME, DOCKER_TLS_SAN, NO_PROXY, no_proxy, TESTCONTAINERS_HOST_OVERRIDE) use the DinD name as the hostname.
Docker image name
The Docker image is built once per role and rebuilt only when the role changes. It is stable across sessions.
Namespaced role: jk_{namespace}_{role-name}
Flat role: jk_{role-name}All structural separators in image names are _. Role segment names are validated to [a-z0-9-] only, so _ never appears in a role or namespace name — _ always marks a structural boundary, never a word break inside a component.
Examples:
jk_chainargos_agent-brown ← chainargos/agent-brown
jk_agent-smith ← agent-smith (no namespace)
jk_scentbird_the-architect ← scentbird/the-architectCollision safety: chainargos/agent-brown produces jk_chainargos_agent-brown while a flat role literally named chainargos-agent-brown produces jk_chainargos-agent-brown. The underscore vs hyphen difference makes them distinct.
Image vs container names: Container names use jk-{id}-… with - separators (required for DNS label validity). Image names use jk_… with _ separators. Both start with jk but use a different delimiter, so they are visually distinct in docker ps and docker images output.
Branch-specific build tags
When a role is built from a specific branch (jackin load --branch), the image tag adds the branch slug after a _ separator:
Namespaced role: jk_{namespace}_{role-name}_{branch-slug}
Flat role: jk_{role-name}_{branch-slug}Branch slashes become dashes in the slug. All separators are _ — unambiguous because branch slugs contain only [a-z0-9-].
Examples:
jk_the-architect_feat-my-pr ← the-architect, branch feat/my-pr
jk_chainargos_agent-brown_feat-my-pr ← chainargos/agent-brown, branch feat/my-prBranch-specific images do not replace the stable image — they coexist with jk_the-architect under a distinct tag.
State directory
The per-instance state directory on the host always has the same name as the container:
~/.jackin/data/{container_name}/Example:
~/.jackin/data/jk-1vft0hkh-chainargosblockchainnodes-agentbrown/Set once at launch time, never renamed. The Docker container name and the state directory name are always identical — they are derived from the same string in crates/jackin-runtime/src/instance.rs.
Repo lock files
The repo cache uses a stable per-role lock file to serialize concurrent git clone/fetch operations for the same role:
~/.jackin/data/{role-name}.repo.lock ← flat role
~/.jackin/data/{namespace}_{role-name}.repo.lock ← namespaced role
~/.jackin/data/{role-name}.locks/
~/.jackin/data/{namespace}_{role-name}.locks/Example:
~/.jackin/data/agent-smith.repo.lock
~/.jackin/data/chainargos_agent-brown.repo.lockThe same _ separator as image names makes these stable across sessions and collision-safe between namespaced and flat selectors.
Roles cache
Cloned role repos are cached under ~/.jackin/roles/ using the selector's namespace and name directly:
~/.jackin/roles/{role-name}/ ← flat role
~/.jackin/roles/{namespace}/{role-name}/ ← namespaced roleExample:
~/.jackin/roles/agent-smith/
~/.jackin/roles/chainargos/agent-brown/GitHub role repository names
By convention, role repos on GitHub are named jackin-{role-name}. This is a GitHub naming convention only — it has no effect on Docker container names or image tags.
https://github.com/ChainArgos/jackin-agent-brown
https://github.com/jackin-project/jackin-the-architect
https://github.com/jackin-project/jackin-agent-smithWhen jackin role new scaffolds a new role repo, it creates the directory at:
{projects_dir}/{namespace}/jackin-{role-name} ← namespaced
{projects_dir}/jackin-{role-name} ← flatCLI selector formats
jackin hardline, jackin eject, and jackin purge accept three forms:
chainargos/agent-brown ← role selector: finds running containers for this role
jk-1vft0hkh-agentbrown ← full container name: exact match
1vft0hkh ← instance ID: resolved via the instance indexWhen a role selector matches exactly one running container, the command proceeds directly. When it matches multiple containers, the command fails with an error that lists the matching container names and asks the operator to pass a specific container name or instance ID instead.