❯envpilot
featurespricing❯docsblogchangelogwishlistfaq
sign-inget-started
// documentation
Start Here
  • Quickstart
  • Core concepts
  • Architecture: the machine surfaces
Platform
  • Data model
  • Variables
  • Secret files
  • Shared Accounts
  • Secret Sharing Links
  • Diagrams in documentation
  • Sharing documentation
  • Roles & permissions
  • Requests & approvals
  • Rotation & expiry
  • Security
Plans & Limits
  • Plans & Limits
  • Rate limits
CLI
  • CLI overview
  • Authentication & accounts
  • Linking projects
  • Pull & push
  • Running commands with secrets
  • Single secrets
  • Requests
  • Secret files
  • Command reference
  • CLI in CI & troubleshooting
VS Code
  • VS Code overview
  • Linking & sync
  • Protection
  • Editor features
  • Commands
  • Settings
  • Troubleshooting
GitHub Action
  • GitHub Action overview
  • Inputs & outputs
  • Secret files in CI
  • Recipes
  • Action security
Docker
  • Docker overview
  • Build time
  • Runtime
  • Docker Compose
  • Docker reference
API Reference
  • API overview
  • API Quickstart
  • Authentication
  • Errors
  • Organization
  • Projects
  • Variables
  • Shared accounts
  • Secret files
MCP Server
  • MCP overview
  • MCP setup
  • Connecting a client
  • Tools
  • Agent requests
Web Dashboard
  • Dashboard overview
  • Working in a project
  • Organization administration
Integrations
  • Slack & Discord Notifications
Guides
  • How to Share Environment Variables Securely
  • Next.js Environment Variables Best Practices
  • Android keystore in CI
  • Giving an agent secrets safely

// resources

  • github
  • npm
  • vs code marketplace
Start HerePlatformPlans & LimitsCLIVS CodeGitHub ActionDockerAPI ReferenceMCP ServerWeb DashboardIntegrationsGuides
❯envpilot

Encrypted environment variables for teams that live in the terminal. No .env files, no secrets in Slack.

$npm install -g @envpilot/cli

// product

  • Features
  • Pricing
  • Changelog
  • Wishlist

// resources

  • Getting Started
  • CLI Reference
  • VS Code Extension
  • Security

// compare

  • vs Doppler
  • vs Infisical
  • vs .env files

// support

  • FAQ
  • Support
  • Contact
  • Docs
  • Status

// legal

  • Privacy Policy
  • Terms of Service

© 2026 Envpilot · Built at Syntax Lab Technology · Abdul Rafay

ENVPILOT

❯envpilot
featurespricing❯docsblogchangelogwishlistfaq
sign-inget-started
// documentation
Start Here
  • Quickstart
  • Core concepts
  • Architecture: the machine surfaces
Platform
  • Data model
  • Variables
  • Secret files
  • Shared Accounts
  • Secret Sharing Links
  • Diagrams in documentation
  • Sharing documentation
  • Roles & permissions
  • Requests & approvals
  • Rotation & expiry
  • Security
Plans & Limits
  • Plans & Limits
  • Rate limits
CLI
  • CLI overview
  • Authentication & accounts
  • Linking projects
  • Pull & push
  • Running commands with secrets
  • Single secrets
  • Requests
  • Secret files
  • Command reference
  • CLI in CI & troubleshooting
VS Code
  • VS Code overview
  • Linking & sync
  • Protection
  • Editor features
  • Commands
  • Settings
  • Troubleshooting
GitHub Action
  • GitHub Action overview
  • Inputs & outputs
  • Secret files in CI
  • Recipes
  • Action security
Docker
  • Docker overview
  • Build time
  • Runtime
  • Docker Compose
  • Docker reference
API Reference
  • API overview
  • API Quickstart
  • Authentication
  • Errors
  • Organization
  • Projects
  • Variables
  • Shared accounts
  • Secret files
MCP Server
  • MCP overview
  • MCP setup
  • Connecting a client
  • Tools
  • Agent requests
Web Dashboard
  • Dashboard overview
  • Working in a project
  • Organization administration
Integrations
  • Slack & Discord Notifications
Guides
  • How to Share Environment Variables Securely
  • Next.js Environment Variables Best Practices
  • Android keystore in CI
  • Giving an agent secrets safely

// resources

  • github
  • npm
  • vs code marketplace
Start HerePlatformPlans & LimitsCLIVS CodeGitHub ActionDockerAPI ReferenceMCP ServerWeb DashboardIntegrationsGuides
❯envpilot

Encrypted environment variables for teams that live in the terminal. No .env files, no secrets in Slack.

$npm install -g @envpilot/cli

// product

  • Features
  • Pricing
  • Changelog
  • Wishlist

// resources

  • Getting Started
  • CLI Reference
  • VS Code Extension
  • Security

// compare

  • vs Doppler
  • vs Infisical
  • vs .env files

// support

  • FAQ
  • Support
  • Contact
  • Docs
  • Status

// legal

  • Privacy Policy
  • Terms of Service

© 2026 Envpilot · Built at Syntax Lab Technology · Abdul Rafay

ENVPILOT

// documentation
Start Here
  • Quickstart
  • Core concepts
  • Architecture: the machine surfaces
Platform
  • Data model
  • Variables
  • Secret files
  • Shared Accounts
  • Secret Sharing Links
  • Diagrams in documentation
  • Sharing documentation
  • Roles & permissions
  • Requests & approvals
  • Rotation & expiry
  • Security
