# Environment discovery

`hlix import` treats the repository, its local configuration, and the invoking process environment as one migration source. It does not rely on a single framework detector and it does not silently discard credentials.

The result is an integrity-bound snapshot plus a declarative environment plan. Source files and Git history move in the Git bundle. Protected files and secret values take a separate encrypted path.

## Prerequisites

- The CLI is [installed](/getting-started/install/) and [authenticated](/getting-started/authentication/)
- The shell you run `hlix import` from holds the environment values the project expects — for a key declared or referenced by the project but absent from a file, the invoking process is where hlix looks
- You are prepared to read the dry-run report before approving anything

## The model

1. **Contain the scan.**

   Hlix resolves one real project root, applies Git and hlix ignore rules, refuses symlink traversal and nested repositories, and enforces size and file-count limits.

2. **Read explicit environment intent first.**

   Cursor environment configuration and Dev Container lifecycle settings outrank inferred commands. Docker, Compose, Gitpod, Procfile, Buildpacks, Railpack, Nixpacks, deployment-platform files, version managers, language manifests, and lockfiles provide additional evidence.

3. **Infer only missing pieces.**

   Package-manager locks and standard manifests can supply install, build, start, runtime, and port hints. Every inference records its source and confidence; repository commands are never executed during the local scan.

4. **Resolve protected configuration.**

   Hlix collects recognized project-local dotenv and credential files and key names explicitly required by environment or MCP configuration. It also observes environment references in project files and collects matching local values when present. Missing explicitly declared values block import; a missing source-code observation produces a warning because the application may provide a default or use it only in another environment. Hlix control-plane variables are never collected from the invoking process.

5. **Review once per import invocation, then bind that exact scan.**

   The report names evidence, setup commands, required and collected secret keys, protected paths, quarantined resources, and blockers. A real import uses one authoritative scan for its prompt, manifest, and upload; it does not rescan after approval.

## Detection order

| Priority | Evidence | What hlix uses |
| --- | --- | --- |
| 1 | `.cursor/environment.json` | install, start, terminal, and working-directory intent |
| 1 | `.devcontainer/devcontainer.json`, `devcontainer.json` | lifecycle setup, forwarded ports, container/remote variables, and declared secret names |
| 2 | Docker, Compose, `.gitpod.yml`, `Procfile` | explicit platform and process evidence; unparsed commands remain visible for review |
| 2 | `project.toml`, `railpack.json`, `nixpacks.toml`, `Aptfile` | Buildpack and build-plan intent |
| 2 | `fly.toml`, `railway.json`, `render.yaml`, `vercel.json`, `netlify.toml` | deployment-platform evidence without pretending every field is portable |
| 3 | `package.json`, lockfiles, Python manifests, `go.mod` | package manager, runtime, dependency installation, build, and start inference |
| 4 | `.node-version`, `.nvmrc`, `.python-version`, `.tool-versions`, `mise.toml` | pinned Node.js, Python, and Bun runtime versions |
| 5 | repository references such as `${DATABASE_URL}` | observed environment key names and private-port hints |

Explicit configuration fills the plan first. Lower-priority detectors fill gaps rather than replacing reviewed intent. Repeated install commands are deduplicated.
**Detection is not execution:** A setup command can run dependency lifecycle scripts and arbitrary repository code. Hlix records commands locally, displays them in the trust review, and runs approved setup only inside the project's isolated Coding Workspace.

## Secret collection without source leakage

Hlix separates four concepts that other environment products often combine:

| Concept | Example | Cloud handling |
| --- | --- | --- |
| Required key name | `DATABASE_URL` declared by Dev Container or MCP config | recorded in the manifest; absence blocks import |
| Observed key name | `OPTIONAL_API_URL` referenced by code | matching local value is collected; absence is a warning |
| Secret value | the local value of `DATABASE_URL` | sent only during authenticated finalization and encrypted at rest |
| Protected file | `.env.local`, `.netrc`, cloud credentials | encrypted separately; excluded from the Git snapshot |
| Quarantined executable config | MCP, agent, or skill definition | encrypted and preserved, but inactive until explicit import |

The dry-run and JSON report contain key names and paths, never values. Plaintext secret values are not placed in Git, the bundle manifest, CLI arguments, or progress logs.

User ignore rules do not hide recognized protected files or quarantined resources:
hlix still discovers them inside paths ignored by Git or `.hlixignore` and keeps
them out of the Git bundle. Hard built-in exclusions for dependency stores,
build output, VCS internals, and `.hlix/` are not traversed.

