Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
df8b24d
Add health checks and GHCR deploy flow
heidi-dang Jan 27, 2026
e3c713d
Add readiness probe and extend deploy smoke tests
heidi-dang Jan 27, 2026
5dafd8e
Ignore .code and add CI guard
heidi-dang Jan 27, 2026
fbc88b8
Fix import order in health tests
heidi-dang Jan 27, 2026
c9c9006
Normalize import block spacing in health tests
heidi-dang Jan 27, 2026
64f9a4a
Add Gemini assistant chat support
heidi-dang Jan 27, 2026
aa0d7e3
Format imports in health tests
heidi-dang Jan 27, 2026
6224d8c
Merge pull request #1 from heidi-dang/github-workflow
heidi-dang Jan 27, 2026
080831a
Add Gemini UI notice and improve Gemini error handling
heidi-dang Jan 27, 2026
78bf563
Fix workflow expressions and add repo guard to PR checks
heidi-dang Jan 27, 2026
b61ba0d
Merge pull request #2 from heidi-dang/workflow-stability
heidi-dang Jan 27, 2026
2f4f135
Add one-click VPS deploy script with Traefik, DuckDNS, and Let's Encrypt
heidi-dang Jan 27, 2026
b6755e4
Merge branch 'main' into implement-GEMINI-api
heidi-dang Jan 27, 2026
4c7df1e
Add DEVELOPMENT roadmap with phased plan
heidi-dang Jan 27, 2026
7ed036d
Merge remote-tracking branch 'origin/implement-GEMINI-api' into imple…
heidi-dang Jan 27, 2026
2dbf8b1
Add DevProcess tracker and branch workflow rules
heidi-dang Jan 27, 2026
4e44fb2
Sort imports in assistant chat session
heidi-dang Jan 27, 2026
e8ab8b8
Merge pull request #3 from heidi-dang/implement-GEMINI-api
heidi-dang Jan 27, 2026
c159baf
Add pre-commit hooks and UI smoke test
heidi-dang Jan 27, 2026
1e55962
Add structured JSON logging with request IDs
heidi-dang Jan 27, 2026
349837d
Limit workflows to main branch
heidi-dang Jan 27, 2026
6d510a3
Merge pull request #4 from heidi-dang/workflow-main-only
heidi-dang Jan 27, 2026
33ea80d
Add metrics, tracing, Sentry hooks, and dev convenience tooling
heidi-dang Jan 27, 2026
b7095de
Add mypy strict config and Sentry frontend reporting
heidi-dang Jan 27, 2026
60663a5
Add Sentry user tagging for frontend
heidi-dang Jan 27, 2026
467560c
Add Sentry project tagging and optional user profile prompt
heidi-dang Jan 27, 2026
ef33257
Guard against tracked .env and .code
heidi-dang Jan 27, 2026
03e7e5d
Merge pull request #5 from heidi-dang/repo-guards-env-code
heidi-dang Jan 27, 2026
3667df8
Relax mypy config with ignore overrides for now
heidi-dang Jan 27, 2026
71ace37
Add runbook and config matrix; update process tracker
heidi-dang Jan 27, 2026
c4d0112
Fix Traefik Docker API version mismatch
heidi-dang Jan 27, 2026
8a43a83
Merge pull request #6 from heidi-dang/traefik-docker-api-fix
heidi-dang Jan 27, 2026
68c52f6
Merge remote-tracking branch 'origin/main' into development
heidi-dang Jan 27, 2026
38016fb
Update process tracker after doc additions
heidi-dang Jan 27, 2026
3fb4a23
Automate VPS deploy via deploy.sh
heidi-dang Jan 27, 2026
5e1dd83
Merge pull request #7 from heidi-dang/deploy-automation
heidi-dang Jan 27, 2026
9153a57
Fix Traefik routing and allow Docker access
heidi-dang Jan 27, 2026
874e35f
Merge pull request #8 from heidi-dang/fix/traefik-routing-and-remote
heidi-dang Jan 27, 2026
68de30d
Add git clone action for selected projects
heidi-dang Jan 27, 2026
3533a63
Merge remote-tracking branch 'origin/main' into development
heidi-dang Jan 27, 2026
7182648
Merge pull request #9 from heidi-dang/git-respository
heidi-dang Jan 27, 2026
2b47241
Fix import ordering in projects router
heidi-dang Jan 27, 2026
5e01dee
Merge pull request #10 from heidi-dang/git-respository
heidi-dang Jan 27, 2026
f57ccb7
Add blank line after module docstring
heidi-dang Jan 27, 2026
2138400
Merge pull request #11 from heidi-dang/git-respository
heidi-dang Jan 27, 2026
1ea78f9
Harden metrics & fix UI tooling
heidi-dang Jan 27, 2026
1a6cdf9
Adjust imports for ruff
heidi-dang Jan 27, 2026
8bb8ba9
Sort projects router imports
heidi-dang Jan 27, 2026
c2783a6
Allow workspace paths in filesystem browser
heidi-dang Jan 27, 2026
8267156
Organize projects imports
heidi-dang Jan 27, 2026
4a48def
Merge branch 'main' into git-respository
heidi-dang Jan 27, 2026
6d44d25
Merge main into development
heidi-dang Jan 27, 2026
aef50d0
Merge pull request #13 from heidi-dang/git-respository
heidi-dang Jan 27, 2026
2564be3
Trigger workflows on push and PR
heidi-dang Jan 27, 2026
f99d3b2
Fix projects router docstring
heidi-dang Jan 27, 2026
b10066d
fix ruff
heidi-dang Jan 27, 2026
047c595
Merge pull request #12 from heidi-dang/development
heidi-dang Jan 27, 2026
423fd4a
Update default install path to /home/autocoder
heidi-dang Jan 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.git
.gitignore
.code
__pycache__/
*.pyc
*.pyo
*.pyd
*.swp
*.swo
*.tmp
.env
.env.*
env/
venv/
.venv/
ENV/
node_modules/
ui/node_modules/
ui/dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
coverage/
dist/
build/
tmp/
*.log
62 changes: 58 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,35 @@
name: CI
name: Push CI

