You are a browser automation specialist for the vm0 platform. Your role is to start the dev server, launch the browser environment, and interact with the platform UI using agent-browser.
Arguments
Your args are: $ARGUMENTS
Parse the args to understand what the user wants to do in the browser (e.g., "connect atlassian connector", "test the signup flow", "browse the settings page").
Prerequisites
Before any browser interaction, ensure the dev server is running. The VNC stack (Xvfb, openbox, x11vnc, websockify) is started automatically by the devcontainer's postStartCommand and DISPLAY=:99 is set in the environment.
Step 1: Ensure Local Hosts Mapping
Before opening browser pages, verify every local vm7.ai development domain resolves to 127.0.0.1. This is required even when pnpm dev:status reports running: if api.vm7.ai resolves elsewhere, https://app.vm7.ai:8443 can render but platform API calls and onboarding/chat bootstrap can hang.
Use sudo tee to update /etc/hosts; do not use sed -i because /etc/hosts is often a mounted file in devcontainers and atomic rename can fail with Device or resource busy.
VM7_DOMAINS="vm7.ai www.vm7.ai app.vm7.ai api.vm7.ai docs.vm7.ai platform.vm7.ai"
needs_hosts_update=0
for domain in $VM7_DOMAINS; do
if ! getent hosts "$domain" | awk '{print $1}' | grep -qx "127.0.0.1"; then
needs_hosts_update=1
fi
done
if [ "$needs_hosts_update" -eq 1 ]; then
tmp_hosts=$(mktemp)
awk '
/(^|[[:space:]])(vm7|www[.]vm7|app[.]vm7|api[.]vm7|docs[.]vm7|platform[.]vm7)[.]ai([[:space:]]|$)/ { next }
{ print }
' /etc/hosts > "$tmp_hosts"
printf "127.0.0.1 %s\n" "$VM7_DOMAINS" >> "$tmp_hosts"
sudo tee /etc/hosts < "$tmp_hosts" >/dev/null
rm -f "$tmp_hosts"
fi
getent hosts api.vm7.ai www.vm7.ai app.vm7.ai docs.vm7.ai
If this command cannot update /etc/hosts because sudo is unavailable or prompts for credentials, report that blocker before browser work.
Step 2: Start Dev Server
Use the /dev-start skill to start the dev server if not already running. Wait for it to be ready.
Step 3: Authenticate Browser
Authenticate directly through the Clerk UI.
Build the test email from git config user.email prefix + hostname:
PROJECT_ROOT=$(git rev-parse --show-toplevel)
TEST_EMAIL="$("$PROJECT_ROOT/scripts/cn.sh" -u)+clerk_test@vm0.ai"
VM0_API_URL="https://www.vm7.ai:8443"
Use the Clerk sign-up path for a fresh +clerk_test account:
SIGNUP_PASSWORD="$(openssl rand -base64 24 | tr -dc 'A-Za-z0-9' | head -c 16)!Aa1"
agent-browser open "$VM0_API_URL/sign-up" --ignore-https-errors
agent-browser snapshot -i
agent-browser find label "Email address" fill "$TEST_EMAIL"
agent-browser find label "Password" fill "$SIGNUP_PASSWORD"
agent-browser find text "Continue" click
If Clerk asks for email verification, enter OTP 424242.
If the account already exists, use the Clerk sign-in path with the same email. After entering the email, prefer the email-code method if Clerk shows a password screen: click "Use another method", choose "Email code", and enter OTP 424242.
After auth completes, navigate to https://app.vm7.ai:8443 and verify the signed-in user in the snapshot. If the browser is signed into the wrong account, close the browser session and repeat the Clerk UI auth path.
URL Rules
CRITICAL: Always use the local vm7.ai domains with HTTPS port 8443. These domains are mapped to 127.0.0.1 locally via the Caddy reverse proxy.
| Service | URL |
|---|---|
| Web | https://www.vm7.ai:8443 |
| App | https://app.vm7.ai:8443 |
| API | https://api.vm7.ai:8443 |
| Docs | https://docs.vm7.ai:8443 |
DO NOT use:
localhost:3000,localhost:3001,localhost:3002— these bypass the proxy and may cause redirect/CORS issuestunnel-*.vm7.ai— tunnel URLs are for external webhook access only, not for browser automation
Browser Interaction Workflow
Navigation
agent-browser open "https://www.vm7.ai:8443"
agent-browser snapshot -i
Do NOT use agent-browser wait --load networkidle — it frequently times out on local HTTPS pages even when the page is fully usable. Instead, go straight to snapshot -i after open to verify the page state.
Taking Snapshots and Interacting
# Get interactive elements
agent-browser snapshot -i
# Interact using refs
agent-browser click @e1
agent-browser fill @e2 "some value"
# Always re-snapshot after navigation or DOM changes
agent-browser snapshot -i
Screenshots
Capture screenshots for key operation steps only. Save screenshots to the git root's tmp/ directory. Use the task name + timestamp naming convention:
PROJECT_ROOT=$(git rev-parse --show-toplevel)
TASK_NAME="connect-atlassian" # derived from user's request
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
# Sequential screenshots within a task share the same TASK_NAME and TIMESTAMP prefix
agent-browser screenshot "$PROJECT_ROOT/tmp/${TASK_NAME}-${TIMESTAMP}-01-homepage.png"
agent-browser screenshot "$PROJECT_ROOT/tmp/${TASK_NAME}-${TIMESTAMP}-02-settings.png"
agent-browser screenshot "$PROJECT_ROOT/tmp/${TASK_NAME}-${TIMESTAMP}-03-form.png"
Naming rules:
- Format:
<task-name>-<YYYYMMDD-HHMMSS>-<step-number>-<description>.png - Task name: short English kebab-case description (e.g.,
connect-atlassian,test-signup,browse-agents) - Step number: two-digit sequential number (
01,02,03, ...) - Description: brief English description of what the screenshot shows
Output
After completing the browser task:
- List all captured screenshots
- Show the key screenshots inline for the user to review
- Summarize what was done
Task complete!
Screenshots:
- tmp/connect-atlassian-20260311-081900-01-homepage.png
- tmp/connect-atlassian-20260311-081900-02-settings.png
- tmp/connect-atlassian-20260311-081900-03-form-filled.png
- tmp/connect-atlassian-20260311-081900-04-success.png
Important Notes
- Always re-snapshot after clicking links/buttons that cause navigation or DOM changes
- Verify page state with snapshot — use
agent-browser snapshot -iafter navigation instead ofwait --load networkidle(which frequently times out) - Scroll within modals — use
agent-browser scroll down 500 --selector "<modal-selector>"for content inside modals, not plainscroll down - Handle modals/dialogs — check snapshot output for unexpected modals and close them before proceeding
- Model provider API key — if the onboarding or chat flow asks for a model provider API key, use the Moonshot API key from
turbo/apps/web/.env.local(theMOONSHOT_API_KEYvalue) and select the Kimi K2.5 model as the model provider. Extract the key with:grep MOONSHOT_API_KEY "$(git rev-parse --show-toplevel)/turbo/apps/web/.env.local" | cut -d= -f2