The setup in 5 commands
curl -sSfL https://tene.sh/install.sh | sh
cd your-cursor-project
tene init
tene import .env # if you have existing secrets
rm .env # yes, delete itThat is the whole structural setup. From now on, open Cursor as usual.
The .cursor/rules/tene.mdc file from tene init teaches the agent
the rest.
What the .cursor/rules/tene.mdc file looks like
tene init writes this file for you. Shortened:
---
description: Secret management with tene
globs:
alwaysApply: true
---
# Secrets Management — tene
This project uses tene for secret management.
Secrets are encrypted locally with XChaCha20-Poly1305.
## Quick Reference
| Task | Command |
|---|---|
| List available secrets | tene list |
| Run with secrets injected | tene run -- <command> |
| Set a new secret | tene set <KEY> <VALUE> |
## Rules
1. Never hardcode secrets in source code.
2. Never create .env files — use tene run -- <command>.
3. Access secrets via process.env.KEY_NAME.
...Cursor reads alwaysApply: true and feeds this file into every new chat
as system context. Composer, Chat, or inline AI — the agent knows how to
handle secrets.
What changes in your Cursor workflow
Before
- Open Cursor in a project with an
.env. - Ask Composer to scaffold a Stripe webhook.
- Composer reads the codebase, including
.env. - Plaintext
sk_test_...lands in the context window.
After
- Open Cursor in a project where
.envwas moved into tene. - Ask Composer to scaffold a Stripe webhook.
- Composer reads
.cursor/rules/tene.mdc, sees the rule aboutprocess.env.*, and writes code that usesprocess.env.STRIPE_KEY. - Composer does not run
tene get STRIPE_KEYbecause the rules say not to. - You start the app in a terminal with
tene run -- npm start.process.env.STRIPE_KEYis the real value. Cursor never saw it.

Running commands inside Cursor
When Composer or Chat tells you to run a command that needs env vars,
prefix it with tene run --:
# Cursor suggests:
npm run dev
# You run:
tene run -- npm run devIf Cursor's built-in terminal is your main shell, set up an alias:
# ~/.zshrc or equivalent
alias npm-run-with-secrets='tene run -- npm'
alias node-with-secrets='tene run -- node'When Cursor really needs a secret value
Sometimes you do need Cursor to see a value — say, debugging a request signed with a specific key. In that case:
- Copy the value yourself with
tene get KEYin a separate terminal. Not Cursor's. - Paste it into Cursor's chat for that one reasoning step.
- Rotate the key after, if it was a production key.
The .cursor/rules/tene.mdc rule discourages this on purpose. "Paste a
secret into chat" should stay a careful, deliberate action. Not a habit.
Multi-environment with Cursor
# Switch active env for later 'tene run' calls
tene env staging
# Or target a specific env inline
tene run --env prod -- node server.jsCursor sees the active env name (through the rules file's tene env list
note) but not the values. To test a deploy with real prod credentials and
then reset:
tene run --env prod -- node server.js
# Test complete
tene env dev # back to dev for day-to-day workCommon mistakes
Skipping tene init. With no .cursor/rules/tene.mdc, Cursor has
no rules. The agent will happily read .env if you forget to delete it.
Committing the vault file. .tene/vault.db is .gitignored by
tene init. Do not override that. The vault belongs on one machine.
Putting credentials in README or CLAUDE.md by hand. Those files are indexed by Cursor. If you write a secret in plaintext anywhere, you have brought the problem back.
Using tene get inside Cursor's terminal. That prints plaintext to
stdout, which then enters Cursor's context. The rules file says no — but
people forget. If you need the value, use a separate terminal.
What if I do not want to use tene?
The rules-file pattern is the general idea. Teach the agent through a
rules file. Keep secrets out of plaintext. Inject them at runtime. You
can do this with Doppler (.cursor/rules/doppler.mdc), Infisical, or any
other secret manager that supports env-var injection. The specific tool
matters less than splitting "what the agent knows about secrets" from
"what the agent sees as values."
Summary
tene initwrites.cursor/rules/tene.mdcso the agent knows how to handle secrets.- Your workflow becomes
tene run -- <cmd>as a prefix. Nothing else changes. .envdoes not exist on disk, so it cannot be indexed.- Related reading: Claude Code + API keys: the safe workflow.
FAQ
Does Cursor read .env by default?
Yes. Cursor's Composer and Chat features index project files to build context. .env at the project root is included unless explicitly excluded via .cursorignore or similar.
What does .cursor/rules/tene.mdc do?
It is a Cursor rules file with front-matter alwaysApply: true. It tells the Cursor agent how to think about secrets: use 'tene run --' to inject env vars, use 'tene list' to check what exists, never 'tene get KEY' in chat since that prints plaintext.
Can I use both Cursor and Claude Code on the same project?
Yes. tene init generates rules files for both agents at the same time (.cursor/rules/tene.mdc and CLAUDE.md). Each agent picks up its own rules automatically.