A stored login in OpenCode in Docker: check it, use it, make one or remove it
Introduction
This article is part of a larger manual,
OpenCode in Docker on Ubuntu 24.04.
The manual shows how to run OpenCode with
the --auto option inside a
Docker container.
With --auto the agent does not ask you before
each command, so the container limits what it can reach: the agent works
only in one git worktree, a separate copy of the
project.
In this setup a paid model gets its key in one of two ways: from a key
file that the launcher passes to one run, or from a stored login.
This article explains what a stored login is, how to find out if you
have one, how to use it, and what to do if you have none.
What a stored login is
A stored login is a key that you gave to OpenCode inside the container,
with opencode auth login.
OpenCode saves it in its database, opencode.db,
in the sessions volume opencode-agent-data.
The launcher mounts this volume into every container, with every image.
So every later run sees the login, and you pass nothing to the launcher.
| Key file | Stored login | |
|---|---|---|
| How you set it up | a file in ~/.config/opencode-agent on the host | opencode auth login in a container |
| Where the key is | in that file | in opencode.db in the sessions volume |
| Which runs get it | only runs started with --opencode-key or --openrouter-key | every run, also the runs on the free model |
| opencode auth list shows | environment | stored |
Every run that has the key can read it, and with a stored login that is
every run.
opencode auth export prints the stored keys in
plain text.
Tested on a throwaway volume with a dummy key:
opencode auth export
[ { "id": "cred_1a62bc2e7001UPeX228degeY89", "integrationID": "opencode-go", "label": "OpenCode Go", "active": true, "value": { "type": "key", "key": "dummy-test-key-123" } } ]
An agent with --auto can run the same command.
A key file is the safer choice: runs without the option never have the
key (keys for one run).
How to find out if there is a stored login
Ask OpenCode in a one-off container on the sessions volume.
You need no worktree for this, and the container ends with the command:
docker run --rm -v opencode-agent-data:/home/agent/.local/share/opencode opencode-agent auth list
With a stored login for OpenCode Go, the line ends with stored:
OpenCode Go OpenCode Go stored
Without any stored login:
No authenticated integrations
In the shell of step 6 (check what
the container sees) the command is opencode auth
list.
There it also lists the keys that the launcher passed to the run, with
environment at the end.
A stored login and a key passed with
--opencode-key, both at once:
OpenCode Go OpenCode Go stored OpenCode Go OPENCODE_API_KEY environment OpenCode Console OPENCODE_API_KEY environment
Keep only one of the two for a provider, so you know which key a run uses.
stored does not mean that the key works.
OpenCode does not check the key when it saves it.
A wrong key fails at the first request of a run. Tested with a dummy
key:
Error: Upstream request failed: Invalid credential
How to use a stored login
Start the run as usual and pick a model of that provider with -m. You add no key option:
container/tools/ai/opencode-docker.sh ../site-agent-<task> run --title <task> -m opencode-go/deepseek-v4.1-flash "<what to do>"
A long task of this setup ran that way, in the
Erlang image and with the task in a file.
It ran on DeepSeek V4.1 Flash through
OpenCode Go:
container/tools/ai/opencode-docker.sh --erlang ../site-agent-<task> run --title <task> -m opencode-go/deepseek-v4.1-flash "$(cat ~/tasks/<task>.md)"
To continue a task that stopped at the usage limit of the free model,
add -s <id>
(when the free model reaches
its usage limit).
Which models a provider gives you: in the shell of step 6,
opencode models lists them, for example the
models of OpenCode Go:
opencode models | grep '^opencode-go/deepseek'
opencode-go/deepseek-v4-pro opencode-go/deepseek-v4.1-flash
What to do if there is no stored login
You have two choices.
1. Pass a key file to each run. This is the safer way: only the
runs you start with the option get the key.
To learn how to save the key and pass it, read the section
Keys for one run of the
launcher article for OpenCode Go, and the section
1. A key for the
container of the OpenRouter article for
OpenRouter.
container/tools/ai/opencode-docker.sh --opencode-key ~/.config/opencode-agent/opencode.key ../site-agent-<task> run -m opencode-go/deepseek-v4.1-flash "<what to do>"
2. Store a login. Copy the key of your OpenCode Go subscription
from the
OpenCode
console.
Then run the login form in a one-off container on the sessions volume.
-it gives the form a terminal, which it needs:
docker run --rm -it -v opencode-agent-data:/home/agent/.local/share/opencode opencode-agent auth login opencode-go --method key
Paste the key at the prompt. It shows as dots. Press Enter. The end of the output:
◇ Connected to OpenCode Go │ └ Done
Check it with auth list, as in
how to find out if there is a stored login.
Tested on a throwaway volume with a dummy key.
- Without -it the form stops: API key input requires an interactive terminal.
- For OpenRouter write openrouter instead of opencode-go. Its login method is also key; the login itself was tested with OpenCode Go only.
- Use a key made for the container, with a spending limit, not the key you use on the host. Every run can read it.
Remove a stored login
Give the provider and the label. The label is the second column of auth list:
docker run --rm -v opencode-agent-data:/home/agent/.local/share/opencode opencode-agent auth logout opencode-go "OpenCode Go"
◇ Removed account from OpenCode Go └ Done
Without the label the command opens a picker, which needs
-it.
Without a terminal it stops with Pass a credential ID
or label when running without an interactive terminal. Tested on
a throwaway volume.
Removing the whole volume, docker volume rm
opencode-agent-data, also removes the login, together with all
sessions.
Article author: Klavdiya Kondakova