@aion0/forge 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -31,6 +31,12 @@ No API keys required. Forge runs on your existing Claude Code subscription.
31
31
 
32
32
  ```bash
33
33
  npm install -g @aion0/forge
34
+
35
+ # Start the server
36
+ forge-server
37
+
38
+ # Or in development mode
39
+ forge-server --dev
34
40
  ```
35
41
 
36
42
  ### From source
@@ -39,38 +45,12 @@ npm install -g @aion0/forge
39
45
  git clone https://github.com/aiwatching/forge.git
40
46
  cd forge
41
47
  pnpm install
42
- pnpm build
48
+ pnpm dev
43
49
  ```
44
50
 
45
51
  ## Quick Start
46
52
 
47
- ### 1. Create config
48
-
49
- Create `.env.local` in the project root:
50
-
51
- ```env
52
- # Auth (generate a random string, e.g. openssl rand -hex 32)
53
- AUTH_SECRET=<random-string>
54
- AUTH_TRUST_HOST=true
55
-
56
- # Optional: Google OAuth for production
57
- # GOOGLE_CLIENT_ID=...
58
- # GOOGLE_CLIENT_SECRET=...
59
- ```
60
-
61
- > **API keys are not required.** Forge uses your local Claude Code CLI, which runs on your Anthropic subscription. If you want to use the built-in multi-model chat feature, you can optionally add provider keys (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GOOGLE_GENERATIVE_AI_API_KEY`, `XAI_API_KEY`) later.
62
-
63
- ### 2. Start the server
64
-
65
- ```bash
66
- # Development
67
- pnpm dev
68
-
69
- # Production
70
- pnpm build && pnpm start
71
- ```
72
-
73
- ### 3. Log in
53
+ ### 1. Log in
74
54
 
75
55
  Open `http://localhost:3000`. A login password is auto-generated and printed in the console:
