feat: add frictionless RA-H OS setup
- Add MCP setup, doctor, init-db, config, and rules CLI commands - Publish latest MCP package wiring and local setup helper - Update OS install docs for MCP-only, full app, and demo-safe setup Generated with Claude Code
This commit is contained in:
@@ -78,6 +78,38 @@ function ensureEnvFile() {
|
||||
log('Created .env.local from .env.example');
|
||||
}
|
||||
|
||||
function ensureEnvValue(key, value) {
|
||||
if (!value) return;
|
||||
|
||||
const lines = fs.existsSync(targetEnv)
|
||||
? fs.readFileSync(targetEnv, 'utf8').split(/\r?\n/)
|
||||
: [];
|
||||
let found = false;
|
||||
|
||||
const nextLines = lines.map((line) => {
|
||||
const trimmed = line.trim();
|
||||
if (trimmed.startsWith(`${key}=`)) {
|
||||
found = true;
|
||||
return `${key}=${value}`;
|
||||
}
|
||||
if (trimmed.startsWith(`# ${key}=`) || trimmed.startsWith(`#${key}=`)) {
|
||||
found = true;
|
||||
return `${key}=${value}`;
|
||||
}
|
||||
return line;
|
||||
});
|
||||
|
||||
if (!found) {
|
||||
if (nextLines.length > 0 && nextLines[nextLines.length - 1] !== '') {
|
||||
nextLines.push('');
|
||||
}
|
||||
nextLines.push(`${key}=${value}`);
|
||||
}
|
||||
|
||||
fs.writeFileSync(targetEnv, `${nextLines.join('\n').replace(/\n+$/, '')}\n`);
|
||||
log(`Set ${key} in .env.local`);
|
||||
}
|
||||
|
||||
function ensureCoreSchema(db) {
|
||||
db.pragma('foreign_keys = ON');
|
||||
db.exec(`
|
||||
@@ -550,7 +582,10 @@ function main() {
|
||||
ensureEnvFile();
|
||||
|
||||
const env = parseEnvFile(targetEnv);
|
||||
const dbPath = expandPath(env.SQLITE_DB_PATH || getDefaultDbPath());
|
||||
if (process.env.SQLITE_DB_PATH) {
|
||||
ensureEnvValue('SQLITE_DB_PATH', process.env.SQLITE_DB_PATH);
|
||||
}
|
||||
const dbPath = expandPath(process.env.SQLITE_DB_PATH || env.SQLITE_DB_PATH || getDefaultDbPath());
|
||||
fs.mkdirSync(path.dirname(dbPath), { recursive: true });
|
||||
if (!fs.existsSync(dbPath)) {
|
||||
fs.closeSync(fs.openSync(dbPath, 'w'));
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { spawnSync } from 'node:child_process';
|
||||
|
||||
function run(command, args) {
|
||||
const result = spawnSync(command, args, {
|
||||
stdio: 'inherit',
|
||||
env: process.env,
|
||||
});
|
||||
|
||||
if (result.status !== 0) {
|
||||
process.exit(result.status || 1);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[setup-local] Rebuilding better-sqlite3 native bindings');
|
||||
run('npm', ['rebuild', 'better-sqlite3']);
|
||||
|
||||
console.log('[setup-local] Bootstrapping local RA-H database');
|
||||
run('npm', ['run', 'bootstrap:local']);
|
||||
|
||||
console.log('');
|
||||
console.log('[setup-local] Local app setup complete.');
|
||||
console.log('[setup-local] Next: npm run dev');
|
||||
console.log('[setup-local] Optional MCP setup: npx -y ra-h-mcp-server@latest setup --client claude-code');
|
||||
@@ -2,8 +2,10 @@
|
||||
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const ROOT = process.cwd();
|
||||
const SCRIPT_DIR = path.dirname(fileURLToPath(import.meta.url));
|
||||
const ROOT = path.resolve(SCRIPT_DIR, '..', '..');
|
||||
const APP_SKILLS_DIR = path.join(ROOT, 'src/config/skills');
|
||||
const STANDALONE_SKILLS_DIR = path.join(ROOT, 'apps/mcp-server-standalone/skills');
|
||||
const CHECK_ONLY = process.argv.includes('--check');
|
||||
|
||||
Reference in New Issue
Block a user