Skip to content

Secrets & protected files

hlix does not solve local-to-cloud by dropping secret files. It moves them through a separate protected-data path so the cloud environment can behave like the local project without committing credentials into its Git history.

Recognized protected files include:

  • .env and environment-specific dotenv files, except examples/templates
  • .envrc, with literal assignments collected without executing shell code
  • credential and service-account JSON
  • .npmrc and .pypirc
  • private-key and certificate-key formats such as .pem, .key, .p12, and .pfx
  • terraform.tfvars and terraform.tfvars.json
  • regular text files containing a high-confidence private-key or provider-token pattern
  • quarantined agent, skill, and MCP configuration

The dry-run report lists paths and key names, never values:

Terminal window
hlix import . --dry-run --json

When no override is provided, hlix composes development dotenv files in this order:

  1. .env
  2. .env.development
  3. .env.local
  4. .env.development.local

Later assignments win. Use an explicit file when the inferred development environment is not the one intended for cloud:

Terminal window
hlix import . --dry-run --env-file .env.cloud-development
hlix import . --env-file .env.cloud-development

Literal .envrc assignments join the selected development secret set. Dynamic shell expressions are not executed during scanning. If your active shell already contains the resolved project key—for example after direnv called 1Password, Infisical, or Doppler—Hlix collects that resolved value. Otherwise import blocks so you can activate the environment before retrying.

The seven steps cross three trust zones: your machine records only metadata and sends protected files separately, the backend verifies every hash and encrypts at rest, and the Coding Workspace revalidates the bytes, writes them 0600, and strips them from every commit.

A seven-step path across three trust zones: your machine records only metadata and sends protected files separately, the backend verifies and encrypts them, and the Coding Workspace revalidates, writes them 0600, and strips them from every commit.Your machine1 · scan reads bytes; manifest records path, size, hash, key names only2 · protected files leave the Git snapshot, sent over authenticated TLSBackend3 · every path, kind, size and SHA-256 must match the manifest4 · encrypted at rest with AES-GCM under the deployment key5 · decrypted for an authorized task, sent via the sandbox filesystemCoding Workspace6 · bytes revalidated; written mode 0600; paths pinned in Git exclude7 · commit staging removes every protected path as a final guard
  1. The local scanner reads protected bytes into memory and records only path, kind, size, hash, and key names in the manifest.
  2. Protected files are omitted from the Git snapshot and sent separately over the authenticated TLS API request.
  3. The backend checks that every supplied path, kind, size, and SHA-256 exactly matches the manifest.
  4. Values and file contents are encrypted at rest with AES-GCM under the deployment’s secrets-encryption key.
  5. For an authorized task, the backend decrypts the protected project files and sends them in the task payload through the sandbox filesystem—not command arguments.
  6. The sandbox validates the bytes again, refuses traversal and symlink targets, writes files with mode 0600, and pins their exact paths in Git exclude rules.
  7. Commit staging explicitly removes every protected path as a final guard.

The same integrity checks apply in reverse during hlix pull.

Encryption at rest is not end-to-end encryption. The hlix backend must be able to decrypt values for authorized project work and authenticated pull. A project task, its selected coding agent, and repository setup commands can read materialized values inside that project’s Coding Workspace.

Use least-privileged, environment-specific credentials. Do not import a personal all-access token when a project-scoped development token will work.

Secret resolution is fail-closed. If protected data cannot be decrypted or a required secret cannot be resolved, task dispatch stops instead of starting with an empty or partial environment.

Known secret values and protected-file contents are included in execution-log redaction. Redaction covers exact values, lines, and dotenv-style assignment values. It is defense in depth—not a reason to print credentials. Encoded, transformed, split, or novel values may not match exact-value redaction.

Excluding a current .env file does not erase an older committed value. Import scans up to 10,000 commits for sensitive paths and high-confidence patterns and blocks by default when it finds them.

If a credential entered Git history:

  1. Rotate or revoke it first.
  2. Decide whether history must be rewritten.
  3. Verify the rewritten repository independently.
  4. Re-run hlix import . --dry-run.

--history preserve retains the history despite findings. It is an informed retention decision, not remediation.

Protected files participate in the project manifest. Edit them locally, then create a new revision:

Terminal window
hlix push

Pulling a cloud revision restores protected bytes with owner-only permissions:

Terminal window
hlix pull

If both local and cloud protected state changed, hlix sync refuses to guess. Review the conflict and select a direction explicitly.

  • A task fails immediately with an empty credential. The key name was imported but its value was not. Add the value at its declared source and push a new revision; MCP and environment configuration carry key names only.
  • hlix import blocks on a missing key. A key the project declares is fatal; one it only references in source is a warning. Provide the declared value, or remove the declaration.
  • The wrong dotenv profile was activated. Re-import or push with --env-file <path>; every other profile was preserved encrypted, so nothing was lost.
  • A .envrc key is empty. Dynamic assignments are never executed. Let direnv resolve it into your shell, then scan again.
  • hlix sync refuses after protected state changed on both sides. It does not guess. Review the conflict and choose a direction with push or pull explicitly.
  • A value you rotated at the provider still works in a task. The project holds its own encrypted copy. Rotating at the provider is not the same as updating the project; push a new revision.
  • A secret appears in a dry-run report. It does not — only key names, hashes, sizes, and paths do. If you believe you are seeing a value, treat it as a defect and report it rather than sharing the report.
  • Use development credentials with narrow project scope.
  • Rotate anything that was exposed in source control, logs, chat, or issue trackers.
  • Keep the deployment encryption key configured, access-controlled, and backed up according to your recovery policy.
  • Treat access to project manage/sync APIs as access to protected project material.
  • Review MCP environment key names before activation.
  • Delete stale credentials at the provider, not only from a dotenv file.