A "seat" is any machine that helps process the pool. One seat does both jobs from a single process: it transcribes & describes lesson videos and turns finished briefs into vectors. It signs in to the hub as an outbound client — no inbound ports, no shared network. Follow the steps for your OS; the one admin step (minting a key) is done once by Vinay.
A combined seat needs: git, Python 3.12, ffmpeg + Whisper (transcription), and the Claude CLI (the Describe pass, on your Max plan). The embedding libraries come in step 6.
# Homebrew first if needed:
# /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install git python@3.12 ffmpeg
pip3 install -U openai-whisper
# Claude CLI (if not already installed):
curl -fsSL https://claude.ai/install.sh | bash
apt install git python3.12 ffmpeg, then the same pip3 / Claude CLI lines.# In an elevated PowerShell:
winget install Git.Git Python.Python.3.12 Gyan.FFmpeg
pip install -U openai-whisper
# Claude CLI (if not already installed):
irm https://claude.ai/install.ps1 | iex
Clone the Asset Platform repo (or copy its pipeline/ folder). Everything runs from the repo root.
git clone <asset-platform repo URL> asset-platform
cd asset-platform
Each seat needs its own worker token (so you can see who did what and revoke one seat without touching the others). Vinay mints it once on the admin machine and hands the value over privately — never in chat.
3a. Create the token (via the MCP, db_execute_sql, schemaId=sandbox). Name the label after the machine:
INSERT INTO ax_token (token, role, label)
VALUES (replace(gen_random_uuid()::text,'-','')||replace(gen_random_uuid()::text,'-',''),
'worker', 'seat-mumbai-01')
RETURNING label;
3b. Read the value back locally (prints only to your terminal), on a machine that already has MCPDB_USER/PASS in ~/.claude/.env:
python3 - <<'PY'
import os,json,base64,urllib.request
e={}
for l in open(os.path.expanduser("~/.claude/.env")):
if "=" in l and not l.startswith("#"): k,v=l.strip().split("=",1); e[k]=v
a="Basic "+base64.b64encode(f"{e['MCPDB_USER']}:{e['MCPDB_PASS']}".encode()).decode()
b=json.dumps({"name":"db_query","arguments":{"schemaId":"sandbox",
"sql":"SELECT label, token FROM ax_token WHERE role='worker' ORDER BY label"}}).encode()
r=urllib.request.Request("https://mcp-db.classrootsedu.com/api/mcp/call",data=b,
headers={"Content-Type":"application/json","Authorization":a})
for row in json.loads(json.loads(urllib.request.urlopen(r).read())["result"]["content"][0]["text"])["rows"]:
print(row["label"],"->",row["token"])
PY
get_tokens.py and run python get_tokens.py. Copy the token next to your new label — that's the seat's AX_TOKEN.Same on every seat (Vinay provides them privately):
CF_ACCESS_CLIENT_ID + CF_ACCESS_CLIENT_SECRET. Lets the seat through the ClassRoots login.MCPDB_USER + MCPDB_PASS. Lets the seat fetch lesson files from Backblaze for transcription..env fileThe worker reads its secrets from ~/.claude/.env (/Users/<you>/.claude/.env)(on Windows: %USERPROFILE%\.claude\.env). Create it with your real values:
mkdir -p ~/.claude
cat >> ~/.claude/.env <<'EOF'
AX_TOKEN=your-worker-token
CF_ACCESS_CLIENT_ID=your-cf-client-id
CF_ACCESS_CLIENT_SECRET=your-cf-client-secret
MCPDB_USER=the-db-user
MCPDB_PASS=the-db-pass
EOF
chmod 600 ~/.claude/.envNew-Item -ItemType Directory -Force "$env:USERPROFILE\.claude" | Out-Null
@"
AX_TOKEN=your-worker-token
CF_ACCESS_CLIENT_ID=your-cf-client-id
CF_ACCESS_CLIENT_SECRET=your-cf-client-secret
MCPDB_USER=the-db-user
MCPDB_PASS=the-db-pass
"@ | Set-Content "$env:USERPROFILE\.claude\.env"<<'EOF') and the PowerShell here-string store values literally — don't wrap them in quotes. If a value looks wrong afterward, edit the file in a plain text editor.An isolated virtualenv holds the embedding libraries. First run downloads the bge-m3 model (~2.3 GB).
python3.12 -m venv ~/.ax-venv
~/.ax-venv/bin/pip install -U pip FlagEmbedding torchpy -3.12 -m venv "$env:USERPROFILE\.ax-venv"
& "$env:USERPROFILE\.ax-venv\Scripts\pip" install -U pip FlagEmbedding torchpython3.12 -m venv ~/.ax-venv
~/.ax-venv/bin/pip install -U pip FlagEmbedding
~/.ax-venv/bin/pip install torch --index-url https://download.pytorch.org/whl/cu128
A Mac/CPU seat still works — it just embeds slower than the GPU box.The Describe pass calls claude -p — no API key, your Max subscription.
claude # then type /login, sign in with your Max account, then /exit
claude -p "Reply with one word: pong" # should print: pong
One command does both jobs each cycle: claim a video → transcribe → describe → submit, and claim a finished brief → embed. Run it with the venv's Python (so bge-m3 is available); it calls whisper / claude as needed.
~/.ax-venv/bin/python pipeline/ax_worker.py --loop 20& "$env:USERPROFILE\.ax-venv\Scripts\python" pipeline\ax_worker.py --loop 20--roles extract (video only) or --roles embed (e.g. the 5090). Re-run any time; it always picks up the next available work and stops when there's nothing left.Open assets.classrootsedu.in → Work in Progress. Units move across the board and the By chapter view fills in — live, no refresh.
error code: 1010 / a sign-in page from the hub → the CF service token isn't set right. Re-check CF_ACCESS_CLIENT_ID/SECRET in .env.unauthorized → the AX_TOKEN value has a stray character. Re-copy it exactly (64 chars).claude CLI not authenticated → run claude → /login again (step 7).