{"slug": "one-dotvault-pull-the-same-env-everywhere-laptop-ci-cloud-dev-environments", "title": "One dotvault pull, the same .env everywhere: laptop, CI, cloud dev environments", "summary": "A developer released dotvault, a CLI that syncs .env secrets to laptops, CI pipelines, servers and cloud development environments such as GitHub Codespaces, Codex cloud and Claude Code on the web through a single `dotvault pull` command. The tool, installed via `npm i -g @earthlink/dotvault` and requiring Node.js 20 or later, stores values in one project and supports `dotvault run -- <command>` for environments where no .env file should be written, with service tokens handling unattended agent and CI use. The walkthrough was run on October 18, 2026 against CLI version 0.15.7 in a fresh node:20 Docker container, and the developer says dotvault will be released free of charge when the series ends.", "body_md": "This is part 2 of the series \"dotvault, Start to Finish: One Command from Your Laptop to CI, Your Team, and Your AI Agents.\" dotvault will be released free of charge when this series ends.\n\nA `.env` rarely lives in one place. The same variables are needed in CI, on the server that runs the app, and in cloud development environments such as GitHub Codespaces, Codex cloud in ChatGPT and Claude Code on the web. With dotvault, every one of those places gets its values the same way: `dotvault pull`, one command. Install, login and init happen once per place. After that it is pull, or `run` if you want no `.env` file.\n\nAny environment that has Node.js and can reach the internet over HTTPS runs the same steps. The terminal screens in this part come from a fresh `node:20` Docker container with nothing carried over from my own machine. This is part 2 of 12, run on October 18, 2026 against the production console at app.dotvault.io and the latest published CLI (0.15.7). Every step has its screen.\n\n`dotvault pull`.` project-config.json` that `init` writes, a fresh clone does not even need `run`, the next start already uses it.`.env` and leaves alone your own lines for keys dotvault does not hold.`dotvault run -- <command>` skips the The values live in one dotvault project. Only the way each place receives them differs.\n\n| Place | Example | How it gets the values | \n|---|---|---|\n| Your machine | Mac, Windows, Linux | Log in, then pull or run (this part) | \n| Cloud dev environment with a human at the terminal | GitHub Codespaces | Exactly as on your machine (this part) | \n| Cloud dev environment where an AI agent works on its own | Codex cloud in ChatGPT, Claude Code on the web | Service token, then the same pull or run (issuing and passing the token: parts 7 and 8) | \n| CI/CD | GitHub Actions and the like | Service token, then the same pull or run (part 7) | \n| Server runtime | The server or container that runs the app | Service token, then the same pull or run (issuing and passing the token: part 7) | \n\n| Command | When | What it does | \n|---|---|---|\n| `npm i -g @earthlink/dotvault` | Once per place | Installs the CLI | \n| `dotvault login` | Once per place (again only when the refresh token expires; see step 2) | Logs in with email and password | \n| `dotvault init` | Once per project folder (not needed in a clone once committed) | Binds the folder to a project | \n| `dotvault pull` /`dotvault run -- <command>` | Every time you need the values | Writes the `.env` / starts a command with the values | \n\nCreating the project and its keys in the console is also once per project. The rest of this part walks through the first time, in order.\n\n`npm i -g` now installs 0.15.8; on October 23 I ran the same steps on 0.15.8, and the differences are the version number, the marker line written into `# BEGIN: dotvault (managed by dotvault)`), the wording in brackets of the network error, and that a hand-written line for a key pull also writes is now commented out (see step 5), within what the steps of this part show (key and file counts are higher now because later parts add keys, files and Global Keys). The terminal is a Linux container (Docker `node:20`) with no earlier configuration and a keychain (gnome-keyring and libsecret) added. On macOS the commands are the same (the screens in this part were not taken on macOS; the first login may show a dialog asking to allow Keychain access).`echo $?` line.`KEY=VALUE` lines. Part 1 has the full glossary.\nNode.js 20 or later is the only requirement, on your machine or in a cloud dev environment's terminal.\n\n```\nnpm i -g @earthlink/dotvault\ndotvault --version\n```\n\nnpm prints one deprecation warning for a dependency. The install still completes. If `dotvault --version` prints a version number, you are ready.\n\n`dotvault login` asks for Email, then Password. The password is not echoed.\n\n```\ndotvault login\ndotvault whoami\n```\n\n[. Token expires in 3600s. Refresh token saved.\"; `dotvault whoami` prints the email, the token expiry and \"org: org_personal_… Personal (personal, org_admin)\".\"/>](https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb75iizzzietg0wwlv1ng.png)\n\nThe token goes into the OS keychain (Keychain on macOS), not into a plain-text file. \"Token expires in 3600s\" sounds short, but a refresh token is saved next to it, so you are not logging in every hour. The refresh token lasts 30 days; when it runs out, run `dotvault login` again.\n\n`dotvault whoami` shows your email and the organisation you are in. At this point a Personal organisation already exists for you; it was created on your first login. Nobody had to set it up.\n\nThe contents of the `.env` are prepared in the browser console at app.dotvault.io, with the same email and password. In a Personal organisation the sidebar shows eight items under a PERSONAL heading. The team features (Teams, My Organizations) are not there.\n\nOpen Projects and press New project. The modal asks for one thing, a name: lowercase letters, digits, hyphens and underscores, starting with a letter or digit. I used `demo-app`. Project names are unique across dotvault, so `demo-app` is taken; pick your own.\n\nAfter Create, the list shows `demo-app` with three environments already attached: development, staging, production. Part 3 is about those. This part only uses development.\n\nOpen `demo-app`. The Keys tab has development selected and no keys yet, so it says \"No keys in development yet.\" The Selected key panel on the right says \"Click a key on the left to inspect.\"\n\nPress + Add key and an inline row appears with Key name and Value. Fill both, press Add. Three times for `DATABASE_URL`, `API_BASE_URL` and `SMTP_PASSWORD`.\n\nClick a key name and the Selected key panel shows its path (development/env/DATABASE_URL), a description field, a reveal button, delete, and a button that moves the key to Common, a shared place for keys that every environment can use. Common is covered in part 3. Values are not shown in the list. They appear only when you press the reveal button. The button says \"audit-logged\"; what the audit record actually holds is checked in part 10.\n\nThat is all the console work. When a value changes later, this is where you change it. Back to the terminal.\n\nIn the project folder, `dotvault init` writes one file, `project-config.json`. The project name defaults to the folder name; `dotvault init --name <name>` overrides it.\n\n```\ncd demo-app\ndotvault init\ncat project-config.json\n```\n\nThere are no secrets in this file: the project name, the API URL, the list of files to write, the default environment. Commit it. Any clone, in CI or in a cloud dev environment, can then pull without running `init`.\n\n`dotvault pull` runs three stages on one progress bar, authenticating, fetching, writing, and finishes with the number of keys written.\n\nBefore pulling, I put a few hand-written lines in `.env` (a comment, `PORT` and `DEBUG`) to show what happens to them.\n\n```\ndotvault pull\ncat .env\nls -l .env\n```\n\nThree things to notice.\n\n`# BEGIN:` and `# END:`. The next pull replaces that block. That is what \"Markers preserved.\" means. On 0.15.8, the current version, a line outside the block for a key that pull also writes (say a hand-kept `DATABASE_URL=`) is turned into a comment starting with `# dotvault: moved into the managed block below:`, and pull prints a warning. Nothing is deleted; the value inside the block is the one that applies. When you move a hand-kept `-rw-------` means your user can read and write it and no other user on the machine can read it.\nAfter you change a value in the console, the same `dotvault pull` in any place replaces the marked block with the current values.\n\nIf you would rather not have a `.env` on disk, `dotvault run -- <command>` puts the variables from this part into that one process's environment without writing a `.env`. One exception: if the project holds whole-file secrets (such as `.npmrc`, covered in part 5), run writes those files to disk while the command runs. They are removed when the command ends normally, but can be left behind if you stop dotvault itself, for example with Ctrl-C. Part 5 covers this.\n\n```\ndotvault run -- printenv DATABASE_URL\ndotvault run -- sh -c 'echo \"$API_BASE_URL\"'\n```\n\nWhen to use which:\n\n|  | `dotvault pull` | `dotvault run -- <command>` | \n|---|---|---|\n| `.env` on disk | Yes (the marked block only) | No | \n| Who sees the values | Anything that reads the file | That one process | \n| Fits | Tools and frameworks that expect a `.env` , start scripts written by other people | Local development ( `dotvault run -- npm run dev` ), CI, anywhere you do not want a plain-text`.env` on disk (whole-file secrets: part 5) | \n| After a value changes | Pull again | The next start uses the new value | \n\nFor local development, use run. If there is no plain-text `.env`, it cannot be committed by accident and it does not end up in a backup.\n\nIn a folder with no `project-config.json`, pull and run still work if you name the project. A bare `dotvault list` shows the projects you can read.\n\n```\ndotvault list demo-app\ndotvault pull demo-app\n```\n\nPutting the project name straight after the command (`dotvault pull demo-app`) and `--project demo-app` mean the same thing. `init` is only for pinning a folder to a project.\n\nA failure prints `✖`, a code in capitals, and sets a fixed exit code (` echo $?`). Scripts can branch on the exit code. The table lists the causes seen in this part and what to check first; the same code can have other causes too.\n\n| code | exit | What happened | What to do | \n|---|---|---|---|\n| `AUTH_REQUIRED` | 3 | Not logged in | `dotvault login` | \n| `PERMISSION_DENIED` | 4 | No permission on that project or environment, or no project by that name | First check the project name for typos: a project name that does not exist also returns this code. If the name is right, ask an org admin to grant access in the console. A service token also gets it when it reads an environment or project it was not allowed (part 7). Permissions are covered in part 9 | \n| `PROJECT_NOT_FOUND` | 5 | No secrets for that project and environment (here: staging, which had no keys yet) | Check your project's name with `dotvault list` , and in the console whether that environment has keys | \n| `VALIDATION_ERROR` | 6 | No `project-config.json` , or something missing from the command | Name the project, or run `dotvault init` in that folder | \n| `NETWORK_ERROR` | 2 | The API URL cannot be reached | Check the connection and `apiUrl` in`project-config.json` | \n| `BAD_PROJECT` /`BAD_ENV` | 1 | Project name in the wrong format (capitals), or an environment the project does not have | Use a lowercase name; use development, staging, production, or an environment you add in part 3 | \n\n`PROJECT_NOT_FOUND` also appears when the project exists but that environment has no keys at all. The second failure in the screen is exactly that: staging, with nothing in it yet.\n\nWhere the OS keychain cannot be used (Linux without libsecret, or a headless container where libsecret is installed but no keychain service is running), the CLI prints a two-line notice and stores the token in `~/.config/dotvault/credentials.json` with mode 600. The commands and the behaviour are the same. The screen below is the same container run without its keychain.\n\nFrom \"Forgot your password?\" on the login screen, enter your email to receive a confirmation code, then enter the code and the new password on the next screen. Passwords need at least 12 characters, with upper and lower case, a digit and a symbol. The form says 8, but the server rule, checked on October 23, 2026, is 12.\n\nUser Settings in the sidebar has a Language select. Choosing one saves immediately and shows \"Saved.\" The setting lives in the browser, not on the account, so another browser starts from its own default.\n\n`dotvault logout` removes the stored token of the account currently in use from this machine (the keychain, or the file where there is no keychain). If no other account is logged in on this machine, `dotvault whoami` then says \"Not logged in.\" If you also logged in with another account, that one is used after logout, so log out of it as well.\n\n[.\"; `dotvault whoami` prints \"Not logged in.\" with exit code 3.\"/>](https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1yaxhbl56lqi44gqv8hd.png)\n\nRegistering and removing multi-factor authentication will be added to this part's appendix once the console has those screens. Switching to a team organisation after an invitation is covered, with its screens, in part 9.\n\nPart 3: \"Three environments plus one shared layer, out of the box: how a dotvault project is shaped.\" The three environments that came with the project, the Common layer, comparing environments, and archiving and deleting a project, one screen at a time.\n\ndotvault stores the secrets in your .env and config files server-side and hands them to any authorised developer, CI job or AI agent with a single command ([https://dotvault.io](https://dotvault.io)). It will be released free of charge when this series ends, and the steps in these articles are the steps you will use on day one.\n\nIf you find this useful, please like and follow.\n\nOur products are listed at [https://www.eln.ne.jp/products](https://www.eln.ne.jp/products)\n\n**EarthLink Network** builds its own products to run the whole company on AI — each one born from a need along the way. See the full index of what we build:\n\n→ [The 18 products EarthLink Network builds in-house](https://dev.to/uehara/the-18-products-earthlink-network-builds-in-house-hb1)\n\nFor more about the company and each product, visit [www.eln.ne.jp](https://www.eln.ne.jp).", "url": "https://wpnews.pro/news/one-dotvault-pull-the-same-env-everywhere-laptop-ci-cloud-dev-environments", "canonical_source": "https://dev.to/uehara/one-dotvault-pull-the-same-env-everywhere-laptop-ci-cloud-dev-environments-aj2", "published_at": "2026-10-25 01:29:54+00:00", "updated_at": "2026-10-25 01:42:21.131954+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents", "ai-tools"], "entities": ["dotvault", "GitHub Codespaces", "Codex cloud", "ChatGPT", "Claude Code", "GitHub Actions", "Node.js", "Docker"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/one-dotvault-pull-the-same-env-everywhere-laptop-ci-cloud-dev-environments", "markdown": "https://wpnews.pro/news/one-dotvault-pull-the-same-env-everywhere-laptop-ci-cloud-dev-environments.md", "text": "https://wpnews.pro/news/one-dotvault-pull-the-same-env-everywhere-laptop-ci-cloud-dev-environments.txt", "jsonld": "https://wpnews.pro/news/one-dotvault-pull-the-same-env-everywhere-laptop-ci-cloud-dev-environments.jsonld"}}