Common protected sources include dotenv profiles, npm and network credentials, Docker registry configuration, AWS and Google application credentials, Cargo and Python registry credentials, and project MCP authentication references. When a declared or observed project key exists only in the invoking shell, Hlix collects that value under the same key instead of asking the developer to re-enter it. Ambient runtime values such as `CI`, `HOME`, `PATH`, `PORT`, and `NODE_ENV`, plus every `HLIX_*` control-plane value, are excluded from this implicit collection path.

`.envrc` is preserved as a protected file. Hlix reads literal assignments without executing the file. Dynamic assignments such as `$(op read …)` always produce a key-only non-execution warning; if direnv has already resolved that key into the invoking process, Hlix collects the resolved value. Only a missing resolved value blocks import. Root assignments take precedence over nested files, and a dynamic key is resolved only from the invoking environment, never from an unrelated nested literal.
**Complete for the project, not the entire laptop:** Zero setup means collecting protected files inside the selected repository and local values for keys the project declares or references. Hlix deliberately does not sweep unrelated shell variables, home-directory credentials, browser stores, SSH agents, or cloud profiles the repository never names. That would turn project import into machine-wide credential exfiltration.

## Patterns adopted from established tools

Hlix combines proven pieces rather than inventing a proprietary environment-file format for every stack:

- [Cursor cloud environments](https://cursor.com/changelog/cloud-in-agents-window) separates machine setup from the checked-out workspace and models reusable `.cursor/environment.json` snapshots for cloud agents.
- [Dev Containers](https://containers.dev/) provides a portable repository-owned environment description and ordered lifecycle hooks.
- [GitHub Codespaces](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/configuring-dev-containers/specifying-recommended-secrets-for-a-repository) lets a repository declare required secret names, while [prebuilds](https://docs.github.com/en/codespaces/prebuilding-your-codespaces) move expensive setup off the startup path.
- [Gitpod tasks](https://www.gitpod.io/docs/configure/workspaces/tasks) separates preparatory, idempotent initialization, and long-running start commands.
- [Railpack](https://railpack.com/architecture/overview), [Nixpacks](https://nixpacks.com/docs/how-it-works), and [Cloud Native Buildpacks detection](https://buildpacks.io/docs/for-platform-operators/concepts/lifecycle/detect/) demonstrate ordered source detection that emits a reviewable build plan.
- [Vercel framework detection](https://vercel.com/docs/project-configuration) shows the same explicit-config-first, conventional-source-second pattern, while [`vercel env pull`](https://vercel.com/docs/cli/env) makes environment synchronization a separate operation.
- [1Password](https://developer.1password.com/docs/cli/secrets-scripts/), [Infisical](https://infisical.com/docs/documentation/platform/secrets-mgmt/concepts/secrets-delivery), and [Doppler](https://docs.doppler.com/docs/cli) demonstrate runtime secret injection without committing values. Hlix adopts that protected lane while also migrating reviewed project-local secret files.

The Hlix-specific layer is the migration boundary: one CLI review carries the source, history, configuration, and protected local state into a workspace-scoped cloud project while preserving revision identity for later `push`, `pull`, and `sync`.

## Review the actual plan

```bash
hlix import . --dry-run
```

For automation, keep the report private because paths and key names can reveal architecture even though values are excluded:

```bash
hlix import . --dry-run --json > /tmp/hlix-import-plan.json
```

If the report is correct, run the real import interactively or use `--yes` in a
non-interactive job. That new invocation performs a fresh authoritative scan;
the earlier dry-run is evidence for review, not a reusable approval token. The
real import binds its own prompt and upload to one scan, and `--yes` cannot
bypass missing secrets, unsafe paths, history findings, integrity failures, or
size limits.

## If the plan is wrong

- **The wrong dotenv profile is active.** Pass `--env-file <path>`; every other profile is still preserved encrypted.
- **A required key is missing** and import blocks. Add the value to the declared source, or to the invoking shell, and scan again — a *declared* key is fatal, an *observed* one is only a warning.
- **A `.envrc` key resolved to nothing.** A dynamic assignment such as `$(op read …)` is never executed. Let direnv resolve it into your shell first, then re-run the scan.
- **A setup command you do not recognise** appears in the review. That is the point of showing it verbatim. Do not approve it; remove or fix the source file first.
- **The stack or install command is wrong.** Override with `--stack`, or add explicit intent in `.cursor/environment.json` or a Dev Container file — explicit configuration outranks every inference.
- **Confidence is low with no evidence listed.** The scanner found no recognised configuration. Add one explicit source rather than relying on inference.

## Next steps

[Import a project](/cli/import/)
  [Secrets & protected files](/security/secrets/)
  [hlix import reference](/reference/cli/import/)
  [Import trust model](/security/trust-model/)