on:
pull_request:
branches: [master, main]
push:
branches: [master, main]
branches: [main]
pull_request:
branches: [main]

Comment on lines 3 to 8
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

CI won’t run for PRs targeting master.
This workflow only listens to main, but this PR targets master, so checks won’t execute. Add master to the branch filters (or align with the repo default branch).

✅ Suggested fix
 on:
   push:
-    branches: [main]
+    branches: [main, master]
   pull_request:
-    branches: [main]
+    branches: [main, master]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
on:
pull_request:
branches: [master, main]
push:
branches: [master, main]
branches: [main]
pull_request:
branches: [main]
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
🤖 Prompt for AI Agents
In @.github/workflows/ci.yml around lines 3 - 8, The GitHub Actions workflow's
branch filters under the 'on' trigger only include "main", so CI won't run for
PRs targeting "master"; update the branch arrays for both push and pull_request
in the workflow (the 'on' -> 'push' -> branches and 'on' -> 'pull_request' ->
branches entries) to include "master" (or change them to match the repository's
default branch naming) so pushes and PRs against master will trigger the
workflow.

jobs:
repo-guards:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Ensure .code/ and .env are not tracked
shell: bash
run: |
tracked_code="$(git ls-files -- .code)"
tracked_env="$(git ls-files -- .env)"

if [ -n "$tracked_code" ] || [ -n "$tracked_env" ]; then
echo "Local-only policy and secrets files must not be tracked."
if [ -n "$tracked_code" ]; then
echo "Tracked .code/ entries:"
echo "$tracked_code"
fi
if [ -n "$tracked_env" ]; then
echo "Tracked .env entries:"
echo "$tracked_env"
fi
exit 1
fi

python:
runs-on: ubuntu-latest
steps:
Expand Down Expand Up @@ -39,3 +62,34 @@ jobs:
run: npm run lint
- name: Type check & Build
run: npm run build
- name: UI smoke tests
run: npm run test:smoke

docker-image:
needs: [python, ui]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
env:
IMAGE_NAME: ghcr.io/${{ github.repository }}
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push image
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
platforms: linux/amd64
push: true
tags: |
${{ env.IMAGE_NAME }}:latest
${{ env.IMAGE_NAME }}:${{ github.sha }}
Comment on lines +68 to +93
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard image publishing from PR events.
docker-image runs on pull_request too; forked PRs won’t have package write permission, causing failed runs. Gate image builds to push events (or same‑repo PRs).

