Getting Started

What is Tokengate?

Tokengate is an end-to-end encrypted environment variable manager for development teams. It replaces insecure practices like sharing .env files over Slack, email, or password managers with a purpose-built CLI and web dashboard.

Every environment has its own encryption password. Secrets are encrypted on your machine before they ever leave it. The Tokengate server stores only ciphertext and can never read your plaintext values. This is true zero-knowledge architecture.

How It Works

Tokengate uses a layered encryption model built on Web Crypto API standards:

  • Each workspace has a workspace key (AES-256) generated at creation time
  • The workspace key is wrapped per-device using RSA-OAEP 2048-bit key pairs
  • Revision data is encrypted with a random per-revision data key (AES-256-GCM)
  • Each data key is wrapped by the workspace key using AES-KW
  • Content integrity is verified with SHA-256 content hashes

The result: your secrets are encrypted client-side, transmitted as ciphertext, and stored as ciphertext. Only devices with the workspace key can decrypt them.

Quick Start

1

Install the CLI

Install globally with Bun or npm. The CLI requires the Bun runtime.

2

Sign in with your browser

Run tokengate login to authenticate via the web dashboard. A device key pair is generated locally and registered with your account.

3

Initialize your project

Run tokengate init in your project directory. The wizard scans for .env files, lets you select a workspace and project, and maps each file to a remote environment.

4

Push and pull

Use tokengate push to encrypt and upload your local files, or tokengate pull to download and decrypt the latest revision from your team.

quick start
$ bun add -g @tokengate/cli
$ tokengate login
> Opening browser for authentication...
Signed in as sarah@acme.dev

$ tokengate init
Scanning for .env files...
Found: .env, .env.local, .env.production
Project linked to acme-corp / web-app

$ tokengate push
.env rev #1
.env.local rev #1
.env.production rev #1

Installation

The Tokengate CLI is distributed as an npm package. Install it globally so the tokengate command is available everywhere.

With Bun (recommended)

install
$ bun add -g @tokengate/cli

With npm

install
$ npm install -g @tokengate/cli

Bun Required

The Tokengate CLI requires the Bun runtime to be installed on your system. Bun provides the native crypto APIs and fast startup time the CLI depends on. Install Bun at bun.sh if you do not already have it.

Verify Installation

verify
$ tokengate help

tokengate - encrypted env sync

Commands:
tokengate Smart mode (interactive menu)
login [label] Authenticate this device
logout Clear stored credentials
init Initialize project in current directory
status Show sync status for mapped files
push Encrypt and upload changed files
pull Download and decrypt remote changes
history Show revision history
workspaces List accessible workspaces
help Show this help message

CLI Commands

tokengateSmart Mode

Running tokengate with no arguments enters smart mode. If you are not signed in or the current directory has no project configuration, it launches the guided setup wizard. If the project is already configured, it presents an interactive menu to push, pull, view history, or check status.

tokengate
$ tokengate

tokengate web-app

? What do you want to do?
> Push env files to remote
Pull env files from remote
View revision history
Show status
Re-initialize / change project
tokengate login [label]Authenticate Device

Authenticates the current device by opening your browser to the Tokengate web dashboard. A unique RSA-OAEP 2048-bit key pair is generated locally for this device. The public key is registered with your account while the private key stays on your machine. The optional [label] argument sets a human-readable name for the device (defaults to your hostname).

login
$ tokengate login macbook-pro

tokengate device login

Opening browser for authentication...
If the browser does not open, visit:
https://tokengate.dev/cli/auth?state=...

Waiting for authorization...

Device registered as macbook-pro
Signed in as sarah@acme.dev
Run tokengate init to set up a project.
tokengate logoutClear Credentials

Removes all stored credentials from the current device, including the access token, device key pair, and cached workspace keys. This does not affect your account or other devices. After logging out, run tokengate login to re-authenticate.

logout
$ tokengate logout

