cd /news/developer-tools/one-dotvault-pull-the-same-env-every… · home › topics › developer-tools › article
[ARTICLE · art-157045] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=↑ positive

One dotvault pull, the same .env everywhere: laptop, CI, cloud dev environments

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.

by read12 min views2 publishedOct 25, 2026

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.

A .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.

Any 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.

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.

Place Example How it gets the values
Your machine Mac, Windows, Linux Log in, then pull or run (this part)
Cloud dev environment with a human at the terminal GitHub Codespaces Exactly as on your machine (this part)
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)
CI/CD GitHub Actions and the like Service token, then the same pull or run (part 7)
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)
Command When What it does
npm i -g @earthlink/dotvault Once per place Installs the CLI
dotvault login Once per place (again only when the refresh token expires; see step 2) Logs in with email and password
dotvault init Once per project folder (not needed in a clone once committed) Binds the folder to a project
dotvault pull /dotvault run -- <command> Every time you need the values Writes the .env / starts a command with the values

Creating 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.

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. Node.js 20 or later is the only requirement, on your machine or in a cloud dev environment's terminal.

npm i -g @earthlink/dotvault
dotvault --version

npm prints one deprecation warning for a dependency. The install still completes. If dotvault --version prints a version number, you are ready.

dotvault login asks for Email, then Password. The password is not echoed.

dotvault login
dotvault whoami

. Token expires in 3600s. Refresh token saved."; dotvault whoami prints the email, the token expiry and "org: org_personal_… Personal (personal, org_admin)"."/>

The 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.

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.

The 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.

Open 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.

After Create, the list shows demo-app with three environments already attached: development, staging, production. Part 3 is about those. This part only uses development.

Open 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."

Press + 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.

Click 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.

That is all the console work. When a value changes later, this is where you change it. Back to the terminal.

In 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.

cd demo-app
dotvault init
cat project-config.json

There 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.

dotvault pull runs three stages on one progress bar, authenticating, fetching, writing, and finishes with the number of keys written.

Before pulling, I put a few hand-written lines in .env (a comment, PORT and DEBUG) to show what happens to them.

dotvault pull
cat .env
ls -l .env

Three things to notice.

# 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. After you change a value in the console, the same dotvault pull in any place replaces the marked block with the current values.

If 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.

dotvault run -- printenv DATABASE_URL
dotvault run -- sh -c 'echo "$API_BASE_URL"'

When to use which:

dotvault pull dotvault run -- <command>
.env on disk Yes (the marked block only) No
Who sees the values Anything that reads the file That one process
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)
After a value changes Pull again The next start uses the new value

For 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.

In 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.

dotvault list demo-app
dotvault pull demo-app

Putting 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.

A 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.

code exit What happened What to do
AUTH_REQUIRED 3 Not logged in dotvault login
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
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
VALIDATION_ERROR 6 No project-config.json , or something missing from the command Name the project, or run dotvault init in that folder
NETWORK_ERROR 2 The API URL cannot be reached Check the connection and apiUrl inproject-config.json
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

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.

Where 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.

From "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.

User 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.

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.

."; dotvault whoami prints "Not logged in." with exit code 3."/>

Registering 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.

Part 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.

dotvault 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). 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.

If you find this useful, please like and follow.

Our products are listed at https://www.eln.ne.jp/products

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:

→ The 18 products EarthLink Network builds in-house

For more about the company and each product, visit www.eln.ne.jp.

── more in #developer-tools 4 stories · sorted by recency
── more on @dotvault 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/one-dotvault-pull-th…] indexed:0 read:12min 2026-10-25 · —