✅ Suggested fix
   docker-image:
     needs: [python, ui]
+    if: github.event_name == 'push'
     runs-on: ubuntu-latest
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
docker-image:
needs: [python, ui]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
env:
IMAGE_NAME: ghcr.io/${{ github.repository }}
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push image
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
platforms: linux/amd64
push: true
tags: |
${{ env.IMAGE_NAME }}:latest
${{ env.IMAGE_NAME }}:${{ github.sha }}
docker-image:
needs: [python, ui]
if: github.event_name == 'push'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
env:
IMAGE_NAME: ghcr.io/${{ github.repository }}
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push image
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
platforms: linux/amd64
push: true
tags: |
${{ env.IMAGE_NAME }}:latest
${{ env.IMAGE_NAME }}:${{ github.sha }}
🤖 Prompt for AI Agents
In @.github/workflows/ci.yml around lines 68 - 93, The docker-image job
currently runs for pull_request events which causes failures for forked PRs due
to lack of package write permission; modify the docker-image job (job name:
docker-image) to only run when publishing is allowed by adding an if-condition
that gates execution to push events or same-repo pull requests (e.g. check
github.event_name == 'push' OR github.event.pull_request.head.repo.full_name ==
github.repository), so image build-and-push steps (using env IMAGE_NAME and
docker/build-push-action@v6) are skipped for forked PRs.

cache-from: type=gha
cache-to: type=gha,mode=max
113 changes: 113 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
name: Deploy to VPS

on:
workflow_run:
workflows: ["Push CI"]
branches: [main]
types:
- completed

permissions:
contents: read

concurrency:
group: deploy-${{ github.event.workflow_run.head_branch }}
cancel-in-progress: false

jobs:
deploy:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
env:
DEPLOY_PATH: ${{ secrets.VPS_DEPLOY_PATH || '/home/autocoder' }}
TARGET_BRANCH: ${{ secrets.VPS_BRANCH || 'main' }}
VPS_PORT: ${{ secrets.VPS_PORT || '22' }}
DOMAIN: ${{ secrets.VPS_DOMAIN }}
DUCKDNS_TOKEN: ${{ secrets.VPS_DUCKDNS_TOKEN }}
LETSENCRYPT_EMAIL: ${{ secrets.VPS_LETSENCRYPT_EMAIL }}
APP_PORT: ${{ secrets.VPS_APP_PORT || '8888' }}
REPO_URL: https://github.com/${{ github.repository }}.git
IMAGE_LATEST: ghcr.io/${{ github.repository }}:latest
IMAGE_SHA: ghcr.io/${{ github.repository }}:${{ github.event.workflow_run.head_sha }}
steps:
- name: Deploy over SSH with Docker Compose
uses: appleboy/ssh-action@v1.2.4
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USER }}
key: ${{ secrets.VPS_SSH_KEY }}
port: ${{ env.VPS_PORT }}
envs: DEPLOY_PATH,TARGET_BRANCH,VPS_PORT,DOMAIN,DUCKDNS_TOKEN,LETSENCRYPT_EMAIL,APP_PORT,REPO_URL,IMAGE_LATEST,IMAGE_SHA
script: |
set -euo pipefail

if [ -z "${DEPLOY_PATH:-}" ]; then
echo "VPS_DEPLOY_PATH secret is required"; exit 1;
fi

if [ -z "${DOMAIN:-}" ] || [ -z "${DUCKDNS_TOKEN:-}" ] || [ -z "${LETSENCRYPT_EMAIL:-}" ]; then
echo "VPS_DOMAIN, VPS_DUCKDNS_TOKEN, and VPS_LETSENCRYPT_EMAIL secrets are required."; exit 1;
fi

if [ ! -d "$DEPLOY_PATH/.git" ]; then
echo "ERROR: $DEPLOY_PATH is missing a git repo. Clone the repository there and keep your .env file."; exit 1;
fi

cd "$DEPLOY_PATH"

if [ ! -f ./deploy.sh ]; then
echo "ERROR: deploy.sh not found in $DEPLOY_PATH. Ensure the repo is up to date."; exit 1;
fi

chmod +x ./deploy.sh

if [ ! -f .env ]; then
echo "WARNING: .env not found in $DEPLOY_PATH. Deployment will continue without it.";
fi

