Core Concepts
Repository & Storage
Understand which Ghostable files belong in Git, which identity material remains local, and what reviewers can learn from encrypted project state.
Repository-backed state
The .ghostable/ directory is project state, not a local cache. It is intended to be committed, reviewed, branched, and merged with the application:
.ghostable/
├── ghostable.yaml
├── policy.json
├── devices/
├── access-requests/
├── environments/
│ └── production/
│ ├── access/
│ ├── keys/
│ └── values/
├── events/
├── schema.yaml
├── schemas/
└── hygiene.yaml
Values are encrypted, while device, policy, key metadata, access, activity, and suppression records are signed so tampering can be detected. Deleting or hand-editing these files can invalidate the project state; use CLI commands whenever one exists.
Local identity
Each device has an Ed25519 signing key and X25519 encryption key. Public device records are committed. Private material is stored outside the repository:
-
macOS - Keychain service dev.ghostable.identity.<project-id>.
-
Windows - Credential Manager target dev.ghostable.identity.<project-id>.
-
Linux / Unix - ${XDG_CONFIG_HOME:-~/.config}/ghostable/identities/<project-id>.json.
-
GHOSTABLE_KEYSTORE - Optional identity-store override used for controlled environments and testing.
File-backed identity directories use 0700 permissions and identity files use 0600 on Unix-like systems.
Metadata visibility
Encryption protects secret values, not all context. Repository readers may see project and environment names, public device labels, access roles, variable key names, annotations, change reasons, event timing, and schema descriptions.
Git workflow
Review Ghostable changes alongside the code that consumes them:
$ ghostable validate --env staging
$ ghostable review
$ git diff -- .ghostable
$ git add .ghostable && git commit -m "Update staging configuration"
Signed records do not remove the need for code review. A valid signature proves which authorized identity produced a record; it does not prove that the change is wise or that a reviewer should merge it.
Resolve Git conflicts
Treat each signed JSON record as an indivisible unit. Never splice signatures, policy fields, wrapped keys, ciphertext, or event content from both sides of a conflict: the resulting record will not verify, and mixing environment-key generations can make state unreadable.
- Stop Ghostable writes and identify every unresolved path under
.ghostable/. - Choose one complete, reviewed version of each conflicted record. For rotations, keep the policy, environment key metadata, grants, and values from the same authoritative generation.
- Finish the merge or rebase, then rerun the discarded Ghostable operation from the resolved branch instead of recreating its JSON by hand.
- Run status, validation, review, and a normal Git diff before committing the resolution.
$ git diff --name-only --diff-filter=U -- .ghostable
$ ghostable status
$ ghostable validate --env staging
$ ghostable review
$ git diff -- .ghostable
Multiple checkouts
Ghostable registers one local identity against the project's canonical repository root. Opening the same project ID from a different checkout or worktree will require ghostable access join for that path instead of silently reusing the identity registered elsewhere. Treat the worktree as a separate device request, or perform Ghostable writes from the registered checkout and use the other worktree for code-only changes.