Credentials cleared.
Run tokengate login to sign in again.
tokengate initInitialize Project

Initializes the current directory as a Tokengate project. The wizard scans for all .env files in the working directory, prompts you to select a workspace and project (or create new ones), then maps each discovered file to a remote environment. A .tokengate.json config file is created to store the mappings.

init
$ tokengate init

tokengate project setup

Scanning for .env files...
Found: .env, .env.local, .env.production

? Select workspace
> acme-corp
personal-projects
+ Create new workspace

? Select project
> web-app
api-server
+ Create new project

? Map .env to environment
> default

? Map .env.local to environment
> local

? Map .env.production to environment
> production

Project linked to acme-corp / web-app
Config written to .tokengate.json
tokengate statusSync Status

Displays the current sync status for all mapped .env files. Shows which files are in sync with the remote, which have local changes pending push, and which have remote updates available to pull. Status is determined by comparing SHA-256 content hashes.

status
$ tokengate status

tokengate web-app

File Environment Status
──────────────────────────────────────────
.env default synced
~ .env.local local local changes
.env.production production synced
tokengate pushEncrypt & Upload

Scans all mapped .env files, identifies which have changed since the last sync (via content hash comparison), and uploads the changed files. Each file is encrypted client-side with the workspace key before transmission. A new revision is created for each pushed file.

push
$ tokengate push

Scanning .env files...

File Status
─────────────────────────
.env synced
~ .env.local changed
+ .env.staging new

? Push 2 files? Yes

Encrypting...
.env.local rev #3
.env.staging rev #1
tokengate pullDownload & Decrypt

Checks the remote for each mapped environment, compares content hashes, and downloads any files where the remote has a newer revision. Files are decrypted client-side using the workspace key and written to disk, overwriting the local version.

pull
$ tokengate pull

Checking remote...

File Status
─────────────────────────
.env remote updated
.env.local synced
.env.production remote updated

Decrypting...
.env rev #5
.env.production rev #8

All files up to date.
tokengate historyRevision History

Shows the revision history for each environment mapped in the current project. Displays the revision number, timestamp, content hash, and which user pushed each revision. Useful for auditing changes and understanding when secrets were last updated.

history
$ tokengate history

production 4 revisions

#4 2025-03-10 14:32 a3f8c1d sarah
#3 2025-03-09 11:18 b7e2f4a alex
#2 2025-03-07 16:45 c1d9e3b sarah
#1 2025-03-05 10:00 d4a6f8c james
tokengate workspacesList Workspaces

Lists all workspaces your account has access to, including your role in each workspace (owner or member). Useful for verifying which workspaces are available before running tokengate init.

workspaces
$ tokengate workspaces

Your workspaces:

> acme-corp owner
personal owner
freelance-2025 member

Configuration

Tokengate uses two configuration files: a project config in your repository and a global config on your machine.

.tokengate.json (Project Config)

Created by tokengate init in the root of your project directory. This file should be committed to version control so all team members share the same project and environment mappings. It does not contain any secrets.

{ "workspaceId": "k57abc123def...", "workspaceName": "acme-corp", "projectId": "k57xyz789ghi...", "projectName": "web-app", "mappings": { ".env": { "secretSetId": "k57...", "environmentId": "k57...", "environmentName": "default" }, ".env.local": { "secretSetId": "k57...", "environmentId": "k57...", "environmentName": "local" }, ".env.production": { "secretSetId": "k57...", "environmentId": "k57...", "environmentName": "production" } } }
FieldDescription
workspaceIdThe Convex document ID of the workspace this project belongs to
workspaceNameHuman-readable workspace name for display in CLI output
projectIdThe Convex document ID of the project
projectNameHuman-readable project name for display in CLI output
mappingsObject mapping local filenames to their remote environment. Each entry contains secretSetId, environmentId, and environmentName

Global Config

Stored at ~/.config/tokengate/config.json with file permissions 0600 (owner read/write only). This file contains your device credentials and should never be shared or committed to version control.