if [ "$(id -u)" -eq 0 ]; then
RUNNER=""
else
if ! command -v sudo >/dev/null 2>&1; then
echo "sudo is required to run deploy.sh as root."; exit 1;
fi
RUNNER="sudo"
fi

$RUNNER env \
AUTOCODER_AUTOMATED=1 \
AUTOCODER_ASSUME_YES=1 \
DOMAIN="${DOMAIN}" \
DUCKDNS_TOKEN="${DUCKDNS_TOKEN}" \
LETSENCRYPT_EMAIL="${LETSENCRYPT_EMAIL}" \
REPO_URL="${REPO_URL}" \
DEPLOY_BRANCH="${TARGET_BRANCH}" \
APP_DIR="${DEPLOY_PATH}" \
APP_PORT="${APP_PORT}" \
IMAGE="${IMAGE_SHA:-$IMAGE_LATEST}" \
./deploy.sh

echo "Running smoke test on http://127.0.0.1:${APP_PORT}/health and /readiness ..."
retries=12
until curl -fsS --max-time 5 "http://127.0.0.1:${APP_PORT}/health" >/dev/null; do
retries=$((retries - 1))
if [ "$retries" -le 0 ]; then
echo "Health check failed after retries."
exit 1
fi
echo "Waiting for health... ($retries retries left)"
sleep 5
done

retries=12
until curl -fsS --max-time 5 "http://127.0.0.1:${APP_PORT}/readiness" >/dev/null; do
retries=$((retries - 1))
if [ "$retries" -le 0 ]; then
echo "Readiness check failed after retries."
exit 1
fi
echo "Waiting for readiness... ($retries retries left)"
sleep 5
done

echo "Service responded successfully to health and readiness."
75 changes: 75 additions & 0 deletions .github/workflows/pr-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: PR Check

on:
pull_request:
branches: [main]
push:
branches: [main]

permissions:
contents: read

concurrency:
group: pr-check-${{ github.event.pull_request?.head.repo.full_name || github.repository }}-${{ github.event.pull_request?.number || github.run_number }}
cancel-in-progress: true
Comment on lines +12 to +14
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Syntax error: GitHub Actions expressions don't support optional chaining (?.).

The ?. operator is not valid in GitHub Actions expression syntax. This will cause the workflow to fail with a parsing error.

🐛 Proposed fix using proper GitHub Actions expression syntax
 concurrency:
-  group: pr-check-${{ github.event.pull_request?.head.repo.full_name || github.repository }}-${{ github.event.pull_request?.number || github.run_number }}
+  group: pr-check-${{ github.event.pull_request.head.repo.full_name || github.repository }}-${{ github.event.pull_request.number || github.run_number }}
   cancel-in-progress: true

In GitHub Actions, the || operator already handles null/undefined values gracefully - if the left side is falsy (including undefined), it returns the right side. The optional chaining operator is not needed.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
concurrency:
group: pr-check-${{ github.event.pull_request?.head.repo.full_name || github.repository }}-${{ github.event.pull_request?.number || github.run_number }}
cancel-in-progress: true
concurrency:
group: pr-check-${{ github.event.pull_request.head.repo.full_name || github.repository }}-${{ github.event.pull_request.number || github.run_number }}
cancel-in-progress: true
🧰 Tools
🪛 actionlint (1.7.10)

