Turns the autobuyer from a page scraper into something that acts. A dashboard button queues a run; a desktop process executes it against the real browser. lib/automations.ts — automations are declarative step lists nested inside the firm whose site they drive. Steps are click / type / wait / navigate, and they inherit the firm's tab pattern and URL, so one firm's automation can't act on another's tab. Adding a button means adding an entry here; the page renders buttons from the API and the runner receives steps from the server, so neither needs editing. Runs key on firm:automation — every firm will plausibly have its own "buy-accounts", and a bare id would resolve to the wrong one. clicker/runner.py — the daemon behind the buttons. Claims a queued run, works through the steps, reports each one back for the page's live log. Only one run executes at a time: two processes driving one physical mouse would interleave clicks. Heartbeats on its own thread, because a step can block for tens of seconds and folding the beat into the main loop would show the runner as offline in the middle of the run it was executing. clicker/actions.py — one implementation of the safety checks, shared by the CLI and the runner. Refuses to act when the element is covered by an overlay, when coordinates fall off-screen, when the browser can't be confirmed frontmost, or (for type) when the target isn't an editable field. Typing: uneven human cadence, and the field is read back afterwards and compared against what was typed — a field that never took focus fails silently and looks identical to success otherwise. Non-ASCII is rejected because pyautogui skips those characters without complaint, and newlines because Enter may submit the form. Typos are deliberately not simulated: a mistyped digit in a trading form is a real loss, and the correction is the part that can go wrong. Extension: opens the firm's page when no tab matches, navigates to a specific page for a navigate step (skipped when already there, so page state survives), and retries the locate while a freshly loaded React app mounts — `complete` only means the document loaded. Staleness reporting, after it cost three debugging rounds: Chrome doesn't reload an unpacked extension and Python doesn't reload a running process, so both now report their version. A stale runner gets a red banner naming both versions and the automation buttons are disabled, rather than failing mid-run on a step type it predates. Scale detection is now conservative: a raw OS/browser width ratio is only trusted when it lands on a real scaling factor. On this multi-monitor desktop the previous logic would have silently halved every coordinate. Verified end to end against the live browser: navigate, locate, and a real click (run #12, all three steps). API round-trips, claim-once semantics, run cancellation, the heartbeat online/offline lifecycle, motion geometry and timing, focus activation, and typing verification all pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AutoFirmer
Automated futures trading dashboard for prop firm accounts via Tradovate.
VPS Setup (Windows Server 2019 / 2022)
All commands are run in PowerShell (run as Administrator).
1. Install Git
Download and install from https://git-scm.com/download/win, or via winget:
winget install --id Git.Git -e --source winget
Restart PowerShell after installing so git is on the PATH.
2. Install Node.js 22+
winget install --id OpenJS.NodeJS.LTS -e --source winget
Restart PowerShell, then verify:
node --version # should be v22.x or higher
npm --version
3. Install Windows Build Tools (required for better-sqlite3)
better-sqlite3 compiles a native C++ module and needs the Visual Studio build tools:
npm install -g windows-build-tools
If that fails on newer Node, install manually:
- Download Build Tools for Visual Studio from https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022
- During install, select "Desktop development with C++"
4. Clone the repo
git clone https://github.com/Senofy/autofirmer.git
cd autofirmer
5. Install dependencies
npm install
6. Build
npm run build
7. Run
Development (with hot reload):
npm run dev
Production:
npm start
The app runs on port 3000. Access it at http://<your-vps-ip>:3000.
First-time setup
On first run, the SQLite database (autotrader.sqlite) is created automatically in the project root. No migrations need to be run manually.
Open the app in your browser and add your firms through the UI:
- Click + Add Firm on the main page
- Enter the firm name, Tradovate username, and password
- Go to the firm's Settings page to configure account types (prefix, profit target, consistency %, etc.)
- Return to the main page — accounts will populate once the firm connects to Tradovate
Keeping it running (PM2)
Install PM2 globally:
npm install -g pm2
npm install -g pm2-windows-startup
Start the app and save the process list:
cd C:\path\to\autofirmer
pm2 start "npm start" --name autofirmer
pm2 save
pm2-startup install
To restart after pulling updates:
cd C:\path\to\autofirmer
git pull
npm install
npm run build
pm2 restart autofirmer
Firewall
To restrict port 3000 to a specific trusted IP only:
New-NetFirewallRule -DisplayName "AutoFirmer" -Direction Inbound -Protocol TCP -LocalPort 3000 -RemoteAddress <your-ip> -Action Allow
Or open it to all inbound (less secure):
New-NetFirewallRule -DisplayName "AutoFirmer" -Direction Inbound -Protocol TCP -LocalPort 3000 -Action Allow
Updating
cd C:\path\to\autofirmer
git pull
npm install # only needed if dependencies changed
npm run build
pm2 restart autofirmer