The cheapest AI coding assistant. One-click setup for OpenClaw with DeepSeek, Qwen, GLM and more — up to 95% cheaper than GPT-4o. No Chinese phone required. Free models included.
Windows x64 installer • Includes OpenClaw auto-installer • Pre-configured with NovAI API
Install, register on NovAI, paste your API key — done. Auto-installs OpenClaw and configures all models in under 2 minutes.
DeepSeek V3.2 at $0.20/1M tokens vs GPT-4o at $2.50. Same HumanEval score (90.2%). Qwen-Turbo even cheaper at $0.05.
NovAI handles all upstream authentication. Just sign up with email, no VPN, no Chinese phone verification, no KYC.
DeepSeek V3.2, Qwen-Max/Plus/Turbo, MiniMax (1M context), GLM-4.6V, Moonshot 128K. Switch models on the fly.
GLM-4.6V-Flash and Qwen-Turbo are completely free with no rate limits. Test everything before spending a cent.
Full source code available below. Inspect, modify, build your own version. No hidden telemetry, no tracking.
const { app, BrowserWindow, ipcMain, shell, dialog } = require('electron');
const path = require('path');
const { spawn, execSync } = require('child_process');
const fs = require('fs');
const os = require('os');
const https = require('https');
// ─── Constants ─────────────────────────────────────────────
const NOVAI_API_BASE = 'https://aiapi-pro.com';
const NOVAI_V1_URL = NOVAI_API_BASE + '/v1';
const NOVAI_PROVIDER = 'novai';
const OC_CONFIG_DIR = path.join(os.homedir(), '.openclaw');
const OC_CONFIG_FILE = path.join(OC_CONFIG_DIR, 'openclaw.json');
const STATE_FILE = path.join(app.getPath('userData'), 'state.json');
// ─── Model Tiers ──────────────────────────────────────────
const NOVAI_MODELS = [
// ── Free Tier ──
{ id: 'glm-4.6v-flash', name: 'GLM-4.6v Flash', tier: 'free', inputPrice: 0, outputPrice: 0, desc: 'Zhipu free model, great for everyday coding', latencyNote: 'May queue 5-15s at peak' },
{ id: 'qwen-turbo', name: 'Qwen Turbo', tier: 'free', inputPrice: 0, outputPrice: 0, desc: 'Alibaba fast model, quick responses', latencyNote: 'Usually 1-3s' },
// ── Paid Tier ──
{ id: 'deepseek-v3.2', name: 'DeepSeek V3.2', tier: 'paid', inputPrice: 0.14, outputPrice: 0.28, desc: 'Best value, strong coding ability', latencyNote: 'Usually 1-2s' },
{ id: 'qwen-plus', name: 'Qwen Plus', tier: 'paid', inputPrice: 0.10, outputPrice: 0.56, desc: 'Enhanced Qwen, stronger reasoning', latencyNote: 'Usually 1-3s' },
{ id: 'qwen-max', name: 'Qwen Max', tier: 'paid', inputPrice: 0.28, outputPrice: 1.12, desc: 'Qwen flagship, best reasoning', latencyNote: 'Usually 2-5s' },
{ id: 'minimax-text-01', name: 'MiniMax Text 01 (1M ctx)', tier: 'paid', inputPrice: 0.21, outputPrice: 0.84, desc: '1M token context for large projects', latencyNote: 'Usually 2-4s' },
{ id: 'moonshot-v1-128k', name: 'Moonshot V1 128K', tier: 'paid', inputPrice: 0.42, outputPrice: 2.10, desc: 'Kimi long-context model, 128K window', latencyNote: 'Usually 2-6s' },
];
const FREE_DAILY_LIMIT = 50;
const FREE_MODELS_ONLY = NOVAI_MODELS.filter(m => m.tier === 'free').map(m => m.id);
// ─── State Management ──────────────────────────────────────
function loadState() {
try {
if (fs.existsSync(STATE_FILE)) {
return JSON.parse(fs.readFileSync(STATE_FILE, 'utf8'));
}
} catch (_) {}
return {
registered: false,
apiKey: '',
jwt: '',
userId: '',
email: '',
plan: 'free',
balance: 0,
setupComplete: false,
openclawInstalled: false,
};
}
function saveState(state) {
const dir = path.dirname(STATE_FILE);
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
}
// ─── HTTP Utilities ─────────────────────────────────────
function apiGet(endpoint, token) {
return new Promise((resolve, reject) => {
const url = new URL(endpoint, NOVAI_API_BASE);
const opts = {
hostname: url.hostname, path: url.pathname + url.search, method: 'GET',
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
timeout: 10000,
};
const req = https.request(opts, res => {
let d = '';
res.on('data', c => d += c);
res.on('end', () => {
try { resolve({ status: res.statusCode, data: JSON.parse(d) }); }
catch (_) { resolve({ status: res.statusCode, data: d }); }
});
});
req.on('error', reject);
req.on('timeout', () => { req.destroy(); reject(new Error('timeout')); });
req.end();
});
}
function apiPost(endpoint, body, token) {
return new Promise((resolve, reject) => {
const url = new URL(endpoint, NOVAI_API_BASE);
const payload = JSON.stringify(body);
const headers = { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) };
if (token) headers['Authorization'] = `Bearer ${token}`;
const opts = { hostname: url.hostname, path: url.pathname, method: 'POST', headers, timeout: 10000 };
const req = https.request(opts, res => {
let d = '';
res.on('data', c => d += c);
res.on('end', () => {
try { resolve({ status: res.statusCode, data: JSON.parse(d) }); }
catch (_) { resolve({ status: res.statusCode, data: d }); }
});
});
req.on('error', reject);
req.on('timeout', () => { req.destroy(); reject(new Error('timeout')); });
req.write(payload);
req.end();
});
}
// ─── Plan from Balance ─────────────────────────────────
function planFromBalance(balance) {
return (balance || 0) > 0 ? 'paid' : 'free';
}
// ─── Verify API Key ──────────────────────────────────────
async function verifyApiKey(apiKey) {
try {
const modelsRes = await apiGet('/v1/models', apiKey);
if (modelsRes.status !== 200) {
return { valid: false, error: 'Invalid API Key. Please check and try again.' };
}
let balance = 0.50;
try {
const meRes = await apiGet('/api/users/me', apiKey);
if (meRes.status === 200 && meRes.data && typeof meRes.data.balance === 'number') {
balance = meRes.data.balance;
}
} catch (_) {}
const plan = planFromBalance(balance);
return { valid: true, apiKey, plan, balance, dailyUsed: 0, dailyLimit: plan === 'paid' ? 999999 : FREE_DAILY_LIMIT };
} catch (err) {
return { valid: false, error: `Connection failed: ${err.message}` };
}
}
// ─── Environment Detection ──────────────────────────────
function checkNodeInstalled() {
try {
const ver = execSync('node --version', { encoding: 'utf8', timeout: 5000 }).trim();
return { installed: true, version: ver, sufficient: parseInt(ver.replace('v','').split('.')[0],10) >= 18 };
} catch (_) { return { installed: false, version: null, sufficient: false }; }
}
function checkNpmInstalled() {
try { return { installed: true, version: execSync('npm --version', { encoding: 'utf8', timeout: 5000 }).trim() }; }
catch (_) { return { installed: false, version: null }; }
}
function checkOpenClawInstalled() {
try { return { installed: true, version: execSync('openclaw --version', { encoding: 'utf8', timeout: 10000 }).trim() }; }
catch (_) { return { installed: false, version: null }; }
}
// ─── OpenClaw Installation ─────────────────────────────
function installOpenClaw(win) {
return new Promise((resolve, reject) => {
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
win.webContents.send('install-log', '>>> npm install -g openclaw ...\n');
const child = spawn(npmCmd, ['install', '-g', 'openclaw'], { shell: true, env: { ...process.env } });
child.stdout.on('data', d => win.webContents.send('install-log', d.toString()));
child.stderr.on('data', d => win.webContents.send('install-log', d.toString()));
child.on('close', code => code === 0
? (win.webContents.send('install-log', '\n✓ OpenClaw installed successfully!\n'), resolve(true))
: (win.webContents.send('install-log', `\n✗ Installation failed (exit code: ${code})\n`), reject(new Error(`exit ${code}`))));
child.on('error', err => { win.webContents.send('install-log', `\n✗ Error: ${err.message}\n`); reject(err); });
});
}
// ─── NovAI Config Injection ────────────────────────────
function injectNovAIConfig(apiKey, plan) {
let config = {};
if (fs.existsSync(OC_CONFIG_FILE)) {
try { config = JSON.parse(fs.readFileSync(OC_CONFIG_FILE, 'utf8')); } catch (_) {}
} else {
if (!fs.existsSync(OC_CONFIG_DIR)) fs.mkdirSync(OC_CONFIG_DIR, { recursive: true });
}
if (!config.models) config.models = {};
config.models.mode = 'merge';
if (!config.models.providers) config.models.providers = {};
const available = plan === 'paid' ? NOVAI_MODELS : NOVAI_MODELS.filter(m => m.tier === 'free');
config.models.providers[NOVAI_PROVIDER] = {
baseUrl: NOVAI_V1_URL, apiKey: apiKey, api: 'openai-completions',
name: 'NovAI — Cheapest AI Models',
models: available.map(m => ({
id: m.id, name: `${m.name}${m.tier === 'free' ? ' ★FREE' : ''}`,
pricing: { inputPerMillion: m.inputPrice, outputPerMillion: m.outputPrice },
})),
};
config.models.default = { provider: NOVAI_PROVIDER, model: 'glm-4.6v-flash' };
fs.writeFileSync(OC_CONFIG_FILE, JSON.stringify(config, null, 2), 'utf8');
return config;
}
// ─── Start/Stop OpenClaw ────────────────────────────────
let openclawProcess = null;
function startOpenClaw(win) {
if (openclawProcess) { win.webContents.send('openclaw-status', { running: true }); return; }
const cmd = process.platform === 'win32' ? 'openclaw.cmd' : 'openclaw';
openclawProcess = spawn(cmd, ['start'], { shell: true, env: { ...process.env } });
openclawProcess.stdout.on('data', d => win.webContents.send('openclaw-log', d.toString()));
openclawProcess.stderr.on('data', d => win.webContents.send('openclaw-log', d.toString()));
openclawProcess.on('close', () => { openclawProcess = null; win.webContents.send('openclaw-status', { running: false }); });
win.webContents.send('openclaw-status', { running: true });
}
function stopOpenClaw() { if (openclawProcess) { openclawProcess.kill(); openclawProcess = null; } }
// ─── IPC Handlers ───────────────────────────────────────
function setupIPC() {
ipcMain.handle('check-env', async () => ({
node: checkNodeInstalled(), npm: checkNpmInstalled(), openclaw: checkOpenClawInstalled(), state: loadState(),
}));
ipcMain.handle('open-register', async () => { shell.openExternal(NOVAI_API_BASE + '/#register'); });
ipcMain.handle('verify-key', async (_, apiKey) => {
const result = await verifyApiKey(apiKey);
if (result.valid) {
const state = loadState();
state.registered = true; state.apiKey = apiKey; state.plan = result.plan; state.balance = result.balance;
saveState(state);
}
return result;
});
ipcMain.handle('login-for-dashboard', async (_, { email, password }) => { /* ... login logic ... */ });
ipcMain.handle('install-openclaw', async (event) => {
const win = BrowserWindow.fromWebContents(event.sender);
try { await installOpenClaw(win); const state = loadState(); state.openclawInstalled = true; saveState(state); return { success: true }; }
catch (err) { return { success: false, error: err.message }; }
});
ipcMain.handle('finish-setup', async () => {
const state = loadState(); injectNovAIConfig(state.apiKey, state.plan); state.setupComplete = true; saveState(state);
return { success: true };
});
ipcMain.handle('query-usage', async () => { const state = loadState(); return await queryUsage(state); });
ipcMain.handle('get-models', async () => { /* ... returns model list ... */ });
ipcMain.handle('set-default-model', async (_, modelId) => { /* ... updates default model ... */ });
ipcMain.handle('open-upgrade', async () => { shell.openExternal(NOVAI_API_BASE + '/#topup'); });
ipcMain.handle('refresh-plan', async () => { /* ... refreshes plan based on balance ... */ });
ipcMain.handle('start-openclaw', async (event) => { startOpenClaw(BrowserWindow.fromWebContents(event.sender)); return { success: true }; });
ipcMain.handle('stop-openclaw', async () => { stopOpenClaw(); return { success: true }; });
ipcMain.handle('open-external', async (_, url) => shell.openExternal(url));
ipcMain.handle('open-config-file', async () => {
if (fs.existsSync(OC_CONFIG_FILE)) shell.openPath(OC_CONFIG_FILE);
else dialog.showMessageBox({ message: 'Config not created yet. Complete setup first.' });
});
}
// ─── Window ──────────────────────────────────────────────
let mainWindow = null;
function createWindow() {
mainWindow = new BrowserWindow({
width: 1000, height: 720, minWidth: 860, minHeight: 640,
title: 'NovAI Coder', icon: path.join(__dirname, '..', 'assets', 'icon.ico'),
backgroundColor: '#07090f',
webPreferences: { preload: path.join(__dirname, 'preload.js'), contextIsolation: true, nodeIntegration: false },
});
mainWindow.setMenuBarVisibility(false);
mainWindow.loadFile(path.join(__dirname, 'renderer', 'index.html'));
mainWindow.on('closed', () => { mainWindow = null; stopOpenClaw(); });
}
app.whenReady().then(() => { setupIPC(); createWindow(); });
app.on('window-all-closed', () => { stopOpenClaw(); if (process.platform !== 'darwin') app.quit(); });
app.on('before-quit', () => stopOpenClaw());
Copyright © 2026 NovAI (aiapi-pro.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
Download NovAI Coder, sign up for free, and start coding in under 2 minutes.
Download NovAI Coder v2.0.0