76
56
 
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * forge-server — Start the Forge web platform.
4
+ *
5
+ * Usage:
6
+ * forge-server Start in production mode (builds first if needed)
7
+ * forge-server --dev Start in development mode
8
+ */
9
+
10
+ import { execSync, spawn } from 'node:child_process';
11
+ import { existsSync } from 'node:fs';
12
+ import { join, dirname } from 'node:path';
13
+ import { fileURLToPath } from 'node:url';
14
+
15
+ const __dirname = dirname(fileURLToPath(import.meta.url));
16
+ const ROOT = join(__dirname, '..');
17
+ const isDev = process.argv.includes('--dev');
18
+
19
+ process.chdir(ROOT);
20
+
21
+ if (isDev) {
22
+ console.log('[forge] Starting in development mode...');
23
+ const child = spawn('npx', ['next', 'dev', '--turbopack'], {
24
+ cwd: ROOT,
25
+ stdio: 'inherit',
26
+ env: { ...process.env },
27
+ });
28
+ child.on('exit', (code) => process.exit(code || 0));
29
+ } else {
30
+ // Build if .next doesn't exist
31
+ if (!existsSync(join(ROOT, '.next'))) {
32
+ console.log('[forge] Building...');
33
+ execSync('npx next build', { cwd: ROOT, stdio: 'inherit' });
34
+ }
35
+ console.log('[forge] Starting server...');
36
+ const child = spawn('npx', ['next', 'start'], {
37
+ cwd: ROOT,
38
+ stdio: 'inherit',
39
+ env: { ...process.env },
40
+ });
41
+ child.on('exit', (code) => process.exit(code || 0));
42
+ }
package/cli/mw.ts CHANGED
File without changes
@@ -836,7 +836,7 @@ const MemoTerminalPane = memo(function TerminalPane({
836
836
  fontSize: 13,
837
837
  fontFamily: 'Menlo, Monaco, "Courier New", monospace',
838
838
  scrollback: 10000,
839
- logger: { debug: () => {}, info: () => {}, warn: () => {}, error: () => {} },
839
+ logger: { trace: () => {}, debug: () => {}, info: () => {}, warn: () => {}, error: () => {} },
840
840
  theme: {
841
841
  background: '#1a1a2e',
842
842
  foreground: '#e0e0e0',
@@ -222,8 +222,7 @@ function executeTask(task: Task): Promise<void> {
222
222
 
223
223
  // Resolve the actual claude CLI script path (claude is a symlink to a .js file)
224
224
  const resolvedClaude = resolveClaudePath(claudePath);
225
- console.log(`[task-runner] Spawning: ${resolvedClaude.cmd} ${resolvedClaude.prefix.concat(args).join(' ')}`);
226
- console.log(`[task-runner] CWD: ${task.projectPath}`);
225
+ console.log(`[task] ${task.projectName}: "${task.prompt.slice(0, 60)}..."`);
227
226
 
228
227
  const child = spawn(resolvedClaude.cmd, [...resolvedClaude.prefix, ...args], {
229
228
  cwd: task.projectPath,
@@ -243,7 +242,7 @@ function executeTask(task: Task): Promise<void> {
243
242
  });
244
243
 
245
244
  child.stdout?.on('data', (data: Buffer) => {
246
- console.log(`[task-runner] stdout chunk: ${data.toString().slice(0, 200)}`);
245
+ // stdout chunk processing (silent)
247
246
 
248
247
  // Check if cancelled
249
248
  if (getTask(task.id)?.status === 'cancelled') {
@@ -275,14 +274,14 @@ function executeTask(task: Task): Promise<void> {
275
274
 
276
275
  child.stderr?.on('data', (data: Buffer) => {
277
276
  const text = data.toString().trim();
278
- console.error(`[task-runner] stderr: ${text.slice(0, 300)}`);
277
+ // stderr logged to task log only
279
278
  if (text) {
280
279
  appendLog(task.id, { type: 'system', subtype: 'error', content: text, timestamp: new Date().toISOString() });
281
280
  }
282
281
  });
283
282
 
284
283
  child.on('exit', (code, signal) => {
285
- console.log(`[task-runner] Process exited: code=${code}, signal=${signal}`);
284
+ // Process exit handled below
286
285
  // Process remaining buffer
287
286
  if (buffer.trim()) {
288
287
  try {
@@ -511,7 +510,7 @@ function startMonitorTask(task: Task) {
511
510
  const stopTail = tailSessionFile(fp, (newEntries) => {
512
511
  lastActivityTime = Date.now();
513
512
  lastEntryCount += newEntries.length;
514
- console.log(`[monitor] ${task.id}: +${newEntries.length} entries (${lastEntryCount} total)`);
513
+ // Monitor entries tracked in task log only
515
514
 
516
515
  appendLog(task.id, {
517
516
  type: 'system', subtype: 'text',
@@ -105,7 +105,7 @@ async function poll() {
105
105
 
106
106
  async function handleMessage(msg: any) {
107
107
  const chatId = msg.chat.id;
108
- console.log(`[telegram] Message from chat ID: ${chatId}, user: ${msg.from?.username || msg.from?.first_name || 'unknown'}`);
108
+ // Message received (logged silently)
109
109
  const text: string = msg.text.trim();
110
110
  const replyTo = msg.reply_to_message?.message_id;
111
111
 
@@ -245,7 +245,7 @@ wss.on('connection', (ws: WebSocket) => {
245
245
  } as Record<string, string>,
246
246
  });
247
247
 
248
- console.log(`[terminal] Attached to tmux session "${name}" (pid: ${term.pid})`);
248
+ // Attached to tmux session (silent)
249
249
  ws.send(JSON.stringify({ type: 'connected', sessionName: name }));
250
250
 
251
251
  term.onData((data: string) => {
@@ -344,7 +344,7 @@ wss.on('connection', (ws: WebSocket) => {
344
344
  // Only kill the pty attach process, NOT the tmux session — it persists
345
345
  if (term) {
346
346
  term.kill();
347
- console.log(`[terminal] Detached from tmux session "${sessionName}"`);
347
+ // Detached from tmux session (silent)
348
348
  }
349
349
 
350
350
  // Untrack this client
package/next-env.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /// <reference types="next" />
2
2
  /// <reference types="next/image-types/global" />
3
- import "./.next/dev/types/routes.d.ts";
3
+ import "./.next/types/routes.d.ts";
4
4
 
5
5
  // NOTE: This file should not be edited
6
6
  // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aion0/forge",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Unified AI workflow platform — multi-model task orchestration, persistent sessions, web terminal, remote access",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -11,6 +11,7 @@
11
11
  },
12
12
  "bin": {
13
13
  "forge": "./cli/mw.ts",
14
+ "forge-server": "./bin/forge-server.mjs",
14
15
  "mw": "./cli/mw.ts"
15
16
  },
16
17
  "keywords": [