
codex-console-automation
AI skill for managing OpenAI account automation using codex-console - registration, payment, token management, and batch operations
- Installs
- 264
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/reason-machines/codex-skills --skill codex-console-automation- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads codex-console-automation automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
codex-console Automation Skill
Skill by ara.so — Codex Skills collection.
Overview
codex-console is a comprehensive automation platform for managing OpenAI accounts at scale. It handles registration, login, token extraction, subscription management, payment binding, auto-replenishment, and integration with API gateways like CPA, Sub2API, Team Manager, and New-API.
This is a maintained fork that fixes compatibility issues with OpenAI's evolving authentication flow, including Sentinel POW solving, split registration/login flows, and improved OTP handling.
Key capabilities:
- Web UI for task management and monitoring
- Batch account registration with email service integration
- Semi-automated payment card binding with 3DS support
- Automated token refresh and upload to API gateways
- Self-check and repair system
- Auto-replenishment based on inventory levels
- Tag-based account pooling and team management
- SQLite or PostgreSQL backend
Installation
Using Python (Recommended for Development)
# Clone the repository
git clone https://github.com/dou-jiang/codex-console.git
cd codex-console
# Install dependencies with uv (recommended)
uv sync
# Or use pip
pip install -r requirements.txt
Using Docker
# With docker-compose
docker-compose up -d
# Or with docker run
docker run -d \
-p 1455:1455 \
-p 6080:6080 \
-e WEBUI_HOST=0.0.0.0 \
-e WEBUI_PORT=1455 \
-e WEBUI_ACCESS_PASSWORD=your_secure_password \
-v $(pwd)/data:/app/data \
--name codex-console \
ghcr.io/dou-jiang/codex-console:latest
Building Standalone Executable
# Windows
build.bat
# Linux/macOS
bash build.sh
The executable will be in dist/codex-console-windows-X64.exe or equivalent.
Configuration
Environment Variables
Create .env from template:
cp .env.example .env
Key variables:
# Server
APP_HOST=0.0.0.0
APP_PORT=8000
APP_ACCESS_PASSWORD=admin123
# Database (SQLite by default)
APP_DATABASE_URL=data/database.db
# Or PostgreSQL
APP_DATABASE_URL=postgresql://user:password@host:5432/dbname
# Logging
LOG_LEVEL=info
# Debug mode
DEBUG=false
Priority: CLI args > .env > database settings > defaults
First-Time Setup
- Start the web UI:
python webui.py --access-password mypassword
-
Access at
http://127.0.0.1:8000 -
Configure in Settings page:
- Email service credentials
- Proxy settings
- Upload targets (CPA/Sub2API/New-API)
- Payment automation options
Core Usage Patterns
Starting the Web UI
# webui.py - main entry point
import uvicorn
from src.web.app import app
from src.utils.settings import get_settings
if __name__ == "__main__":
settings = get_settings()
uvicorn.run(
app,
host=settings.app_host,
port=settings.app_port,
log_level=settings.log_level.lower()
)
CLI options:
# Default
python webui.py
# Custom host/port
python webui.py --host 0.0.0.0 --port 8080
# Set password
python webui.py --access-password mypassword
# Debug mode (hot reload)
python webui.py --debug
Email Service Integration
codex-console supports multiple email providers:
# src/services/email_service.py
from src.services.email_service import EmailServiceFactory
# Configure in database or code
email_config = {
"service_type": "cloudmail", # or luckmail, yydsmail, outlook
"api_key": None, # from env: CLOUDMAIL_API_KEY
"config": {
"base_url": "https://api.cloudmail.com",
"timeout": 30
}
}
# Factory creates appropriate service
service = EmailServiceFactory.create(email_config)
# Fetch verification code
otp = await service.get_verification_code(
email="test@example.com",
timeout=60
)
Supported services:
- CloudMail (API-based)
- LuckMail (API-based)
- YYDS Mail (API-based)
- Outlook (self-hosted accounts)
Registration Flow
# src/core/register.py
from src.core.register import RegisterService
from src.models.task import RegisterTask
async def register_account(email: str, password: str, proxy: str):
"""Register a new OpenAI account"""
task = RegisterTask(
email=email,
password=password,
proxy=proxy,
status="pending"
)
service = RegisterService(task)
result = await service.execute()
return result
# Returns: {"success": True, "account_id": 123, "token": "..."}
Key steps handled:
- Sentinel POW solving
- Email verification (auto-fetch from email service)
- Split registration/login flow
- Token extraction
- Workspace caching
Batch Registration
# src/core/auto_register.py
from src.core.auto_register import AutoRegisterService
async def batch_register(count: int):
"""Register multiple accounts"""
service = AutoRegisterService()
# Configure
await service.configure({
"target_count": count,
"email_service": "cloudmail",
"proxy_pool": "residential",
"auto_upload": True,
"upload_target": "newapi"
})
# Start registration
await service.start()
# Monitor progress
status = await service.get_status()
# Returns: {"completed": 50, "failed": 2, "running": True}
Payment Binding
# src/core/payment.py
from src.core.payment import PaymentService
from src.models.task import BindCardTask
async def bind_payment_card(account_id: int, card_info: dict):
"""Bind payment card to account (semi-automated)"""
task = BindCardTask(
account_id=account_id,
card_number=card_info["number"], # Store encrypted
expiry=card_info["expiry"],
cvv=card_info["cvv"],
billing_address={
"street": "auto-generated", # Random US address
"city": "New York",
"state": "NY",
"zip": "10001",
"country": "US"
},
status="pending"
)
service = PaymentService(task)
result = await service.execute()
# Note: 3DS verification requires manual intervention
# Browser window will open for 3DS flow
return result
Token Management
# src/core/account_manager.py
from src.core.account_manager import AccountManager
from src.models.account import Account
async def refresh_account_token(account_id: int):
"""Refresh access token for an account"""
manager = AccountManager()
account = await manager.get_account(account_id)
# Refresh using refresh_token
new_token = await manager.refresh_token(account)
# Auto-upload to configured targets
await manager.upload_to_targets(account)
return new_token
Auto-Upload to API Gateways
# src/services/upload_service.py
from src.services.upload_service import UploadService
async def upload_account(account_id: int, target: str):
"""Upload account to API gateway"""
service = UploadService()
# Supported targets: cpa, sub2api, team_manager, newapi
result = await service.upload(
account_id=account_id,
target=target
)
return result
# Returns: {"success": True, "external_id": "...", "quota": 20}
New-API configuration example:
# In settings or database
newapi_config = {
"base_url": "https://api.example.com",
"api_key": None, # from env: NEWAPI_API_KEY
"auto_upload": True,
"upload_on_register": True,
"quota_per_account": 20
}
Task Management
# src/services/task_service.py
from src.services.task_service import TaskService
async def manage_tasks():
"""Unified task management"""
service = TaskService()
# Create registration task
task_id = await service.create_task(
task_type="register",
count=10,
config={"email_service": "cloudmail"}
)
# Pause task
await service.pause_task(task_id)
# Resume task
await service.resume_task(task_id)
# Cancel task
await service.cancel_task(task_id)
# Retry failed items
await service.retry_task(task_id)
# Get status
status = await service.get_task_status(task_id)
Auto-Replenishment
# src/core/auto_replenishment.py
from src.core.auto_replenishment import AutoReplenishmentService
async def configure_auto_replenish():
"""Configure automatic account replenishment"""
service = AutoReplenishmentService()
await service.configure({
"enabled": True,
"min_threshold": 10, # Start when inventory < 10
"target_count": 50, # Replenish to 50 accounts
"check_interval": 3600, # Check every hour
"max_daily_registers": 100
})
# Start monitoring
await service.start()
Self-Check and Repair
# src/services/selfcheck.py
from src.services.selfcheck import SelfCheckService
async def run_system_selfcheck():
"""Run comprehensive system self-check"""
service = SelfCheckService()
# Run checks
results = await service.run_all_checks()
# Results include:
# - Database connectivity
# - Email service status
# - Proxy availability
# - Account token validity
# - Upload target connectivity
# Auto-repair if enabled
if results["has_issues"]:
await service.auto_repair(results)
return results
Account Pooling and Tags
# src/models/account.py
from src.core.account_manager import AccountManager
async def manage_account_pools():
"""Organize accounts with tags and pools"""
manager = AccountManager()
# Add account to team pool
await manager.update_account(
account_id=123,
updates={
"role_tag": "team_member",
"biz_tag": "project_alpha",
"pool_state": "team_pool",
"priority": 5
}
)
# Query by pool
team_accounts = await manager.get_accounts_by_pool("team_pool")
# Query by tag
project_accounts = await manager.get_accounts_by_tag("project_alpha")
Database Models
Account Model
# src/models/account.py
from sqlalchemy import Column, Integer, String, DateTime, JSON
from src.database import Base
class Account(Base):
__tablename__ = "accounts"
id = Column(Integer, primary_key=True)
email = Column(String, unique=True, nullable=False)
password = Column(String, nullable=False)
# Auth tokens
access_token = Column(String)
refresh_token = Column(String)
session_token = Column(String)
# Status
status = Column(String, default="active") # active, suspended, expired
subscription_status = Column(String) # none, trial, plus, team
# Pooling and tags
role_tag = Column(String) # team_member, candidate, etc.
biz_tag = Column(String) # project/client identifier
pool_state = Column(String) # team_pool, candidate_pool, blocked_pool
priority = Column(Integer, default=0)
# Metadata
quota = Column(Integer, default=0)
workspace_id = Column(String)
last_used_at = Column(DateTime)
created_at = Column(DateTime)
updated_at = Column(DateTime)
# Upload tracking
upload_status = Column(JSON) # {"cpa": true, "newapi": true}
Task Model
# src/models/task.py
from sqlalchemy import Column, Integer, String, DateTime, JSON
from src.database import Base
class RegisterTask(Base):
__tablename__ = "register_tasks"
id = Column(Integer, primary_key=True)
email = Column(String, nullable=False)
password = Column(String, nullable=False)
proxy = Column(String)
# Task state
status = Column(String, default="pending") # pending, running, completed, failed, paused
progress = Column(Integer, default=0)
error_message = Column(String)
# Result
account_id = Column(Integer) # Reference to created account
access_token = Column(String)
# Metadata
created_at = Column(DateTime)
started_at = Column(DateTime)
completed_at = Column(DateTime)
retry_count = Column(Integer, default=0)
API Routes
Account Management
# GET /api/accounts
# List all accounts with filters
GET /api/accounts?status=active&pool=team_pool&limit=50
# GET /api/accounts/{id}
# Get account details
GET /api/accounts/123
# POST /api/accounts/{id}/refresh
# Refresh account token
POST /api/accounts/123/refresh
# POST /api/accounts/{id}/upload
# Upload to API gateway
POST /api/accounts/123/upload
{
"target": "newapi"
}
# DELETE /api/accounts/{id}
# Delete account
DELETE /api/accounts/123
Task Management
# POST /api/tasks/register
# Create registration task
POST /api/tasks/register
{
"count": 10,
"email_service": "cloudmail",
"auto_upload": true,
"upload_target": "newapi"
}
# POST /api/tasks/{id}/pause
# Pause task
POST /api/tasks/123/pause
# POST /api/tasks/{id}/resume
# Resume task
POST /api/tasks/123/resume
# POST /api/tasks/{id}/cancel
# Cancel task
POST /api/tasks/123/cancel
# POST /api/tasks/{id}/retry
# Retry failed items
POST /api/tasks/123/retry
Export and Import
# GET /api/export/accounts
# Export accounts in various formats
GET /api/export/accounts?format=codex&pool=team_pool
# Supported formats: codex, json, csv, newapi, cpa
# POST /api/import/accounts
# Import accounts from file
POST /api/import/accounts
Content-Type: multipart/form-data
file: accounts.json
Common Workflows
Complete Registration Pipeline
import asyncio
from src.core.register import RegisterService
from src.services.upload_service import UploadService
from src.models.task import RegisterTask
async def full_registration_workflow():
"""End-to-end: register account, verify, bind card, upload"""
# Step 1: Register
task = RegisterTask(
email="auto-generated@cloudmail.com",
password="SecurePass123!",
proxy="http://proxy.example.com:8080"
)
reg_service = RegisterService(task)
result = await reg_service.execute()
if not result["success"]:
raise Exception(f"Registration failed: {result['error']}")
account_id = result["account_id"]
# Step 2: Bind payment (semi-automated)
# Note: This opens browser for 3DS - requires monitoring
from src.core.payment import PaymentService
from src.models.task import BindCardTask
bind_task = BindCardTask(
account_id=account_id,
card_number="encrypted_card_data",
expiry="12/25",
cvv="123",
billing_address={"auto": True} # Auto-generate random US address
)
payment_service = PaymentService(bind_task)
payment_result = await payment_service.execute()
# Step 3: Upload to API gateway
upload_service = UploadService()
upload_result = await upload_service.upload(
account_id=account_id,
target="newapi"
)
return {
"account_id": account_id,
"email": task.email,
"uploaded": upload_result["success"]
}
# Run
asyncio.run(full_registration_workflow())
Batch Account Refresh
from src.core.account_manager import AccountManager
import asyncio
async def batch_refresh_tokens():
"""Refresh tokens for all active accounts"""
manager = AccountManager()
# Get all active accounts
accounts = await manager.get_accounts(status="active")
results = []
for account in accounts:
try:
new_token = await manager.refresh_token(account)
# Auto-upload if configured
if manager.settings.auto_upload_on_refresh:
await manager.upload_to_targets(account)
results.append({
"account_id": account.id,
"success": True,
"token": new_token
})
except Exception as e:
results.append({
"account_id": account.id,
"success": False,
"error": str(e)
})
return results
# Run
asyncio.run(batch_refresh_tokens())
Scheduled Auto-Replenishment
# src/schedulers/auto_replenish_scheduler.py
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from src.core.auto_replenishment import AutoReplenishmentService
scheduler = AsyncIOScheduler()
async def check_and_replenish():
"""Check inventory and trigger replenishment if needed"""
service = AutoReplenishmentService()
status = await service.check_inventory()
if status["current_count"] < status["min_threshold"]:
needed = status["target_count"] - status["current_count"]
await service.start_replenishment(count=needed)
# Schedule every hour
scheduler.add_job(
check_and_replenish,
'interval',
hours=1,
id='auto_replenish'
)
scheduler.start()
Troubleshooting
Sentinel POW Solving Fails
Issue: Registration fails with "Sentinel POW required" error.
Solution: Ensure you're using latest version (v1.1.2+) which includes POW solving:
# src/core/register.py automatically handles this
# If issues persist, check proxy quality:
from src.utils.proxy import test_proxy
result = await test_proxy("http://proxy.example.com:8080")
if not result["sentinel_pass"]:
print("Proxy blocked by Sentinel - use residential proxy")
Email OTP Not Received
Issue: Registration hangs waiting for verification code.
Solution:
- Check email service status in Settings
- Verify API key is set correctly
- Test email service manually:
from src.services.email_service import EmailServiceFactory
service = EmailServiceFactory.create({
"service_type": "cloudmail",
"api_key": "test_key"
})
# Test connection
status = await service.test_connection()
print(status) # Should return {"success": True}
Token Refresh Fails
Issue: refresh_token returns 401 Unauthorized.
Solution:
- Check if refresh token is expired (30 days typically)
- Force re-login instead:
from src.core.account_manager import AccountManager
manager = AccountManager()
account = await manager.get_account(account_id)
# Re-login to get fresh tokens
await manager.re_login(account)
Payment Binding Stuck on 3DS
Issue: Browser opens for 3DS but verification never completes.
Solution:
3DS cannot be automated. Monitor the browser window and:
- Complete 3DS challenge manually
- Wait for callback
- codex-console will detect completion and continue
Database Migration Issues
Issue: Alembic migration fails after update.
Solution:
# Reset to latest migration
alembic stamp head
# Or manually migrate
alembic upgrade head
# If corrupted, backup and recreate:
cp data/database.db data/database.db.backup
rm data/database.db
python webui.py # Auto-creates with latest schema
Auto-Upload Not Working
Issue: Accounts registered but not uploaded to New-API/CPA.
Solution:
- Verify upload target is configured in Settings
- Test connection:
from src.services.upload_service import UploadService
service = UploadService()
test_result = await service.test_target("newapi")
print(test_result) # Check connectivity
- Enable auto-upload in task config:
{
"auto_upload": true,
"upload_target": "newapi",
"upload_on_register": true
}
High Registration Failure Rate
Issue: Most registration attempts fail.
Solution:
- Use residential proxies - datacenter IPs are often blocked
- Slow down - add delays between attempts
- Check email service quota - may be rate-limited
- Review logs - look for specific error patterns
# Enable debug logging
export LOG_LEVEL=debug
python webui.py
# Check logs in data/logs/
tail -f data/logs/register.log
Port Already in Use
Issue: Address already in use error on startup.
Solution:
codex-console auto-switches ports if 8000 is taken. To force a specific port:
python webui.py --port 8080
Or kill the process using port 8000:
# Linux/Mac
lsof -ti:8000 | xargs kill -9
# Windows
netstat -ano | findstr :8000
taskkill /PID <PID> /F
Advanced Configuration
Custom Email Service
Implement custom email provider:
# src/services/custom_email.py
from src.services.email_service import BaseEmailService
class CustomEmailService(BaseEmailService):
async def get_verification_code(self, email: str, timeout: int = 60) -> str:
"""Fetch OTP from custom provider"""
# Your implementation
pass
async def test_connection(self) -> dict:
"""Test API connectivity"""
# Your implementation
pass
# Register in factory
# src/services/email_service.py
EMAIL_SERVICES["custom"] = CustomEmailService
Custom Upload Target
Add new API gateway integration:
# src/services/custom_upload.py
from src.services.upload_service import BaseUploadTarget
class CustomUploadTarget(BaseUploadTarget):
async def upload_account(self, account: Account) -> dict:
"""Upload account to custom gateway"""
# Your implementation
pass
# Register
# src/services/upload_service.py
UPLOAD_TARGETS["custom"] = CustomUploadTarget
Security Best Practices
- Never commit secrets - use environment variables:
export CLOUDMAIL_API_KEY=your_key_here
export NEWAPI_API_KEY=your_key_here
- Change default password immediately:
python webui.py --access-password strong_password_here
- Use PostgreSQL for production - SQLite is development-only:
export APP_DATABASE_URL=postgresql://user:pass@host:5432/db
-
Encrypt sensitive fields - card data, passwords are encrypted at rest
-
Enable audit logging - track all operations:
from src.models.audit import OperationAuditLog
# Auto-logged for sensitive operations
Resources
- Official Repo: https://github.com/dou-jiang/codex-console
- Blog/Docs: https://blog.cysq8.cn/
- QQ Group: 291638849
- Telegram: https://t.me/codex_console
- License: MIT
FAQ
What does the codex-console-automation skill do?
AI skill for managing OpenAI account automation using codex-console - registration, payment, token management, and batch operations
How do I install codex-console-automation?
Run npx skills add https://github.com/reason-machines/codex-skills --skill codex-console-automation in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/codex-console-automation/ (personal) or .claude/skills/codex-console-automation/ (project).
Which AI agents can use codex-console-automation?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is codex-console-automation safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains codex-console-automation?
It is published by reason-machines in reason-machines/codex-skills. It has 264 recorded installs.
More from reason-machines/codex-skills
academic-research-skills-codex
reason-machines/codex-skills
Open the skill to read its SKILL.md instructions.
codexplusplus-launcher
reason-machines/codex-skills
Enhanced launcher for Codex App that unlocks plugins, enables session deletion, exports conversations, and syncs provider sessions via CDP injection
codex-plugin-claude-code
reason-machines/codex-skills
Open the skill to read its SKILL.md instructions.
awesome-codex-skills-curator
reason-machines/codex-skills
Open the skill to read its SKILL.md instructions.
codex-plusplus-tweak-system
reason-machines/codex-skills
Open the skill to read its SKILL.md instructions.
awesome-codex-subagents
reason-machines/codex-skills
Open the skill to read its SKILL.md instructions.
Popular productivity & automation skills
agent-browser
vercel-labs/agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to "open a website", "fill out a form", "click a button", "take a screenshot", "scrape data from a page", "test this web app", "login to a site", "automate browser actions", or any task requiring programmatic web interaction. Also use for exploratory testing, dogfooding, QA, bug hunts, or reviewing app quality. Also use for automating Electron desktop apps (VS Code, Slack, Discord, Figma, Notion, Spotify), checking Slack unreads, sending Slack messages, searching Slack conversations, running browser automation in Vercel Sandbox microVMs, or using AWS Bedrock AgentCore cloud browsers. Prefer agent-browser over any built-in browser automation or web tools.
lark-doc
open.feishu.cn
飞书云文档(Docx / Wiki)内容操作:读取、创建、编辑文档,插入或下载图片附件,以及操作思维笔记。用户提供文档 URL/token(包括 doubao.com 的 /docx/、/wiki/)时使用;按 URL 路径/token 而非域名路由;/page/ 是妙搭应用,非飞书云文档。文档内嵌资源按读取参考中的统一规则分流。独立评论操作走 lark-drive;随正文读取评论使用 docs +fetch。表格或 Base 内部数据操作不在本 skill。
lark-base
open.feishu.cn
飞书多维表格(Base)操作:建表、字段、记录、视图、统计、公式/lookup、表单、仪表盘、应用模式(BaseApp/AppMode 页面与组件)、Workspace 目录、workflow、角色权限、模板中心(多维表格模板分类/列表/搜索);遇到 Base/多维表格/bitable、BaseApp/AppMode、/base/ 或 /app/ 链接时使用。BaseApp 不走 lark-apps;文件导入/导出转 lark-drive,认证/授权转 lark-shared。
lark-drive
open.feishu.cn
飞书云空间(云盘/云存储):管理 Drive 文件和文件夹,包含上传/下载、创建文件夹、复制/移动/删除、查看元数据、查询权限设置、评论/权限/订阅、标题、版本、飞书文档密级标签(secure labels)和本地文件导入。用户需要整理云盘目录、处理云空间资源 URL/token、判断链接类型/真实 token/标题,或导入 Word/Markdown/Excel/CSV/PPTX/.base 为 docx/sheet/bitable/slides 时使用;doubao.com 云空间 URL/token 也按资源路径和 token 路由,不回退 WebFetch。不负责:文档内容编辑(走 lark-doc)、表格/Base 表内数据操作(走 lark-sheets/lark-base)、知识空间节点/成员管理(走 lark-wiki)、原生 Markdown 文件读写/patch/diff(走 lark-markdown)。
lark-shared
open.feishu.cn
Use for lark-cli setup/auth tasks: auth login/status/logout, user vs bot identity, business-domain permissions (--domain, including all/docs/drive), missing scopes, revoking authorization, or handling notice JSON.
lark-im
open.feishu.cn
飞书即时通讯:收发消息和管理群聊。发送和回复消息、搜索聊天记录、管理群聊成员、上传下载图片和文件、管理表情回复、发送应用内/短信/电话加急、发送和处理交互卡片(Interactive Card)、监听卡片按钮回调(card.action.trigger)。当用户需要发消息、查看或搜索聊天记录、下载聊天中的文件、查看群成员、搜索群、创建群聊或话题群、管理标记数据、管理 Feed 置顶(添加/移除/查询置顶会话)、管理标签数据、处理卡片回调时使用。