Environment Configuration
The .aether/environment.json file defines how your workspace should be set up. It tells Aether what to run after cloning your repository — installing dependencies, running migrations, and starting background services like dev servers.
This file lives in your repository and should be committed to version control so every team member and the AI agent get the same environment.
Quick Start
Create a .aether/environment.json file at the root of your repository:
{
"setup": "npm install",
"terminals": [
{ "name": "Dev Server", "command": "npm run dev" }
]
}
The next time a workspace starts, Aether will install dependencies and start your dev server in the background before the agent begins working.
Schema Reference
All fields are optional. Only include what your project needs.
| Field | Type | Description |
|---|
setup | string | Shell command to run after clone, before the agent starts. Cached by seed volumes. |
setup_on_boot | string | Shell command to run on every task boot. For secret-dependent steps. |
terminals | array | Background processes to start and keep running. |
setup
A shell command that prepares your project for development. This runs after the repository is cloned and environment variables are injected, but before the AI agent starts working.
Use this for anything that needs to complete before work can begin — installing dependencies, building assets, pulling Docker images. This command is cached by seed volumes — once the seed volume is built, setup is skipped on subsequent task boots (only setup_on_boot runs).
Because seed volumes run setup without secrets, this command must not depend on API keys, private registry tokens, or other secrets. Put secret-dependent steps in setup_on_boot instead.
{
"setup": "npm install"
}
Chain multiple commands with &&:
{
"setup": "npm install && npm run build"
}
The command should be idempotent (safe to run multiple times), like what a developer runs when setting up the project on a new machine.
setup_on_boot
A shell command that runs on every task boot, after the seed volume is attached. Use this for steps that depend on secrets or need to run fresh each time — database migrations, private registry authentication, environment-specific configuration.
{
"setup": "npm install && npm run build",
"setup_on_boot": "npm run db:migrate"
}
If setup_on_boot is not defined, the full setup runs on every boot as it does today. Projects opt into the seed volume optimization by splitting their setup into the two fields.
setup_on_boot also runs after setup on non-seeded boots (e.g., first task for a project before a seed volume exists). It only skips setup when a valid seed volume is attached.
terminals
An array of background processes that start automatically when the workspace boots. These keep running while the agent works — dev servers, file watchers, queue workers, etc.
{
"terminals": [
{ "name": "Dev Server", "command": "npm run dev" },
{ "name": "Type Check", "command": "npm run typecheck -- --watch" }
]
}
| Field | Type | Required | Description |
|---|
name | string | Yes | A label for the process (shown in the UI). |
command | string | Yes | The shell command to run. |
Terminals are restarted automatically when the workspace reboots.
The agent can also start additional services on-the-fly using the start_service tool. Those are separate from terminals and don’t persist across reboots.
Examples
Node.js / Next.js
{
"setup": "npm install",
"terminals": [
{ "name": "Dev Server", "command": "npm run dev" }
]
}
Python / Django
{
"setup": "python -m venv .venv && .venv/bin/pip install -r requirements.txt && .venv/bin/python manage.py migrate",
"terminals": [
{ "name": "Dev Server", "command": ".venv/bin/python manage.py runserver 0.0.0.0:8000" }
]
}
Ruby on Rails
{
"setup": "bundle install && bin/rails db:prepare",
"terminals": [
{ "name": "Rails Server", "command": "bin/rails server -b 0.0.0.0" },
{ "name": "Background Jobs", "command": "bin/jobs" }
]
}
Monorepo (Bun Workspaces)
bun install at the monorepo root resolves all workspace dependencies. Use terminals to start each app independently.
{
"setup": "bun install",
"terminals": [
{ "name": "API", "command": "cd apps/api && bun run dev" },
{ "name": "Web", "command": "cd apps/web && bun run dev" }
]
}
Project with Private Registry and Migrations
{
"setup": "npm install && npm run build",
"setup_on_boot": "npm run db:migrate && npm run seed:dev",
"terminals": [
{ "name": "Dev Server", "command": "npm run dev" }
]
}
Project with Docker Services
{
"setup": "npm install && docker compose up -d postgres redis",
"terminals": [
{ "name": "Dev Server", "command": "npm run dev" }
]
}
Execution Order
When a workspace starts, Aether runs the environment configuration in this order:
- Clone the repository
- Write secret files and environment variables
- Run
setup (if configured)
- Start
terminals in the background (if configured)
- Start the AI agent
If the setup command exits with a non-zero status, terminals will not start and the error is logged. Check the workspace logs for the full command output to debug failures.
Best Practices
- Keep
setup idempotent. Use commands like npm install or python -m venv .venv && .venv/bin/pip install -r requirements.txt that are safe to re-run. For Python, always use a virtual environment (python -m venv .venv).
- Use
setup for one-time prep, terminals for long-running processes. Installing dependencies is setup. Running a dev server is a terminal.
- Don’t put secrets in this file. It’s committed to your repository. Use Environment Variables for API keys, database credentials, and other sensitive values.
- Test your commands locally first. Run them manually to make sure they work before committing.
- Chain setup commands with
&&. This ensures later commands only run if earlier ones succeed.
.aether/environment.json is read at workspace boot time. If you update it while a workspace is running, the changes take effect on the next workspace restart.