FieldDescription
versionConfig schema version (currently 3)
appUrlThe Tokengate web app URL (default: https://tokengate.dev)
convexUrlThe Convex backend URL, obtained during login
deviceIdUnique identifier for this device
deviceLabelHuman-readable device name set during login
accessTokenAuthentication token for API requests
privateKeyRSA-OAEP private key (JWK format) for unwrapping workspace keys
publicKeyRSA-OAEP public key (JWK format) registered with the server

Environment Variables

VariableDescription
TOKENGATE_APP_URLOverride the default Tokengate web app URL. Useful for self-hosted deployments or local development. Defaults to https://tokengate.dev

Multi-file Sync

Most projects use multiple .env files for different purposes: .env for shared defaults, .env.local for developer overrides, .env.production for production secrets. Tokengate handles all of them in a single workflow.

File Scanning

When you run tokengate init or tokengate push, the CLI scans the current working directory for files matching the pattern .env or .env.*. This includes files like:

  • .env - default environment variables
  • .env.local - local developer overrides
  • .env.development - development-specific variables
  • .env.staging - staging environment variables
  • .env.production - production secrets
  • .env.test - test environment variables

Any file in the working directory that matches the /^\.env(\..+)?$/ regex pattern will be discovered. The scan is non-recursive and only checks the top-level directory.

Environment Mapping

During tokengate init, each discovered file is mapped to a remote environment within your project. A single environment can only be mapped to one local file. These mappings are stored in the .tokengate.json file and persist across push/pull operations.

If you add a new .env file later, run tokengate init again to add the new mapping. Your existing mappings are preserved.

Change Detection

Tokengate uses SHA-256 content hashing to detect changes efficiently. When you push, the CLI computes a hash of each local file and compares it to the content hash stored on the remote revision. Only files with different hashes are uploaded, saving bandwidth and avoiding unnecessary revisions.

The same mechanism works in reverse during pull: the CLI compares the remote content hash to a hash of your local file and only downloads files where the remote has changed.

Push/Pull Workflow

The typical workflow is straightforward:

  1. Edit your local .env files as needed
  2. Run tokengate push to upload changes
  3. Team members run tokengate pull to get the latest
  4. Use tokengate status to check sync state at any time

File Selection

Both push and pull show you a table of all mapped files with their current status before making any changes. Files that are already in sync are skipped automatically. Only files with actual changes are transmitted.

Encryption

Tokengate implements a layered encryption architecture designed so the server never has access to plaintext secrets. All cryptographic operations use the Web Crypto API, a battle-tested standard available in all modern runtimes.

Workspace Key Model

Each workspace has a 256-bit AES workspace key generated at creation time. This key is the root of the encryption hierarchy and never leaves client devices in plaintext. When a new device is registered, the workspace key is wrapped (encrypted) using the device's RSA-OAEP 2048-bit public key, and the wrapped copy is stored on the server.

When the CLI needs the workspace key, it downloads the wrapped copy and unwraps it locally using the device's private key (which is stored only in ~/.config/tokengate/config.json).

Per-Revision Encryption

Each time you push a revision, the following process occurs entirely on your machine:

  1. A random 256-bit data key is generated for this specific revision
  2. A random 96-bit IV (initialization vector) is generated
  3. Your env file content is encrypted using AES-256-GCM with the data key and IV
  4. The data key is wrapped using the workspace key via AES-KW (Key Wrap)
  5. A SHA-256 content hash of the plaintext is computed for change detection
  6. The ciphertext, wrapped data key, and content hash are uploaded to the server

Why AES-KW?

AES Key Wrap (RFC 3394) is specifically designed for wrapping cryptographic keys. It provides both confidentiality and integrity protection for the wrapped key material, ensuring the data key cannot be tampered with in transit or storage.

Zero-Knowledge Architecture

The Tokengate server stores only:

  • Encrypted ciphertext (AES-256-GCM output)
  • Wrapped data keys (AES-KW output, only useful with the workspace key)
  • Content hashes (SHA-256 of plaintext, used for change detection only)
  • Wrapped workspace keys (RSA-OAEP output, one per device)

The server never sees your plaintext secrets, the workspace key in unwrapped form, or any per-revision data keys. Even with full database access, an attacker cannot decrypt your secrets without the RSA private key stored on an authorized device.

Recovery

When a workspace is created, a recovery phrase is generated from the raw workspace key using Base32 encoding. This phrase allows restoring workspace access if all devices are lost. Store it securely offline. The recovery phrase is shown once during workspace creation and cannot be retrieved again.

Important

If you lose your recovery phrase and all authorized devices, your encrypted data is permanently unrecoverable. There is no backdoor. This is by design.

Web Dashboard

The Tokengate web dashboard at tokengate.dev/dashboard provides a visual interface for managing your workspaces, projects, environments, and secrets. It complements the CLI for tasks that benefit from a graphical UI.

Workspace / Project / Environment Hierarchy

Tokengate organizes secrets in a three-level hierarchy:

  • Workspace - the top-level container, typically one per organization or team. Each workspace has its own encryption key and member list.
  • Project - a logical grouping within a workspace, usually mapping to a single code repository or service.
  • Environment - a named set of secrets within a project, such as "default", "local", "staging", or "production". Each environment maps to one .env file.

Unlocking Environments

Environments are locked by default in the dashboard. To view or edit secrets, you must unlock the environment by providing the workspace credentials. The decryption happens entirely in your browser using the Web Crypto API. The plaintext is never sent to the server.

Key-Value Editor

Once unlocked, the dashboard presents a spreadsheet-style key-value editor where you can add, edit, or remove individual environment variables. Changes are encrypted and saved as a new revision when you click save. The editor highlights which keys have been modified since the last revision.

Revision History

Each environment maintains a complete revision history. You can view past revisions, see when they were created, and identify which team member pushed each change. This provides a full audit trail for secret changes across your team.

Browser Encryption

The web dashboard performs all encryption and decryption in the browser using the same Web Crypto APIs as the CLI. Your plaintext secrets exist only in browser memory and are never transmitted to or stored on the server.

Team Workflows

Tokengate is designed for teams. Multiple developers can push and pull secrets from the same project without stepping on each other's work.

Sharing Environments

To give a team member access to a project's secrets:

  1. Add them to the workspace via the web dashboard
  2. They install the CLI and run tokengate login to register their device
  3. The workspace key is automatically wrapped for their device's public key
  4. They clone the repo (which includes .tokengate.json) and run tokengate pull

Because .tokengate.json is committed to version control, new team members automatically get the correct project and environment mappings. They only need to authenticate their device once.

Conflict Detection

Tokengate uses revision numbers to detect conflicts. Each environment has a monotonically increasing revision counter. When you push, the CLI sends the expected revision number. If another team member pushed in the meantime, the server rejects the push and you must pull first to get the latest changes.

This optimistic concurrency model prevents accidental overwrites while keeping the workflow simple. In practice, environment variable changes are infrequent enough that conflicts are rare.

conflict detection
$ tokengate push

Scanning .env files...

~ .env.production changed

? Push 1 file? Yes

! .env.production conflict - remote has newer revision
Run tokengate pull first to get the latest changes.

Recommended Team Setup

  1. One person creates the workspace via the web dashboard and saves the recovery phrase securely
  2. Add team members to the workspace through the dashboard
  3. Initialize the project with tokengate init and commit .tokengate.json to your repository
  4. Add .env* to .gitignore to prevent accidental commits of secret files
  5. Each developer runs tokengate login once, then tokengate pull after cloning the repo
  6. Push changes after updating secrets locally, and communicate significant changes to the team

Git Integration

Make sure .env* patterns are in your .gitignore file. The .tokengate.json file should be committed since it contains only non-sensitive identifiers and environment mappings.

SDK (@tokengate/env)

The @tokengate/env SDK gives you type-safe, validated environment variables with zero-knowledge encryption. Define a schema, and the SDK fetches, decrypts, validates, and types your variables automatically.

install
$ npm install @tokengate/env

Define a Schema

Create tokengate.config.ts in your project root:

tokengate.config.ts
import { defineConfig } from '@tokengate/env'

export default defineConfig({
project: 'web',
environment: 'production',
schema: {
DATABASE_URL: { type: 'string', required: true, sensitive: true },
API_KEY: { type: 'string', required: true, sensitive: true },
PORT: { type: 'port', default: 3000 },
DEBUG: { type: 'boolean', default: false },
ALLOWED_ORIGINS: { type: 'string[]', separator: ',' },
LOG_LEVEL: { type: 'enum', values: ['debug', 'info', 'warn', 'error'], default: 'info' },
}
})

Use in Your App

app.ts
import { createEnv } from '@tokengate/env'

const env = await createEnv({ schema: { /* ... */ } })

env.DATABASE_URL // string — guaranteed present
env.PORT // number — parsed from string
env.DEBUG // boolean — parsed from "true"/"1"
env.LOG_LEVEL // "debug" | "info" | "warn" | "error"

Schema Types

TypeParses toExample
stringstring"hello"
numbernumber"42" → 42
booleanboolean"true" / "1" / "yes"
string[]string[]"a,b,c" → ["a","b","c"]
number[]number[]"1,2,3" → [1,2,3]
urlstringValidated URL
emailstringValidated email
portnumber0–65535
enumstringOne of values

Sources Priority

Variables load from these sources in order (first match wins):

  1. Cloud — Tokengate API (E2E encrypted, decrypted locally via TOKENGATE_PASSWORD)
  2. File — Local .env file
  3. Processprocess.env

Generate Types

terminal
$ tokengate generate-types

env.d.ts — 6 typed variables
.env.example — template with defaults

Next.js Integration

install
$ npm install @tokengate/env-next @tokengate/env

Wrap Your Config

next.config.ts
import { withTokengate } from '@tokengate/env-next'

export default withTokengate({
schema: {
DATABASE_URL: { type: 'string', required: true, sensitive: true },
NEXT_PUBLIC_API_URL: { type: 'url', required: true },
PORT: { type: 'port', default: 3000 },
}
})

Variables prefixed with NEXT_PUBLIC_ are automatically exposed to client-side code. All others are server-only.

Server Components / API Routes

app/api/route.ts
import { getEnv } from '@tokengate/env-next'

export async function GET() {
const env = await getEnv({ schema: { /* ... */ } })
// env.DATABASE_URL — fully typed
}

Vite Integration

install
$ npm install @tokengate/env-vite @tokengate/env

Add the Plugin

vite.config.ts
import { defineConfig } from 'vite'
import { tokengate } from '@tokengate/env-vite'

export default defineConfig({
plugins: [
tokengate({
schema: {
VITE_API_URL: { type: 'url', required: true },
DATABASE_URL: { type: 'string', required: true, sensitive: true },
}
})
]
})

Variables prefixed with VITE_ are exposed to client code via import.meta.env. All variables are available in process.env during SSR/build.

Secret Scanning

Tokengate can scan your codebase for accidentally hardcoded secret values. It reads your mapped .env files, extracts the values, and searches all source files for matches.

terminal
$ tokengate scan

Found 12 secret values to scan for.
Scanning codebase...

Found 3 potential leaks:

src/config.ts
L42:15 DATABASE_URL leaked: const db = "postgres://user:pass@prod..."

deploy.sh
L12:20 STRIPE_SECRET leaked: export STRIPE_KEY="sk_live_..."

CI Integration

tokengate scan exits with code 1 if leaks are found, making it easy to add to your CI pipeline as a pre-merge check.