Imported from dip-develop/dip-lab (
dev-agent/data/config/AGENTS.md). Install upstream withnpx skills add dip-develop/dip-lab --skill config. Copyright stays with the author.
Developer Workstation — Agent Guide
This file is read by opencode when you open a project inside the developer workstation container. It defines what agents are allowed to do.
Stack
- Container: Debian Bookworm + Flutter SDK (stable) + Dart + opencode CLI v2
- Build entrypoint:
opencode serve --hostname 0.0.0.0 --port 4096 - Companion tmux session:
tmux attach -t dev(started by ENTRYPOINT) - Container name:
dev-agent(OpenCode v2 version)
Database Quick Reference (Always Available)
Critical database information is included here so it's available in every project.
Test Credentials (from dev-agent/.env)
- PostgreSQL:
postgres:5432→ USER:$TEST_POSTGRES_USER, DB:dev_test_* - MySQL:
mysql:3306→ USER:$TEST_MYSQL_USER, DB:dev_test_* - Redis:
redis:6379→ DB index:$TEST_REDIS_DB(default 15)
Common Commands
# Connect to test DB
psql -h postgres -U "$TEST_POSTGRES_USER" -d "$TEST_POSTGRES_DB"
mysql -h mysql -u "$TEST_MYSQL_USER" "$TEST_MYSQL_DB"
redis-cli -h redis
# Create feature-specific test DB
psql -h postgres -U "$TEST_POSTGRES_USER" -d "$TEST_POSTGRES_DB" \
-c "CREATE DATABASE dev_test_feature_name;"
# Drop after tests
psql -h postgres -U "$TEST_POSTGRES_USER" -d "$TEST_POSTGRES_DB" \
-c "DROP DATABASE dev_test_feature_name;"
Safety Rules
- ✅ Allowed: Work with databases
dev_test_* - ❌ Forbidden:
production,app,cloud,galleryand other prod databases - ❌ Forbidden: Redis indexes 0-14 (only TEST_REDIS_DB allowed)
- The
db-safewrapper enforces these rules automatically
Network
The container is attached to the internal and database Docker
networks. From inside the container, services are reachable by
hostname:
| Service | URL (inside this container) |
|---|---|
| Automation (n8n) | http://automation:5678 |
| n8n health | http://automation:5678/healthz |
| Hermes API Gateway | http://hermes:8642 |
| Hermes API Gateway health | http://hermes:8642/health |
| Hermes API Gateway Dashboard | http://hermes:9119 |
| PostgreSQL (test user only) | postgres:5432 (use TEST_POSTGRES_USER / TEST_POSTGRES_PASSWORD from dev-agent/.env) |
| MySQL (test user only) | mysql:3306 (use TEST_MYSQL_USER / TEST_MYSQL_PASSWORD from dev-agent/.env) |
| Redis (test DB index only) | redis:6379 (use TEST_REDIS_PASSWORD and TEST_REDIS_DB from dev-agent/.env) |
The opencode web UI/API itself is on http://localhost:4096 (host:
http://${BIND_IP}:4096, default ${BIND_IP}=127.0.0.1). It is protected
by OPENCODE_SERVER_PASSWORD from dev-agent/.env.
Database access (test only)
The container has database access, but it is strictly isolated:
- You connect as
TEST_POSTGRES_USER/TEST_MYSQL_USER(not the prod users). These test users have server-side grants ONLY on databases whose name starts withdev_test_. - A bash wrapper (
db-safe, symlinked topsql/mysql/mariadb/redis-clion PATH) refuses to talk to any non-test database. Examples that will be rejected:psql -d production→ exit 1psql -d app→ exit 1mysql -D cloud→ exit 1redis-cli -n 0→ exit 1redis-cli SELECT 2→ exit 1
- The wrapper can be disabled per-command with
DBSAFE=0 ...or globally by settingDB_SAFETY_GUARD=falseindev-agent/.env. Don't disable it without a reason - the prod creds are NOT available inside the container, but the wrapper also protects against typo'd DB names that happen to match a prod DB.
Working with test databases
# Connect to the pre-created test DB.
psql -h postgres -U "$TEST_POSTGRES_USER" -d "$TEST_POSTGRES_DB"
mysql -h mysql -u "$TEST_MYSQL_USER" "$TEST_MYSQL_DB"
redis-cli -h redis # uses TEST_REDIS_DB index
# Create a new isolated test DB for one feature under test.
psql -h postgres -U "$TEST_POSTGRES_USER" -d "$TEST_POSTGRES_DB" \
-c "CREATE DATABASE dev_test_feature_x;"
# ... tests run against dev_test_feature_x ...
# Drop it when done (the test user is the owner, so this works).
psql -h postgres -U "$TEST_POSTGRES_USER" -d "$TEST_POSTGRES_DB" \
-c "DROP DATABASE dev_test_feature_x;"
# Redis: namespace your keys with `dev_test:` so a future FLUSHDB on
# the test index can never collide with prod keys.
redis-cli SET dev_test:counter 1
The PGPASSWORD, MYSQL_PWD, REDISCLI_AUTH env vars are
auto-exported in your shell from the container's TEST_*_PASSWORD
values (see ~/.config/dev-agent/env.sh).
Docker
- This container runs without
docker.sockand without--privileged. The user inside is not in thedockergroup, sodockeranddocker composeare not even installed. - If a task seems to need to build/run containers, say so explicitly and the operator will run those steps or grant a scoped exception. Do not try to work around the permission denial.
Git workflow (Git Flow)
- The full branch/PR policy is injected into every agent as
instructions/git-flow.md— it is the single source of truth; this section only summarizes the consequences. - Supporting branches (
feature/,bugfix/,release/) base ondevelop;hotfix/bases onmain. Never commit directly tomain/develop. - Push your branch, open a PR with
gh pr create --base develop(hotfix/release: two PRs — intomainANDdevelop), then stop and summarize what's ready for review. - Merging into
main/develop, tagging releases, and force-pushes are operator actions. Pushes tomain/develop(including refspec forms likeHEAD:develop) are denied at the permission level. - After a release/hotfix lands on
main, propose the back-merge PR (backmerge/*cut fromorigin/main, basedevelop) right away; dependency/CI maintenance targetsdevelop(target-branch: develop). Details ininstructions/git-flow.md.
Roadmap & TODO
- Long-lived plans and ideas go to GitHub issues; the current working
list is
TODO.mdin the project root. Details:instructions/roadmap.md(injected into every agent). - Multi-step plans get a tracking issue before implementation (the
operator approves filing); PR bodies link it via
Refs #<n>and the orchestrator closes it after the merge — GitHub'sCloseskeyword does not fire for develop-based merges.
Scheduled jobs
- Creating a recurring job is an operator action, same as installing the
auto-back-merge GitHub Action in
instructions/git-flow.md: agents may propose a cron job (what it would run, how often) but must not create one themselves. (Theopencode-cronplugin was removed as non-functional under V2.) - Reason: a recurring job runs unattended against whichever model it's configured to use, against that model's own OpenCode Go usage cap (5h/week/month tranches -- see opencode.ai/docs/go), with no approval step in the loop, unlike a normal ask-gated bash command.
Things to never do
- Never edit
.env, secrets, SSH keys, WireGuard config, or anything outside the project working directory mounted at/home/develop/projects. - Never run
docker,systemctl, or firewall commands.sudois allowed for installing packages/tools inside the container (e.g.sudo apt-get install ...), never for altering system/network config or anything outside the container. - Never push to
main/developor delete branches. - Never touch other services' Docker containers. Only reach them over HTTP/TCP from inside the container, as documented in the Network table above.
- Never
DROP DATABASE/TRUNCATE/FLUSHDBagainst a non-dev_test_PostgreSQL/MySQL database, or a non-TEST_REDIS_DBRedis index. Thedb-safewrapper enforces this; do not bypass it (DBSAFE=0) without operator approval. - Never
DELETE FROM <prod_table>orUPDATEprod data. The test users do not have privileges on prod DBs, so the server will reject the SQL - but if a future change widens the grant, the history here says "do not do this".
Package research policy
- Docs before sources: the full policy is injected into every agent as
instructions/package-docs-first.md— MCP doc servers first, then README /example// pub.dev docs;~/.pub-cachesources only as a surgical last resort (search for a symbol, never whole-file browsing).
Testing expectations
- Run
dart analyzeanddart test(or the project's equivalents) before calling a change done. Delegate to thetestersubagent. - Use
flutter analyze/flutter testfor Flutter projects. - For projects that need a real database: the
testersubagent should use the test creds documented above. Use a per-feature test database (e.g.dev_test_<feature>) and drop it after the run. - If a test needs a "clean slate" mid-run, drop and recreate the test DB - do not attempt to truncate a shared one.