chore: import upstream snapshot with attribution
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:20:55 +08:00
commit d25d482dc2
13754 changed files with 4996608 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
# Sim CLI
Sim CLI allows you to run [Sim](https://sim.ai) using Docker with a single command.
## Installation
To install the Sim CLI globally, use:
```bash
npm install -g simstudio
```
## Usage
To start Sim, simply run:
```bash
simstudio
```
### Options
- `-p, --port <port>`: Specify the port to run Sim on (default: 3000).
- `--no-pull`: Skip pulling the latest Docker images.
## Requirements
- Docker must be installed and running on your machine.
## Contributing
Contributions are welcome! Please open an issue or submit a pull request.
## License
This project is licensed under the Apache-2.0 License.
+54
View File
@@ -0,0 +1,54 @@
{
"name": "simstudio",
"version": "0.1.19",
"description": "Sim CLI - Run Sim with a single command",
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
},
"bin": {
"simstudio": "dist/index.js"
},
"scripts": {
"build": "tsc",
"type-check": "tsc --noEmit",
"lint": "biome check --write --unsafe .",
"lint:check": "biome check .",
"format": "biome format --write .",
"format:check": "biome format .",
"prepublishOnly": "bun run build"
},
"files": [
"dist"
],
"keywords": [
"simstudio",
"ai",
"workflow",
"cli",
"agent",
"automation",
"docker"
],
"author": "Sim",
"license": "Apache-2.0",
"engines": {
"node": ">=16"
},
"dependencies": {
"chalk": "^4.1.2",
"commander": "^11.1.0",
"dotenv": "^16.3.1",
"inquirer": "^8.2.6",
"listr2": "^6.6.1"
},
"devDependencies": {
"@sim/tsconfig": "workspace:*",
"@types/inquirer": "^8.2.6",
"@types/node": "^20.5.1",
"typescript": "^7.0.2"
}
}
+286
View File
@@ -0,0 +1,286 @@
#!/usr/bin/env node
import { execSync, spawn } from 'child_process'
import { existsSync, mkdirSync } from 'fs'
import { homedir } from 'os'
import { join } from 'path'
import { createInterface } from 'readline'
import chalk from 'chalk'
import { Command } from 'commander'
const NETWORK_NAME = 'simstudio-network'
const DB_CONTAINER = 'simstudio-db'
const MIGRATIONS_CONTAINER = 'simstudio-migrations'
const REALTIME_CONTAINER = 'simstudio-realtime'
const APP_CONTAINER = 'simstudio-app'
const DEFAULT_PORT = '3000'
const program = new Command()
program.name('simstudio').description('Run Sim using Docker').version('0.1.0')
program
.option('-p, --port <port>', 'Port to run Sim on', DEFAULT_PORT)
.option('-y, --yes', 'Skip interactive prompts and use defaults')
.option('--no-pull', 'Skip pulling the latest Docker images')
function isDockerRunning(): Promise<boolean> {
return new Promise((resolve) => {
const docker = spawn('docker', ['info'])
docker.on('close', (code) => {
resolve(code === 0)
})
})
}
async function runCommand(command: string[]): Promise<boolean> {
return new Promise((resolve) => {
const process = spawn(command[0], command.slice(1), { stdio: 'inherit' })
process.on('error', () => {
resolve(false)
})
process.on('close', (code) => {
resolve(code === 0)
})
})
}
async function ensureNetworkExists(): Promise<boolean> {
try {
const networks = execSync('docker network ls --format "{{.Name}}"').toString()
if (!networks.includes(NETWORK_NAME)) {
console.log(chalk.blue(`🔄 Creating Docker network '${NETWORK_NAME}'...`))
return await runCommand(['docker', 'network', 'create', NETWORK_NAME])
}
return true
} catch (error) {
console.error('Failed to check networks:', error)
return false
}
}
async function pullImage(image: string): Promise<boolean> {
console.log(chalk.blue(`🔄 Pulling image ${image}...`))
return await runCommand(['docker', 'pull', image])
}
async function stopAndRemoveContainer(name: string): Promise<void> {
try {
execSync(`docker stop ${name} 2>/dev/null || true`)
execSync(`docker rm ${name} 2>/dev/null || true`)
} catch (_error) {
// Ignore errors, container might not exist
}
}
async function cleanupExistingContainers(): Promise<void> {
console.log(chalk.blue('🧹 Cleaning up any existing containers...'))
await stopAndRemoveContainer(APP_CONTAINER)
await stopAndRemoveContainer(DB_CONTAINER)
await stopAndRemoveContainer(MIGRATIONS_CONTAINER)
await stopAndRemoveContainer(REALTIME_CONTAINER)
}
async function main() {
const options = program.parse().opts()
console.log(chalk.blue('🚀 Starting Sim...'))
// Check if Docker is installed and running
const dockerRunning = await isDockerRunning()
if (!dockerRunning) {
console.error(
chalk.red('❌ Docker is not running or not installed. Please start Docker and try again.')
)
process.exit(1)
}
// Use port from options, with 3000 as default
const port = options.port
// Pull latest images if not skipped
if (options.pull) {
await pullImage('ghcr.io/simstudioai/simstudio:latest')
await pullImage('ghcr.io/simstudioai/migrations:latest')
await pullImage('ghcr.io/simstudioai/realtime:latest')
await pullImage('pgvector/pgvector:pg17')
}
// Ensure Docker network exists
if (!(await ensureNetworkExists())) {
console.error(chalk.red('❌ Failed to create Docker network'))
process.exit(1)
}
// Clean up any existing containers
await cleanupExistingContainers()
// Create data directory
const dataDir = join(homedir(), '.simstudio', 'data')
if (!existsSync(dataDir)) {
try {
mkdirSync(dataDir, { recursive: true })
} catch (_error) {
console.error(chalk.red(`❌ Failed to create data directory: ${dataDir}`))
process.exit(1)
}
}
// Start PostgreSQL container
console.log(chalk.blue('🔄 Starting PostgreSQL database...'))
const dbSuccess = await runCommand([
'docker',
'run',
'-d',
'--name',
DB_CONTAINER,
'--network',
NETWORK_NAME,
'-e',
'POSTGRES_USER=postgres',
'-e',
'POSTGRES_PASSWORD=postgres',
'-e',
'POSTGRES_DB=simstudio',
'-v',
`${dataDir}/postgres:/var/lib/postgresql/data`,
'-p',
'5432:5432',
'pgvector/pgvector:pg17',
])
if (!dbSuccess) {
console.error(chalk.red('❌ Failed to start PostgreSQL'))
process.exit(1)
}
// Wait for PostgreSQL to be ready
console.log(chalk.blue('⏳ Waiting for PostgreSQL to be ready...'))
let pgReady = false
for (let i = 0; i < 30; i++) {
try {
execSync(`docker exec ${DB_CONTAINER} pg_isready -U postgres`)
pgReady = true
break
} catch (_error) {
await new Promise((resolve) => setTimeout(resolve, 1000))
}
}
if (!pgReady) {
console.error(chalk.red('❌ PostgreSQL failed to become ready'))
process.exit(1)
}
// Run migrations
console.log(chalk.blue('🔄 Running database migrations...'))
const migrationsSuccess = await runCommand([
'docker',
'run',
'--rm',
'--name',
MIGRATIONS_CONTAINER,
'--network',
NETWORK_NAME,
'-e',
`DATABASE_URL=postgresql://postgres:postgres@${DB_CONTAINER}:5432/simstudio`,
'ghcr.io/simstudioai/migrations:latest',
'bun',
'run',
'db:migrate',
])
if (!migrationsSuccess) {
console.error(chalk.red('❌ Failed to run migrations'))
process.exit(1)
}
// Start the realtime server
console.log(chalk.blue('🔄 Starting Realtime Server...'))
const realtimeSuccess = await runCommand([
'docker',
'run',
'-d',
'--name',
REALTIME_CONTAINER,
'--network',
NETWORK_NAME,
'-p',
'3002:3002',
'-e',
`DATABASE_URL=postgresql://postgres:postgres@${DB_CONTAINER}:5432/simstudio`,
'-e',
`BETTER_AUTH_URL=http://localhost:${port}`,
'-e',
`NEXT_PUBLIC_APP_URL=http://localhost:${port}`,
'-e',
'BETTER_AUTH_SECRET=your_auth_secret_here',
'ghcr.io/simstudioai/realtime:latest',
])
if (!realtimeSuccess) {
console.error(chalk.red('❌ Failed to start Realtime Server'))
process.exit(1)
}
// Start the main application
console.log(chalk.blue('🔄 Starting Sim...'))
const appSuccess = await runCommand([
'docker',
'run',
'-d',
'--name',
APP_CONTAINER,
'--network',
NETWORK_NAME,
'-p',
`${port}:3000`,
'-e',
`DATABASE_URL=postgresql://postgres:postgres@${DB_CONTAINER}:5432/simstudio`,
'-e',
`BETTER_AUTH_URL=http://localhost:${port}`,
'-e',
`NEXT_PUBLIC_APP_URL=http://localhost:${port}`,
'-e',
'BETTER_AUTH_SECRET=your_auth_secret_here',
'-e',
'ENCRYPTION_KEY=your_encryption_key_here',
'ghcr.io/simstudioai/simstudio:latest',
])
if (!appSuccess) {
console.error(chalk.red('❌ Failed to start Sim'))
process.exit(1)
}
console.log(chalk.green(`✅ Sim is now running at ${chalk.bold(`http://localhost:${port}`)}`))
console.log(
chalk.yellow(
`🛑 To stop all containers, run: ${chalk.bold('docker stop simstudio-app simstudio-db simstudio-realtime')}`
)
)
// Handle Ctrl+C
const rl = createInterface({
input: process.stdin,
output: process.stdout,
})
rl.on('SIGINT', async () => {
console.log(chalk.yellow('\n🛑 Stopping Sim...'))
// Stop containers
await stopAndRemoveContainer(APP_CONTAINER)
await stopAndRemoveContainer(DB_CONTAINER)
await stopAndRemoveContainer(REALTIME_CONTAINER)
console.log(chalk.green('✅ Sim has been stopped'))
process.exit(0)
})
}
main().catch((error) => {
console.error(chalk.red('❌ An error occurred:'), error)
process.exit(1)
})
+12
View File
@@ -0,0 +1,12 @@
{
"extends": "@sim/tsconfig/library-build.json",
"compilerOptions": {
"target": "ES2020",
"module": "nodenext",
"moduleResolution": "nodenext",
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}