Skip to content

Secrets & protected files

hlix moves your project’s credentials to the cloud without ever committing them. Secret files travel on a separate, encrypted path, so the cloud environment behaves like your local project while its Git history stays free of credentials.

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 holds the resolved value — for example after direnv loaded it from a secret manager such as 1Password or Doppler — hlix collects that value. Otherwise import stops so you can activate the environment and try again.

A protected file crosses three zones: your machine records only metadata and sends the file separately, hlix verifies every hash and encrypts the file at rest, and the Coding Workspace checks the bytes again, writes them readable only by their owner, and keeps them out of every commit.

A seven-step path across three trust zones: your machine records only metadata and sends protected files separately, hlix verifies them and encrypts them under the Workspace's own data key, and the Coding Workspace checks them again, writes them readable only by the job, and keeps them out of every commit.Your machine1 · scan reads bytes; manifest records path, size, hash, key names only2 · protected files leave the Git snapshot, sent over authenticated TLShlix3 · every path, kind, size and SHA-256 must match the manifest4 · encrypted at rest under your Workspace's own data key5 · decrypted only for an authorized job and written into its sandboxCoding Workspace6 · checked again, written readable by the job only, kept out of Git7 · 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. hlix 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-256-GCM under a key unique to your Workspace, so encrypted data copied into another Workspace cannot be decrypted there.
  5. For an authorized task, hlix decrypts the protected files and writes them into the task’s sandbox as files — never as command arguments.
  6. The sandbox validates the bytes again, refuses path traversal and symlink targets, writes the files with owner-only permissions (0600), and excludes their paths from Git.
  7. Every commit removes protected paths once more before it is made, as a final guard.

The same integrity checks apply in reverse during hlix pull.

Encryption at rest is not end-to-end encryption. hlix decrypts values for authorized project work and for an authenticated hlix pull. Inside the project’s Coding Workspace, a task, its coder and the repository’s setup commands can read the values written there.

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

Imported resources reference secrets, they never carry them

Section titled “Imported resources reference secrets, they never carry them”

Agent instructions, skills and MCP configuration are collected as quarantined resources: import preserves their exact bytes encrypted, and activates nothing. Activation is always a separate, explicit command — hlix skill import, hlix agent import, hlix mcp import.

At activation, an MCP server may only name a secret, never contain one:

  • A remote authentication header must be exactly ${KEY}, or one approved scheme followed by it — Authorization: Bearer ${TOKEN}. Extra prefix or suffix text is refused.
  • A sensitive stdio argument must be exactly one complete ${KEY} placeholder.
  • A high-confidence literal token is refused in every argument, whatever it is called.

The placeholder is resolved from the project’s encrypted secrets at task time, so the value lives in one place and the configuration stays safe to read, diff and share. Import skills, agents & MCP covers the full activation path, including the two extra gates on MCP transports.

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 redacted from execution logs, including exact values, whole lines and dotenv-style assignments. Redaction is a safety net, not a reason to print credentials: an encoded, transformed or split value may not match.

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.
  • MCP remote headers must use ${KEY} placeholders; literal credentials are refused. The header carried a real token. Move the value into the project’s secrets and reference it by name.
  • MCP remote header <name> must be a strict environment placeholder template — the header referenced a key but wrapped it in extra text. It must be exactly ${KEY}, or one approved scheme followed by it.
  • MCP stdio arguments must not contain literal credentials or MCP stdio secret arguments must use a complete environment placeholder. A command-line argument held a token, or a partial placeholder. A sensitive argument must be exactly one complete ${KEY}.
  • An imported skill, agent or MCP server has no effect. That is quarantine working, not a failure. Nothing imported is active until you activate it explicitly.
  • Use development credentials with narrow project scope.
  • Rotate anything that was exposed in source control, logs, chat, or issue trackers.
  • 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.