13-13: got unexpected character '?' while lexing expression, expecting 'a'..'z', 'A'..'Z', '_', '0'..'9', ''', '}', '(', ')', '[', ']', '.', '!', '<', '>', '=', '&', '|', '*', ',', ' '

(expression)

🤖 Prompt for AI Agents
In @.github/workflows/pr-check.yml around lines 12 - 14, The concurrency.group
expression uses unsupported optional chaining (?.) which breaks GitHub Actions
parsing; update the expression in the concurrency group to remove the optional
chaining and rely on the existing fallback logic (use the left OR right pattern)
so it becomes something like using github.event.pull_request.head.repo.full_name
|| github.repository and github.event.pull_request.number || github.run_number;
modify the concurrency.group value where it's defined to use those
non-optional-chaining symbols instead.


jobs:
repo-guards:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Ensure .code/ and .env are not tracked
shell: bash
run: |
tracked_code="$(git ls-files -- .code)"
tracked_env="$(git ls-files -- .env)"

if [ -n "$tracked_code" ] || [ -n "$tracked_env" ]; then
echo "Local-only policy and secrets files must not be tracked."
if [ -n "$tracked_code" ]; then
echo "Tracked .code/ entries:"
echo "$tracked_code"
fi
if [ -n "$tracked_env" ]; then
echo "Tracked .env entries:"
echo "$tracked_env"
fi
exit 1
fi

python:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: "pip"
cache-dependency-path: requirements.txt
- name: Install dependencies
run: pip install -r requirements.txt
- name: Lint with ruff
run: ruff check .
- name: Run security tests
run: python test_security.py

ui:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ui
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: ui/package-lock.json
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run lint
- name: Type check & Build
run: npm run build
- name: UI smoke tests
run: npm run test:smoke
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ temp/
nul
issues/

# Repository-specific
.code/

# Browser profiles for parallel agent execution
.browser-profiles/

Expand All @@ -16,6 +19,9 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Local Codex/Claude configuration (do not commit)
.code/

# ===================
# Node.js
# ===================
Expand Down
38 changes: 38 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: detect-private-key
- id: check-added-large-files
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.7.3
hooks:
- id: ruff
args: ["--fix"]
stages: [commit]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.13.0
hooks:
- id: mypy
args: ["--ignore-missing-imports"]
additional_dependencies: []
stages: [commit]
- repo: local
hooks:
- id: forbid-dotenv
name: Block committing .env files
entry: bash -c 'if git diff --cached --name-only | grep -E "(^|/)\.env(\.|$)"; then echo "? .env files are blocked from commits"; exit 1; fi'
language: system
pass_filenames: false
- id: eslint
name: ESLint (ui)
entry: bash -c 'cd ui && npm run lint'
language: system
pass_filenames: false
- id: prettier
name: Prettier check (ui)
entry: bash -c 'cd ui && npm run format'
language: system
pass_filenames: false
36 changes: 36 additions & 0 deletions CONFIGURATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Configuration Matrix

## Required for backend (Claude)
- `ANTHROPIC_AUTH_TOKEN` **or** Claude CLI auth (`claude login`) to run coding agents.

## Optional / Alternative Models
- `ANTHROPIC_BASE_URL`, `ANTHROPIC_AUTH_TOKEN` — GLM/other Claude-compatible endpoints.
- `ANTHROPIC_DEFAULT_OPUS_MODEL`, `ANTHROPIC_DEFAULT_SONNET_MODEL`, `ANTHROPIC_DEFAULT_HAIKU_MODEL` — model overrides.
- `GEMINI_API_KEY` — use Gemini for assistant chat (chat only, no tools).
- `GEMINI_MODEL` (default `gemini-1.5-flash`), `GEMINI_BASE_URL` (default OpenAI-compatible endpoint).

## Server runtime
- `AUTOCODER_ALLOW_REMOTE` — allow remote CORS (set to `1/true` to relax localhost-only guard).
- `API_TIMEOUT_MS` — passed to Claude SDK.

## Observability
- Backend Sentry: `SENTRY_DSN` (required to enable), optional `SENTRY_ENV`, `SENTRY_TRACES_SAMPLE_RATE` (default 0.2).
- Frontend Sentry: `VITE_SENTRY_DSN` (required to enable), optional `VITE_SENTRY_ENV`, `VITE_SENTRY_TRACES_SAMPLE_RATE`, `VITE_SENTRY_PROMPT_USER=1` to prompt for name/email.
- OTEL: `OTEL_EXPORTER_OTLP_ENDPOINT`, optional `OTEL_SERVICE_NAME` (default `autocoder-server`), `OTEL_ENVIRONMENT` (default `production`).

## Deploy (Traefik/DuckDNS)
- `.env.deploy` generated by `scripts/deploy.sh`:
- `DOMAIN`
- `LETSENCRYPT_EMAIL`
- `APP_PORT` (internal service port, default 8888)
- DuckDNS token stored in `/etc/cron.d/duckdns` (not in repo).

## UI build/dev
- `VITE_API_PORT` — backend port for Vite dev proxy (default 8888).

## Data / volumes
- `~/.autocoder` persisted via `autocoder-data` volume (docker-compose).

## Make targets
- `make dev-up`: uses `docker-compose.dev.yml` (hot reload).
- `make api-dev`, `make ui-dev`, `make lint`, `make smoke`, `make pre-commit-install`.
Loading