atlas-hq 0.1.0

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 ADDED
@@ -0,0 +1,52 @@
1
+ # atlas-hq
2
+
3
+ CLI launcher for [Atlas HQ](https://github.com/nord-initiatives/atlas_hq) — task management for AI agent teams.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ npx atlas-hq start
9
+ ```
10
+
11
+ That's it. Atlas HQ will be running at [http://localhost:3500](http://localhost:3500).
12
+
13
+ ## Requirements
14
+
15
+ - [Docker Desktop](https://docs.docker.com/get-docker/) (with Docker Compose V2)
16
+ - Node.js ≥ 18
17
+
18
+ ## Commands
19
+
20
+ | Command | Description |
21
+ | ----------------- | ------------------------------------ |
22
+ | `atlas-hq start` | Pull images and start the stack |
23
+ | `atlas-hq stop` | Stop the stack |
24
+ | `atlas-hq status` | Show running container status |
25
+ | `atlas-hq open` | Open the UI in your browser |
26
+ | `atlas-hq help` | Show help |
27
+
28
+ ## Options
29
+
30
+ | Flag | Description | Default |
31
+ | ----------------- | ------------------------------------ | ------- |
32
+ | `--port-api` | Host port for the API | 3501 |
33
+ | `--port-ui` | Host port for the UI | 3500 |
34
+
35
+ Environment variables `ATLAS_HQ_API_PORT` and `ATLAS_HQ_UI_PORT` also work.
36
+
37
+ ## Examples
38
+
39
+ ```bash
40
+ # Start with custom ports
41
+ npx atlas-hq start --port-ui 8080 --port-api 8081
42
+
43
+ # Check status
44
+ npx atlas-hq status
45
+
46
+ # Stop
47
+ npx atlas-hq stop
48
+ ```
49
+
50
+ ## License
51
+
52
+ MIT
package/bin/cli.mjs ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { run } from '../lib/index.mjs';
4
+
5
+ run(process.argv.slice(2));
@@ -0,0 +1,85 @@
1
+ ###############################################################################
2
+ # docker-compose.yml — Atlas HQ full-stack one-command local install
3
+ #
4
+ # Spins up:
5
+ # atlas-hq-api Atlas HQ API → http://localhost:3501
6
+ # atlas-hq-ui Atlas HQ UI → http://localhost:3500
7
+ #
8
+ # Named volume:
9
+ # atlas-hq-data SQLite database persistence (/data inside the API container)
10
+ #
11
+ # ── Quick start ───────────────────────────────────────────────────────────────
12
+ # docker compose up # build images and start everything (foreground)
13
+ # docker compose up -d # same, detached
14
+ # docker compose down # stop and remove containers (data volume kept)
15
+ # docker compose down -v # ⚠️ also removes the data volume (wipes DB)
16
+ #
17
+ # ── Local overrides ───────────────────────────────────────────────────────────
18
+ # Copy docker-compose.override.yml.example to docker-compose.override.yml
19
+ # and edit it. Docker Compose merges it automatically — no extra flags needed.
20
+ #
21
+ # ── Environment variables ─────────────────────────────────────────────────────
22
+ # ATLAS_HQ_API_PORT Host port for the API (default: 3501)
23
+ # ATLAS_HQ_UI_PORT Host port for the UI (default: 3500)
24
+ # NEXT_PUBLIC_API_URL API URL baked into the UI build
25
+ # (default: http://localhost:3501)
26
+ ###############################################################################
27
+
28
+ name: atlas-hq
29
+
30
+ # ── Named volume for SQLite persistence ───────────────────────────────────────
31
+ volumes:
32
+ atlas-hq-data:
33
+ driver: local
34
+
35
+ # ── Services ──────────────────────────────────────────────────────────────────
36
+ services:
37
+
38
+ # ── API ─────────────────────────────────────────────────────────────────────
39
+ atlas-hq-api:
40
+ build:
41
+ context: .
42
+ dockerfile: docker/Dockerfile.api
43
+ image: atlas-hq-api:local
44
+ container_name: atlas-hq-api
45
+ restart: unless-stopped
46
+ ports:
47
+ - "${ATLAS_HQ_API_PORT:-3501}:3501"
48
+ volumes:
49
+ - atlas-hq-data:/data
50
+ environment:
51
+ NODE_ENV: production
52
+ PORT: "3501"
53
+ ATLAS_HQ_DB_PATH: /data/atlas.db
54
+ ATLAS_HQ_DATA_DIR: /data
55
+ healthcheck:
56
+ test: ["CMD", "wget", "-qO-", "http://localhost:3501/health"]
57
+ interval: 30s
58
+ timeout: 10s
59
+ retries: 5
60
+ start_period: 15s
61
+
62
+ # ── UI ──────────────────────────────────────────────────────────────────────
63
+ atlas-hq-ui:
64
+ build:
65
+ context: .
66
+ dockerfile: docker/Dockerfile.ui
67
+ args:
68
+ NEXT_PUBLIC_API_URL: "${NEXT_PUBLIC_API_URL:-http://localhost:3501}"
69
+ image: atlas-hq-ui:local
70
+ container_name: atlas-hq-ui
71
+ restart: unless-stopped
72
+ ports:
73
+ - "${ATLAS_HQ_UI_PORT:-3500}:3500"
74
+ environment:
75
+ NODE_ENV: production
76
+ PORT: "3500"
77
+ depends_on:
78
+ atlas-hq-api:
79
+ condition: service_healthy
80
+ healthcheck:
81
+ test: ["CMD", "wget", "-qO-", "http://localhost:3500"]
82
+ interval: 30s
83
+ timeout: 10s
84
+ retries: 5
85
+ start_period: 20s
package/lib/index.mjs ADDED
@@ -0,0 +1,211 @@
1
+ import { execSync, execFileSync } from 'node:child_process';
2
+ import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { homedir } from 'node:os';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ const __dirname = fileURLToPath(new URL('.', import.meta.url));
8
+ const COMPOSE_SOURCE = join(__dirname, '..', 'docker-compose.yml');
9
+
10
+ // Data directory where we keep the compose file and any local config
11
+ const DATA_DIR = join(homedir(), '.atlas-hq');
12
+
13
+ const HELP = `
14
+ atlas-hq — CLI launcher for Atlas HQ
15
+
16
+ Usage:
17
+ atlas-hq <command> [options]
18
+
19
+ Commands:
20
+ start Pull images and start the Atlas HQ stack
21
+ stop Stop the Atlas HQ stack
22
+ status Show running container status
23
+ open Open the Atlas HQ UI in a browser
24
+ help Show this help message
25
+
26
+ Options:
27
+ --port-api <port> Host port for the API (default: 3501, env: ATLAS_HQ_API_PORT)
28
+ --port-ui <port> Host port for the UI (default: 3500, env: ATLAS_HQ_UI_PORT)
29
+
30
+ Examples:
31
+ npx atlas-hq start
32
+ npx atlas-hq start --port-ui 8080
33
+ npx atlas-hq stop
34
+ `.trim();
35
+
36
+ // ── Helpers ──────────────────────────────────────────────────────────────────
37
+
38
+ function die(msg) {
39
+ console.error(`\x1b[31m✗\x1b[0m ${msg}`);
40
+ process.exit(1);
41
+ }
42
+
43
+ function info(msg) {
44
+ console.log(`\x1b[36mℹ\x1b[0m ${msg}`);
45
+ }
46
+
47
+ function success(msg) {
48
+ console.log(`\x1b[32m✓\x1b[0m ${msg}`);
49
+ }
50
+
51
+ function checkDocker() {
52
+ try {
53
+ execFileSync('docker', ['--version'], { stdio: 'pipe' });
54
+ } catch {
55
+ die(
56
+ 'Docker is not installed or not in PATH.\n' +
57
+ ' Install Docker Desktop: https://docs.docker.com/get-docker/\n' +
58
+ ' Then run this command again.'
59
+ );
60
+ }
61
+
62
+ // Check Docker daemon is running
63
+ try {
64
+ execFileSync('docker', ['info'], { stdio: 'pipe' });
65
+ } catch {
66
+ die(
67
+ 'Docker daemon is not running.\n' +
68
+ ' Start Docker Desktop and try again.'
69
+ );
70
+ }
71
+
72
+ // Check docker compose is available
73
+ try {
74
+ execFileSync('docker', ['compose', 'version'], { stdio: 'pipe' });
75
+ } catch {
76
+ die(
77
+ 'Docker Compose (V2) is not available.\n' +
78
+ ' Update Docker Desktop or install the compose plugin:\n' +
79
+ ' https://docs.docker.com/compose/install/'
80
+ );
81
+ }
82
+ }
83
+
84
+ function ensureDataDir() {
85
+ if (!existsSync(DATA_DIR)) {
86
+ mkdirSync(DATA_DIR, { recursive: true });
87
+ }
88
+ // Copy compose file into data dir so Docker Compose has a stable project dir
89
+ const dest = join(DATA_DIR, 'docker-compose.yml');
90
+ writeFileSync(dest, readFileSync(COMPOSE_SOURCE));
91
+ return DATA_DIR;
92
+ }
93
+
94
+ function compose(args, opts = {}) {
95
+ const cwd = ensureDataDir();
96
+ const cmd = ['docker', 'compose', ...args].join(' ');
97
+ try {
98
+ execSync(cmd, { cwd, stdio: 'inherit', ...opts });
99
+ } catch (e) {
100
+ if (!opts.ignoreError) {
101
+ die(`Command failed: ${cmd}`);
102
+ }
103
+ }
104
+ }
105
+
106
+ function parseFlags(argv) {
107
+ const flags = {};
108
+ for (let i = 0; i < argv.length; i++) {
109
+ if (argv[i] === '--port-api' && argv[i + 1]) {
110
+ flags.apiPort = argv[++i];
111
+ } else if (argv[i] === '--port-ui' && argv[i + 1]) {
112
+ flags.uiPort = argv[++i];
113
+ }
114
+ }
115
+ return flags;
116
+ }
117
+
118
+ function setPortEnv(flags) {
119
+ if (flags.apiPort) process.env.ATLAS_HQ_API_PORT = flags.apiPort;
120
+ if (flags.uiPort) process.env.ATLAS_HQ_UI_PORT = flags.uiPort;
121
+ }
122
+
123
+ function getUiPort() {
124
+ return process.env.ATLAS_HQ_UI_PORT || '3500';
125
+ }
126
+
127
+ function openBrowser(url) {
128
+ const platform = process.platform;
129
+ try {
130
+ if (platform === 'darwin') {
131
+ execFileSync('open', [url], { stdio: 'pipe' });
132
+ } else if (platform === 'win32') {
133
+ execFileSync('cmd', ['/c', 'start', url], { stdio: 'pipe' });
134
+ } else {
135
+ execFileSync('xdg-open', [url], { stdio: 'pipe' });
136
+ }
137
+ } catch {
138
+ info(`Could not open browser automatically. Visit: ${url}`);
139
+ }
140
+ }
141
+
142
+ // ── Commands ─────────────────────────────────────────────────────────────────
143
+
144
+ function cmdStart(flags) {
145
+ checkDocker();
146
+ setPortEnv(flags);
147
+ const uiPort = getUiPort();
148
+ const apiPort = process.env.ATLAS_HQ_API_PORT || '3501';
149
+
150
+ info('Pulling latest Atlas HQ images…');
151
+ compose(['pull']);
152
+
153
+ info('Starting Atlas HQ…');
154
+ compose(['up', '-d', '--remove-orphans']);
155
+
156
+ success(`Atlas HQ is starting!`);
157
+ console.log(` UI: http://localhost:${uiPort}`);
158
+ console.log(` API: http://localhost:${apiPort}`);
159
+ console.log(`\n Run \x1b[1matlas-hq open\x1b[0m to open the UI in your browser.`);
160
+ }
161
+
162
+ function cmdStop() {
163
+ checkDocker();
164
+ info('Stopping Atlas HQ…');
165
+ compose(['down']);
166
+ success('Atlas HQ stopped.');
167
+ }
168
+
169
+ function cmdStatus() {
170
+ checkDocker();
171
+ ensureDataDir();
172
+ compose(['ps'], { ignoreError: true });
173
+ }
174
+
175
+ function cmdOpen(flags) {
176
+ setPortEnv(flags);
177
+ const uiPort = getUiPort();
178
+ const url = `http://localhost:${uiPort}`;
179
+ info(`Opening ${url}…`);
180
+ openBrowser(url);
181
+ }
182
+
183
+ // ── Main ─────────────────────────────────────────────────────────────────────
184
+
185
+ export function run(argv) {
186
+ const command = argv[0];
187
+ const flags = parseFlags(argv.slice(1));
188
+
189
+ switch (command) {
190
+ case 'start':
191
+ cmdStart(flags);
192
+ break;
193
+ case 'stop':
194
+ cmdStop();
195
+ break;
196
+ case 'status':
197
+ cmdStatus();
198
+ break;
199
+ case 'open':
200
+ cmdOpen(flags);
201
+ break;
202
+ case 'help':
203
+ case '--help':
204
+ case '-h':
205
+ case undefined:
206
+ console.log(HELP);
207
+ break;
208
+ default:
209
+ die(`Unknown command: ${command}\n\nRun \x1b[1matlas-hq help\x1b[0m for usage.`);
210
+ }
211
+ }
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "atlas-hq",
3
+ "version": "0.1.0",
4
+ "description": "CLI launcher for Atlas HQ — task management for AI agent teams",
5
+ "license": "MIT",
6
+ "bin": {
7
+ "atlas-hq": "./bin/cli.mjs"
8
+ },
9
+ "type": "module",
10
+ "engines": {
11
+ "node": ">=18"
12
+ },
13
+ "files": [
14
+ "bin/",
15
+ "lib/",
16
+ "docker-compose.yml",
17
+ "README.md"
18
+ ],
19
+ "keywords": [
20
+ "atlas-hq",
21
+ "task-management",
22
+ "ai-agents",
23
+ "docker",
24
+ "cli"
25
+ ],
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/nord-initiatives/atlas_hq"
29
+ }
30
+ }