Secrets and variables live
Secrets hold credentials. Variables hold plain configuration. Workflows and automations
read them as ${{ secrets.NAME }} and ${{ vars.NAME }}.
Secret
Write-only and encrypted at rest. Settings lists its name, never its value. It is masked in logs. Use it for tokens, keys and passwords.
Variable
Plain configuration such as an account id, a region or a URL. Anyone with a role on the repository can read its value, and logs print it. Never put a credential in one.
Add a secret
-
Open the repository's settings
Go to Settings, then Secrets and variables. You need the maintain role or to own the repository. Everyone else with a role sees names only.
-
Name it and paste the value
Names use letters, digits and underscores, up to 100 characters, and may not start with
GITHUB_. Names are stored in upper case. Saving a name that exists replaces its value. -
Name it in the workflow
.github/workflows/deploy.yml - run: npx wrangler deploy env: CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}A run gets only the secrets its workflow names.
The repository screen
Variables sit on the same page with the same form, minus the mask and the pre-land toggle. Inherited org entries show a variable's value. An org entry that your repository overrides stays listed and says so.
The organization screen
Org owners and admins manage org secrets and variables in the org's Settings, then Secrets and variables. Other org members can read names. Each entry chooses which repositories it reaches.
Precedence: a repository entry with the same name beats the org entry, as on GitHub.
Who gets which secrets
A secret is released only to code you trust. Pick the row for how the run started.
| Run started by | Secrets released | Job token |
|---|---|---|
The stalk moving (a push to main), Run workflow, a
schedule
|
The ones the workflow names. This is how deploys work. | As the workflow's permissions say |
| An automation, started by a bean event | Only the secrets marked available to pre-land checks | May push bean/* if beans: write |
| An automation, scheduled or run by hand | The ones the automation names in secrets: |
As above |
| A pre-land workflow run of a bean pushed by an agent session, a deploy token or a collaborator below maintain planned | None, unless the secret is marked available to pre-land checks | Read-only |
Masking
Every secret value a job may read is replaced with *** in the log before
the log is stored or streamed. The base64 and URL-encoded forms are masked too, and so
is the job token. Values shorter than three characters are not masked, as on GitHub.
Masking is a net, not a vault: do not print secrets on purpose.
Protect the workflow files
A workflow that holds a secret is code, and an agent can change code. List the workflow
folder in protected-paths of
.gitstalk/checks.yml
so only maintainers and the owner can change it:
protected-paths:
- .github/**
A stalk workflow still runs your package.json scripts, which agents wrote,
with its secrets, as auto-merge does on GitHub. Asking for approval before secrets are
released is planned.
From an agent beta
An agent session sees names and sets values through two tools. The tool surface was
renamed on 2026-10-14 (actions_secret_* and
actions_variable_* became actions_config_*), so a server you
connected earlier may still show the old names.
| Tool | What it does | Needs |
|---|---|---|
actions_config_list |
Secret names with where each comes from and who updated it, never values. Variables with their values. | Any role that reads the repository |
actions_config_set |
Stores a secret or a variable. A secret is write-only. |
The secrets scope, ticked on the consent page, and the maintain
role. An org entry needs an org owner or admin.
|
actions_config_delete |
Deletes one, only when you asked. Workflows that read it get an empty value. | Same as set |
-
The
secretsscope is never pre-ticked on the consent page. A session without it never sees the set and delete tools. - Prefer adding the secret yourself. If you give the value to an agent, it passes through the agent and its model provider. A missing secret is best handled by asking you to add it in Settings. The agent only stores a value you gave it for that name.
-
The audit log names the secret, you and the agent's client, as
via <client> (MCP). - An org entry set this way starts out reaching only the repository the agent named.
Good to know
- Deleting a repository deletes its secrets and variables.
-
Variables named
GITSTALK_DEPS_CACHE,GITSTALK_DEPS_SNAPSHOT_MAXandGITSTALK_NPM_AUDITswitch Gitstalk's own job behaviour. See Environment variables. - Secrets are encrypted at rest with a key the deployment holds. A self-hoster sets it. See Self-hosting.