Plans & Limits
  • Plans & Limits
  • Rate limits
CLI
  • CLI overview
  • Authentication & accounts
  • Linking projects
  • Pull & push
  • Running commands with secrets
  • Single secrets
  • Requests
  • Secret files
  • Command reference
  • CLI in CI & troubleshooting
VS Code
  • VS Code overview
  • Linking & sync
  • Protection
  • Editor features
  • Commands
  • Settings
  • Troubleshooting
GitHub Action
  • GitHub Action overview
  • Inputs & outputs
  • Secret files in CI
  • Recipes
  • Action security
Docker
  • Docker overview
  • Build time
  • Runtime
  • Docker Compose
  • Docker reference
API Reference
  • API overview
  • API Quickstart
  • Authentication
  • Errors
  • Organization
  • Projects
  • Variables
  • Shared accounts
  • Secret files
MCP Server
  • MCP overview
  • MCP setup
  • Connecting a client
  • Tools
  • Agent requests
Web Dashboard
  • Dashboard overview
  • Working in a project
  • Organization administration
Integrations
  • Slack & Discord Notifications
Guides
  • How to Share Environment Variables Securely
  • Next.js Environment Variables Best Practices
  • Android keystore in CI
  • Giving an agent secrets safely

// resources

  • github
  • npm
  • vs code marketplace
Start HerePlatformPlans & LimitsCLIVS CodeGitHub ActionDockerAPI ReferenceMCP ServerWeb DashboardIntegrationsGuides
How to Share Environment Variables SecurelyNext.js Environment Variables Best PracticesAndroid keystore in CIGiving an agent secrets safely
docs/Guides

Android keystore in CI

Stop emailing the upload keystore — store it once, pull it in the build, and keep the audit trail.

open in claudeopen in chatgptopen in cursor

Android keystore in CI

Every Android team has the same artefact: an upload keystore that must reach the release build and must never reach the repository. The usual workarounds — base64 in a CI secret, a file in a private bucket, a Slack message from three years ago — all lose the same thing: who has it, and who last used it.

This is the walkthrough for storing it as a secret file instead.

What you need#

  • A project in Envpilot, with the keystore's environment (production) available
  • The CLI installed and linked: envpilot init
  • An API key for CI with the GitHub Action surface and the files resource

Store the keystore#

Upload it#

❯terminal
envpilot files add ./upload.jks \
  --path android/app/upload.jks \
  --name "Play upload keystore" \
  --env production \
  --mode 0600

The --path is where every client will write it — pick the path your Gradle config already expects.

Store the passwords as variables#

❯terminal
envpilot secrets set KEYSTORE_PASSWORD -e production
envpilot secrets set KEY_ALIAS -e production
envpilot secrets set KEY_PASSWORD -e production

Masked prompts, so nothing lands in your shell history.

Delete the local original#

Once it is uploaded and you have verified a pull works, the copy in your Downloads folder is a liability. envpilot files pull will bring it back.

Wire up Gradle#

Read the passwords from the environment rather than a checked-in gradle.properties:

❯groovy
android {
  signingConfigs {
    release {
      storeFile file("upload.jks")
      storePassword System.getenv("KEYSTORE_PASSWORD")
      keyAlias System.getenv("KEY_ALIAS")
      keyPassword System.getenv("KEY_PASSWORD")
    }
  }
}

Local builds#

❯terminal
envpilot files pull -e production   # writes android/app/upload.jks, mode 0600
envpilot run --env production -- ./gradlew bundleRelease

files pull gitignores the path before writing it, and refuses to overwrite a local copy that differs from the server unless you pass --force.

The CI workflow#

❯yaml
name: Release
on:
  push:
    tags: ["v*"]
 
jobs:
  bundle:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
 
      - uses: rafay99-epic/envpilot-action@v1
        with:
          token: ${{ secrets.ENVPILOT_TOKEN }}
          environment: production
          project: mobile-app
          files: true
 
      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: "17"
 
      - run: ./gradlew bundleRelease

One step brings both halves: the passwords are exported to $GITHUB_ENV and masked in the log, and the keystore is written to android/app/upload.jks with mode 0600.

project is required whenever files: true — the files endpoint is project-scoped.

What you gained#

BeforeAfter
Keystore in a base64 CI secretEncrypted at rest, envelope-encrypted across two stores
No record of who downloaded itEvery fetch audited against a person or an API key
Rotating means editing every repo secretReplace contents once; path and grants stay put
New hire needs someone to send itenvpilot files pull

Rotating the keystore#

Use Replace contents in Project → Files: the bytes change, the path, environments and per-file grants stay. Every client picks up the new file on its next pull, and the old one is unrecoverable.

Limits#

  • 8 MB per file on Pro, 256 KB on Free. A keystore is a few KB; a provisioning bundle might not be.
  • Every content fetch is audited and rate-limited — a workflow that pulls on every push produces an entry per run.
  • The Action overwrites the destination path without a conflict check. That is right for a runner, wrong for a laptop, which is why the CLI behaves differently.
  • The files resource is never granted by default. A key that does not carry it is refused, not partially served.

See also#

  • Secret files · CLI files · Action: secret files
← guidesNext.js Environment Variables Best Practices
guides →Giving an agent secrets safely

// on this page

  • What you need
  • Store the keystore
  • Upload it
  • Store the passwords as variables
  • Delete the local original
  • Wire up Gradle
  • Local builds
  • The CI workflow
  • What you gained
  • Rotating the keystore
  • Limits
  • See also