@startanaicompany/cli 1.4.21 → 1.6.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/.claude/settings.local.json +10 -0
- package/CLAUDE.md +67 -7
- package/README.md +453 -18
- package/bin/saac.js +2 -6
- package/package.json +1 -1
- package/src/commands/create.js +13 -12
- package/src/commands/delete.js +6 -4
- package/src/commands/deploy.js +6 -4
- package/src/commands/deployments.js +5 -3
- package/src/commands/domain.js +9 -5
- package/src/commands/env.js +9 -5
- package/src/commands/exec.js +9 -5
- package/src/commands/git.js +13 -17
- package/src/commands/init.js +116 -20
- package/src/commands/keys.js +6 -57
- package/src/commands/list.js +5 -6
- package/src/commands/logs.js +142 -15
- package/src/commands/run.js +5 -3
- package/src/commands/sessions.js +4 -5
- package/src/commands/shell.js +5 -3
- package/src/commands/status.js +4 -5
- package/src/commands/update.js +5 -6
- package/src/commands/whoami.js +5 -6
- package/src/lib/config.js +47 -0
package/CLAUDE.md
CHANGED
|
@@ -146,16 +146,28 @@ Uses Commander.js to define:
|
|
|
146
146
|
5. All subsequent API requests include X-Session-Token header
|
|
147
147
|
6. Token expires after 1 year → user must login again
|
|
148
148
|
|
|
149
|
-
**
|
|
150
|
-
1. User
|
|
151
|
-
2.
|
|
152
|
-
3.
|
|
149
|
+
**Auto-Login Flow (CI/CD & Automation):**
|
|
150
|
+
1. User sets `SAAC_USER_API_KEY` and `SAAC_USER_EMAIL` environment variables
|
|
151
|
+
2. Any command checks `ensureAuthenticated()` instead of `isAuthenticated()`
|
|
152
|
+
3. If not logged in, `ensureAuthenticated()` checks for env vars
|
|
153
|
+
4. If both present, automatically calls login API
|
|
154
|
+
5. Session token saved to config, cached for subsequent commands
|
|
155
|
+
6. Subsequent commands use cached session (fast path, no API call)
|
|
153
156
|
|
|
154
157
|
**Authentication Priority:**
|
|
155
158
|
```javascript
|
|
156
|
-
// In
|
|
159
|
+
// In commands (e.g., deploy.js, list.js, etc.)
|
|
160
|
+
if (!(await ensureAuthenticated())) {
|
|
161
|
+
// Not logged in and auto-login failed
|
|
162
|
+
logger.error('Not logged in');
|
|
163
|
+
logger.info('Run: saac login -e <email> -k <api-key>');
|
|
164
|
+
logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// In api.js createClient() - Header priority:
|
|
157
169
|
if (process.env.SAAC_API_KEY) {
|
|
158
|
-
headers['X-API-Key'] = SAAC_API_KEY; // 1st priority
|
|
170
|
+
headers['X-API-Key'] = SAAC_API_KEY; // 1st priority (legacy)
|
|
159
171
|
} else if (user.sessionToken) {
|
|
160
172
|
headers['X-Session-Token'] = sessionToken; // 2nd priority
|
|
161
173
|
} else if (user.apiKey) {
|
|
@@ -163,6 +175,11 @@ if (process.env.SAAC_API_KEY) {
|
|
|
163
175
|
}
|
|
164
176
|
```
|
|
165
177
|
|
|
178
|
+
**Environment Variables:**
|
|
179
|
+
- `SAAC_USER_API_KEY` - API key for auto-login (NEW)
|
|
180
|
+
- `SAAC_USER_EMAIL` - Email for auto-login (NEW)
|
|
181
|
+
- `SAAC_API_KEY` - Legacy API key (used directly in API headers, bypasses login)
|
|
182
|
+
|
|
166
183
|
### Application Lifecycle
|
|
167
184
|
|
|
168
185
|
1. **Create/Init** → applicationUuid saved to `.saac/config.json`
|
|
@@ -205,10 +222,53 @@ The CLI now uses session tokens instead of storing permanent API keys:
|
|
|
205
222
|
```
|
|
206
223
|
|
|
207
224
|
**Token Validation Functions** (in `config.js`):
|
|
208
|
-
- `isAuthenticated()` - Checks if user has valid, non-expired token
|
|
225
|
+
- `isAuthenticated()` - Checks if user has valid, non-expired token (synchronous)
|
|
226
|
+
- `ensureAuthenticated()` - **NEW**: Checks authentication + auto-login via env vars (async)
|
|
209
227
|
- `isTokenExpired()` - Checks if session token has expired
|
|
210
228
|
- `isTokenExpiringSoon()` - Checks if token expires within 7 days
|
|
211
229
|
|
|
230
|
+
**ensureAuthenticated() Function:**
|
|
231
|
+
```javascript
|
|
232
|
+
async function ensureAuthenticated() {
|
|
233
|
+
// Step 1: Check if already authenticated (fast path)
|
|
234
|
+
if (isAuthenticated()) {
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Step 2: Check for environment variables
|
|
239
|
+
const apiKey = process.env.SAAC_USER_API_KEY;
|
|
240
|
+
const email = process.env.SAAC_USER_EMAIL;
|
|
241
|
+
|
|
242
|
+
if (!apiKey || !email) {
|
|
243
|
+
return false; // No env vars - cannot auto-login
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Step 3: Attempt auto-login via API
|
|
247
|
+
try {
|
|
248
|
+
const api = require('./api');
|
|
249
|
+
const result = await api.login(email, apiKey);
|
|
250
|
+
|
|
251
|
+
// Step 4: Save session token to config
|
|
252
|
+
saveUser({
|
|
253
|
+
email: result.user.email,
|
|
254
|
+
userId: result.user.id,
|
|
255
|
+
sessionToken: result.session_token,
|
|
256
|
+
expiresAt: result.expires_at,
|
|
257
|
+
verified: result.user.verified,
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
return true; // Auto-login successful
|
|
261
|
+
} catch (error) {
|
|
262
|
+
return false; // Auto-login failed
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**When to use:**
|
|
268
|
+
- Use `ensureAuthenticated()` in ALL non-auth commands (deploy, list, create, etc.)
|
|
269
|
+
- Use `isAuthenticated()` only when you don't want auto-login behavior
|
|
270
|
+
- Commands that should NOT use `ensureAuthenticated()`: login, logout, register, verify
|
|
271
|
+
|
|
212
272
|
**Backend Requirements:**
|
|
213
273
|
- `POST /auth/login` - Accepts `X-API-Key` + email, returns session token
|
|
214
274
|
- Middleware must accept both `X-Session-Token` and `X-API-Key` headers
|
package/README.md
CHANGED
|
@@ -272,6 +272,259 @@ saac whoami
|
|
|
272
272
|
|
|
273
273
|
---
|
|
274
274
|
|
|
275
|
+
## Environment Variables for CI/CD
|
|
276
|
+
|
|
277
|
+
The SAAC CLI supports **automatic authentication** via environment variables, perfect for CI/CD pipelines, Docker containers, and automation scripts.
|
|
278
|
+
|
|
279
|
+
### How It Works
|
|
280
|
+
|
|
281
|
+
When you run any SAAC command:
|
|
282
|
+
1. CLI checks if you're already logged in (session token exists)
|
|
283
|
+
2. If not logged in, checks for `SAAC_USER_API_KEY` and `SAAC_USER_EMAIL` environment variables
|
|
284
|
+
3. If both are present, **automatically logs in** via API
|
|
285
|
+
4. Session token is cached for subsequent commands (same performance as manual login)
|
|
286
|
+
|
|
287
|
+
### Required Environment Variables
|
|
288
|
+
|
|
289
|
+
- `SAAC_USER_API_KEY` - Your API key (format: `cw_...`)
|
|
290
|
+
- `SAAC_USER_EMAIL` - Your email address
|
|
291
|
+
|
|
292
|
+
**Both variables must be set** for auto-login to work.
|
|
293
|
+
|
|
294
|
+
### Usage Examples
|
|
295
|
+
|
|
296
|
+
#### GitHub Actions
|
|
297
|
+
|
|
298
|
+
```yaml
|
|
299
|
+
name: Deploy to SAAC
|
|
300
|
+
on:
|
|
301
|
+
push:
|
|
302
|
+
branches: [main]
|
|
303
|
+
|
|
304
|
+
jobs:
|
|
305
|
+
deploy:
|
|
306
|
+
runs-on: ubuntu-latest
|
|
307
|
+
steps:
|
|
308
|
+
- uses: actions/checkout@v3
|
|
309
|
+
|
|
310
|
+
- name: Install SAAC CLI
|
|
311
|
+
run: npm install -g @startanaicompany/cli
|
|
312
|
+
|
|
313
|
+
- name: Deploy Application
|
|
314
|
+
env:
|
|
315
|
+
SAAC_USER_API_KEY: ${{ secrets.SAAC_API_KEY }}
|
|
316
|
+
SAAC_USER_EMAIL: ${{ secrets.SAAC_EMAIL }}
|
|
317
|
+
run: |
|
|
318
|
+
saac deploy
|
|
319
|
+
saac logs --deployment
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
**Setup:**
|
|
323
|
+
1. Go to your repo → Settings → Secrets → Actions
|
|
324
|
+
2. Add `SAAC_API_KEY` with your API key
|
|
325
|
+
3. Add `SAAC_EMAIL` with your email address
|
|
326
|
+
|
|
327
|
+
#### GitLab CI/CD
|
|
328
|
+
|
|
329
|
+
```yaml
|
|
330
|
+
deploy:
|
|
331
|
+
stage: deploy
|
|
332
|
+
image: node:18
|
|
333
|
+
variables:
|
|
334
|
+
SAAC_USER_API_KEY: $CI_SAAC_API_KEY
|
|
335
|
+
SAAC_USER_EMAIL: $CI_SAAC_EMAIL
|
|
336
|
+
script:
|
|
337
|
+
- npm install -g @startanaicompany/cli
|
|
338
|
+
- saac deploy
|
|
339
|
+
- saac logs --deployment
|
|
340
|
+
only:
|
|
341
|
+
- main
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
**Setup:**
|
|
345
|
+
1. Go to your project → Settings → CI/CD → Variables
|
|
346
|
+
2. Add `CI_SAAC_API_KEY` (protected, masked)
|
|
347
|
+
3. Add `CI_SAAC_EMAIL`
|
|
348
|
+
|
|
349
|
+
#### Docker
|
|
350
|
+
|
|
351
|
+
```dockerfile
|
|
352
|
+
FROM node:18
|
|
353
|
+
|
|
354
|
+
# Install SAAC CLI
|
|
355
|
+
RUN npm install -g @startanaicompany/cli
|
|
356
|
+
|
|
357
|
+
# Set environment variables (use build args for security)
|
|
358
|
+
ARG SAAC_API_KEY
|
|
359
|
+
ARG SAAC_EMAIL
|
|
360
|
+
ENV SAAC_USER_API_KEY=$SAAC_API_KEY
|
|
361
|
+
ENV SAAC_USER_EMAIL=$SAAC_EMAIL
|
|
362
|
+
|
|
363
|
+
# Your application code
|
|
364
|
+
WORKDIR /app
|
|
365
|
+
COPY . .
|
|
366
|
+
|
|
367
|
+
# Deploy on container startup
|
|
368
|
+
CMD ["sh", "-c", "saac deploy && npm start"]
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
**Build with secrets:**
|
|
372
|
+
```bash
|
|
373
|
+
docker build \
|
|
374
|
+
--build-arg SAAC_API_KEY=cw_your_key \
|
|
375
|
+
--build-arg SAAC_EMAIL=your@email.com \
|
|
376
|
+
-t my-app .
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
#### Local Shell Script
|
|
380
|
+
|
|
381
|
+
```bash
|
|
382
|
+
#!/bin/bash
|
|
383
|
+
set -e
|
|
384
|
+
|
|
385
|
+
# Set environment variables
|
|
386
|
+
export SAAC_USER_API_KEY=cw_your_api_key_here
|
|
387
|
+
export SAAC_USER_EMAIL=your@email.com
|
|
388
|
+
|
|
389
|
+
# Run SAAC commands
|
|
390
|
+
saac deploy
|
|
391
|
+
saac logs --deployment
|
|
392
|
+
saac status
|
|
393
|
+
|
|
394
|
+
echo "Deployment complete!"
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
#### With .env File (Local Development)
|
|
398
|
+
|
|
399
|
+
Create `.env` file (**add to `.gitignore`!**):
|
|
400
|
+
```bash
|
|
401
|
+
SAAC_USER_API_KEY=cw_your_api_key_here
|
|
402
|
+
SAAC_USER_EMAIL=your@email.com
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
Use with a script:
|
|
406
|
+
```bash
|
|
407
|
+
#!/bin/bash
|
|
408
|
+
# Load .env file
|
|
409
|
+
set -a
|
|
410
|
+
source .env
|
|
411
|
+
set +a
|
|
412
|
+
|
|
413
|
+
# Run SAAC commands
|
|
414
|
+
saac list
|
|
415
|
+
saac status
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### Security Best Practices
|
|
419
|
+
|
|
420
|
+
✅ **DO:**
|
|
421
|
+
- Store API keys in secrets management (GitHub Secrets, GitLab Variables, AWS Secrets Manager, etc.)
|
|
422
|
+
- Use environment variables for automation
|
|
423
|
+
- Add `.env` files to `.gitignore`
|
|
424
|
+
- Rotate API keys periodically with `saac keys regenerate`
|
|
425
|
+
- Use different API keys for different environments (dev, staging, prod)
|
|
426
|
+
- Set secrets as "protected" and "masked" in CI/CD systems
|
|
427
|
+
|
|
428
|
+
❌ **DON'T:**
|
|
429
|
+
- Commit API keys to version control
|
|
430
|
+
- Share API keys in plain text (Slack, email, etc.)
|
|
431
|
+
- Hardcode API keys in scripts or Dockerfiles
|
|
432
|
+
- Use the same API key across multiple teams/projects
|
|
433
|
+
- Log API keys in CI/CD output
|
|
434
|
+
|
|
435
|
+
### How It Differs from Manual Login
|
|
436
|
+
|
|
437
|
+
| Feature | Manual Login | Auto-Login (Env Vars) |
|
|
438
|
+
|---------|--------------|----------------------|
|
|
439
|
+
| Session token created | ✅ Yes | ✅ Yes |
|
|
440
|
+
| Session cached locally | ✅ Yes | ✅ Yes |
|
|
441
|
+
| Session expires | ✅ 1 year | ✅ 1 year |
|
|
442
|
+
| Requires user interaction | ❌ No (after first login) | ✅ Fully automated |
|
|
443
|
+
| Perfect for CI/CD | ⚠️ Requires manual setup | ✅ Native support |
|
|
444
|
+
| Performance | ⚡ Fast (cached) | ⚡ Fast (cached after first auto-login) |
|
|
445
|
+
|
|
446
|
+
### Troubleshooting
|
|
447
|
+
|
|
448
|
+
**"Not logged in" despite setting environment variables:**
|
|
449
|
+
- Verify both `SAAC_USER_API_KEY` and `SAAC_USER_EMAIL` are set:
|
|
450
|
+
```bash
|
|
451
|
+
echo $SAAC_USER_API_KEY
|
|
452
|
+
echo $SAAC_USER_EMAIL
|
|
453
|
+
```
|
|
454
|
+
- Ensure API key is valid (not revoked or expired)
|
|
455
|
+
- Check API key format starts with `cw_`
|
|
456
|
+
- Try logging in manually to verify credentials work:
|
|
457
|
+
```bash
|
|
458
|
+
saac login -e $SAAC_USER_EMAIL -k $SAAC_USER_API_KEY
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
**Environment variables not being read:**
|
|
462
|
+
- Make sure variables are exported: `export SAAC_USER_API_KEY=...`
|
|
463
|
+
- Check for typos in variable names (must be exact)
|
|
464
|
+
- In Docker, ensure ENV is set or use build args correctly
|
|
465
|
+
- In CI/CD, verify secrets are configured correctly
|
|
466
|
+
|
|
467
|
+
**Security concerns:**
|
|
468
|
+
- Never print environment variables in logs: `echo $SAAC_USER_API_KEY` ❌
|
|
469
|
+
- Use masked/protected secrets in CI/CD systems
|
|
470
|
+
- Regenerate API key if accidentally exposed: `saac keys regenerate`
|
|
471
|
+
- Monitor active sessions: `saac sessions`
|
|
472
|
+
|
|
473
|
+
### Example: Complete CI/CD Workflow
|
|
474
|
+
|
|
475
|
+
```yaml
|
|
476
|
+
name: Full Deployment Workflow
|
|
477
|
+
on:
|
|
478
|
+
push:
|
|
479
|
+
branches: [main, staging]
|
|
480
|
+
|
|
481
|
+
jobs:
|
|
482
|
+
deploy:
|
|
483
|
+
runs-on: ubuntu-latest
|
|
484
|
+
steps:
|
|
485
|
+
- uses: actions/checkout@v3
|
|
486
|
+
|
|
487
|
+
- name: Setup Node.js
|
|
488
|
+
uses: actions/setup-node@v3
|
|
489
|
+
with:
|
|
490
|
+
node-version: '18'
|
|
491
|
+
|
|
492
|
+
- name: Install Dependencies
|
|
493
|
+
run: npm install
|
|
494
|
+
|
|
495
|
+
- name: Run Tests
|
|
496
|
+
run: npm test
|
|
497
|
+
|
|
498
|
+
- name: Install SAAC CLI
|
|
499
|
+
run: npm install -g @startanaicompany/cli
|
|
500
|
+
|
|
501
|
+
- name: Deploy to SAAC
|
|
502
|
+
env:
|
|
503
|
+
SAAC_USER_API_KEY: ${{ secrets.SAAC_API_KEY }}
|
|
504
|
+
SAAC_USER_EMAIL: ${{ secrets.SAAC_EMAIL }}
|
|
505
|
+
run: |
|
|
506
|
+
# Auto-login happens automatically!
|
|
507
|
+
saac deploy
|
|
508
|
+
|
|
509
|
+
# Wait for deployment to complete (built-in timeout)
|
|
510
|
+
echo "Deployment finished!"
|
|
511
|
+
|
|
512
|
+
- name: Check Application Status
|
|
513
|
+
env:
|
|
514
|
+
SAAC_USER_API_KEY: ${{ secrets.SAAC_API_KEY }}
|
|
515
|
+
SAAC_USER_EMAIL: ${{ secrets.SAAC_EMAIL }}
|
|
516
|
+
run: |
|
|
517
|
+
saac status
|
|
518
|
+
saac logs --deployment | tail -20
|
|
519
|
+
|
|
520
|
+
- name: Notify on Failure
|
|
521
|
+
if: failure()
|
|
522
|
+
run: |
|
|
523
|
+
echo "Deployment failed! Check logs with: saac logs --deployment"
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
---
|
|
527
|
+
|
|
275
528
|
## Git OAuth
|
|
276
529
|
|
|
277
530
|
SAAC CLI uses **OAuth-only authentication** for Git access. You must connect your Git account before creating applications.
|
|
@@ -374,6 +627,141 @@ saac git disconnect git.startanaicompany.com
|
|
|
374
627
|
- Existing applications continue to work
|
|
375
628
|
- New applications will require reconnection
|
|
376
629
|
|
|
630
|
+
### `saac git repos <host>`
|
|
631
|
+
|
|
632
|
+
List repositories from a connected Git host.
|
|
633
|
+
|
|
634
|
+
```bash
|
|
635
|
+
# Basic usage
|
|
636
|
+
saac git repos git.startanaicompany.com
|
|
637
|
+
saac git repos github.com
|
|
638
|
+
|
|
639
|
+
# Include latest commit information
|
|
640
|
+
saac git repos github.com --commits
|
|
641
|
+
|
|
642
|
+
# Filter by visibility
|
|
643
|
+
saac git repos github.com --visibility private
|
|
644
|
+
saac git repos github.com --visibility public
|
|
645
|
+
|
|
646
|
+
# With pagination
|
|
647
|
+
saac git repos github.com --page 2 --per-page 10
|
|
648
|
+
|
|
649
|
+
# Sort repositories
|
|
650
|
+
saac git repos github.com --sort created
|
|
651
|
+
saac git repos github.com --sort name
|
|
652
|
+
|
|
653
|
+
# JSON output for scripting
|
|
654
|
+
saac git repos github.com --json
|
|
655
|
+
|
|
656
|
+
# Combine options
|
|
657
|
+
saac git repos github.com --commits --visibility private --per-page 20
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
**Options:**
|
|
661
|
+
- `-p, --page <number>` - Page number for pagination (default: 1)
|
|
662
|
+
- `-n, --per-page <number>` - Results per page, max 100 (default: 20)
|
|
663
|
+
- `-s, --sort <type>` - Sort order: `updated`, `created`, `name` (default: `updated`)
|
|
664
|
+
- `-v, --visibility <type>` - Filter: `all`, `public`, `private` (default: `all`)
|
|
665
|
+
- `-c, --commits` - Include latest commit info for each repository
|
|
666
|
+
- `--json` - Output as JSON for scripting
|
|
667
|
+
|
|
668
|
+
**Shows:**
|
|
669
|
+
- Repository name
|
|
670
|
+
- Visibility (public/private)
|
|
671
|
+
- Last updated timestamp
|
|
672
|
+
- Default branch
|
|
673
|
+
- Primary language
|
|
674
|
+
- Latest commit (with `--commits` flag)
|
|
675
|
+
|
|
676
|
+
**Example output (without commits):**
|
|
677
|
+
```
|
|
678
|
+
Repositories on git.startanaicompany.com (ryan.gogo)
|
|
679
|
+
────────────────────────────────────────────────────
|
|
680
|
+
|
|
681
|
+
NAME VISIBILITY UPDATED BRANCH LANGUAGE
|
|
682
|
+
mysimpleflowershop private 1/27/2026, 12:52:18 AM master JavaScript
|
|
683
|
+
api-server private 1/26/2026, 8:30:00 PM main TypeScript
|
|
684
|
+
landing-page public 1/25/2026, 3:15:00 PM master HTML
|
|
685
|
+
|
|
686
|
+
Showing 3 repositories (page 1)
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
**Example output (with `--commits`):**
|
|
690
|
+
```
|
|
691
|
+
Repositories on git.startanaicompany.com (ryan.gogo)
|
|
692
|
+
────────────────────────────────────────────────────
|
|
693
|
+
|
|
694
|
+
NAME VISIBILITY LAST COMMIT
|
|
695
|
+
mysimpleflowershop private 4b2c63f Initial commit - Simple Flower (3d ago)
|
|
696
|
+
api-server private a90373d Add user authentication (1d ago)
|
|
697
|
+
landing-page public f1e2d3c Update homepage design (5h ago)
|
|
698
|
+
|
|
699
|
+
Showing 3 repositories (page 1)
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
**JSON output:**
|
|
703
|
+
```bash
|
|
704
|
+
$ saac git repos github.com --json
|
|
705
|
+
|
|
706
|
+
{
|
|
707
|
+
"success": true,
|
|
708
|
+
"git_host": "github.com",
|
|
709
|
+
"username": "johndoe",
|
|
710
|
+
"provider_type": "github",
|
|
711
|
+
"repositories": [
|
|
712
|
+
{
|
|
713
|
+
"name": "my-app",
|
|
714
|
+
"fullName": "johndoe/my-app",
|
|
715
|
+
"description": "A cool application",
|
|
716
|
+
"private": false,
|
|
717
|
+
"sshUrl": "git@github.com:johndoe/my-app.git",
|
|
718
|
+
"cloneUrl": "https://github.com/johndoe/my-app.git",
|
|
719
|
+
"htmlUrl": "https://github.com/johndoe/my-app",
|
|
720
|
+
"defaultBranch": "main",
|
|
721
|
+
"updatedAt": "2026-01-30T12:00:00Z",
|
|
722
|
+
"language": "JavaScript",
|
|
723
|
+
"latestCommit": {
|
|
724
|
+
"sha": "abc1234",
|
|
725
|
+
"message": "Fix authentication bug",
|
|
726
|
+
"author": "John Doe",
|
|
727
|
+
"date": "2026-01-30T11:30:00Z"
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
],
|
|
731
|
+
"count": 1,
|
|
732
|
+
"page": 1,
|
|
733
|
+
"per_page": 100
|
|
734
|
+
}
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
**Use Cases:**
|
|
738
|
+
- Browse available repositories before creating an application
|
|
739
|
+
- Find repository SSH URLs for `saac create` command
|
|
740
|
+
- Check latest commits without visiting Git provider
|
|
741
|
+
- Script repository discovery and automation
|
|
742
|
+
- Filter personal vs organization repositories
|
|
743
|
+
|
|
744
|
+
**Performance Notes:**
|
|
745
|
+
- Without `--commits`: Fast (single API call)
|
|
746
|
+
- With `--commits`: Slower (fetches commit info for each repo in parallel)
|
|
747
|
+
- Use `--commits` only when you need commit information
|
|
748
|
+
|
|
749
|
+
**Example Workflow:**
|
|
750
|
+
```bash
|
|
751
|
+
# 1. Connect to Git host
|
|
752
|
+
saac git connect github.com
|
|
753
|
+
|
|
754
|
+
# 2. List your repositories
|
|
755
|
+
saac git repos github.com
|
|
756
|
+
|
|
757
|
+
# 3. Find the repository you want to deploy
|
|
758
|
+
saac git repos github.com --visibility private
|
|
759
|
+
|
|
760
|
+
# 4. Copy the SSH URL from the output
|
|
761
|
+
# 5. Create application with that repository
|
|
762
|
+
saac create my-app -s myapp -r git@github.com:username/my-app.git
|
|
763
|
+
```
|
|
764
|
+
|
|
377
765
|
---
|
|
378
766
|
|
|
379
767
|
## Application Management
|
|
@@ -392,31 +780,78 @@ saac init
|
|
|
392
780
|
- Have an existing project
|
|
393
781
|
- Want to manage an application from a different directory
|
|
394
782
|
|
|
395
|
-
**
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
3. Saves selected application info to `.saac/config.json`
|
|
399
|
-
4. Now you can use `saac deploy`, `saac logs`, etc.
|
|
783
|
+
**Smart Auto-Detection (NEW!):**
|
|
784
|
+
|
|
785
|
+
If you're in a Git repository, `saac init` automatically detects the remote URL and matches it to your applications:
|
|
400
786
|
|
|
401
|
-
**Example:**
|
|
402
787
|
```bash
|
|
788
|
+
$ cd mysimpleflowershop
|
|
403
789
|
$ saac init
|
|
404
790
|
|
|
405
|
-
|
|
406
|
-
|
|
791
|
+
Initialize SAAC Project
|
|
792
|
+
───────────────────────
|
|
407
793
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
794
|
+
✓ Found 3 application(s)
|
|
795
|
+
|
|
796
|
+
ℹ Auto-detected Git repository: git@git.startanaicompany.com:ryan.gogo/mysimpleflowershop.git
|
|
797
|
+
|
|
798
|
+
Matched Application: mysimpleflowershop
|
|
799
|
+
Domain: mysimpleflowershop.startanaicompany.com
|
|
800
|
+
Status: running:healthy
|
|
801
|
+
|
|
802
|
+
? Link this application to the current directory? (Y/n) Yes
|
|
803
|
+
|
|
804
|
+
✓ Project initialized!
|
|
805
|
+
|
|
806
|
+
Application: mysimpleflowershop
|
|
807
|
+
UUID: abc123-def456...
|
|
808
|
+
Domain: mysimpleflowershop.startanaicompany.com
|
|
809
|
+
Status: running:healthy
|
|
810
|
+
|
|
811
|
+
You can now use:
|
|
812
|
+
saac deploy Deploy your application
|
|
813
|
+
saac logs --follow View deployment logs
|
|
814
|
+
saac status Check application status
|
|
815
|
+
saac update --port 8080 Update configuration
|
|
816
|
+
```
|
|
412
817
|
|
|
413
|
-
|
|
818
|
+
**How Auto-Detection Works:**
|
|
819
|
+
1. Reads Git remote URL from `.git/config`
|
|
820
|
+
2. Normalizes both Git remote and application repositories
|
|
821
|
+
3. Matches against your applications automatically
|
|
822
|
+
4. Asks for confirmation (defaults to Yes)
|
|
823
|
+
5. Falls back to manual selection if no match found or if you decline
|
|
414
824
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
825
|
+
**Supports:**
|
|
826
|
+
- SSH URLs: `git@github.com:user/repo.git`
|
|
827
|
+
- HTTPS URLs: `https://github.com/user/repo.git`
|
|
828
|
+
- With or without `.git` suffix
|
|
829
|
+
- Case-insensitive matching
|
|
830
|
+
|
|
831
|
+
**Manual Selection (fallback):**
|
|
832
|
+
|
|
833
|
+
If not in a Git repository or no match found, shows interactive list:
|
|
834
|
+
|
|
835
|
+
```bash
|
|
836
|
+
$ saac init
|
|
837
|
+
|
|
838
|
+
? Select application to link to this directory:
|
|
839
|
+
❯ mysimpleflowershop - mysimpleflowershop.startanaicompany.com (running:healthy)
|
|
840
|
+
api-server - api.startanaicompany.com (running:healthy)
|
|
841
|
+
landing-page - landing.startanaicompany.com (stopped)
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
**What it saves:**
|
|
845
|
+
|
|
846
|
+
Creates `.saac/config.json` in current directory:
|
|
847
|
+
```json
|
|
848
|
+
{
|
|
849
|
+
"applicationUuid": "abc123-def456...",
|
|
850
|
+
"applicationName": "mysimpleflowershop",
|
|
851
|
+
"subdomain": "mysimpleflowershop",
|
|
852
|
+
"domainSuffix": "startanaicompany.com",
|
|
853
|
+
"gitRepository": "git@git.startanaicompany.com:ryan.gogo/mysimpleflowershop.git"
|
|
854
|
+
}
|
|
420
855
|
```
|
|
421
856
|
|
|
422
857
|
### `saac create <name>`
|
package/bin/saac.js
CHANGED
|
@@ -96,12 +96,6 @@ keysCommand
|
|
|
96
96
|
.description('Generate a new API key (invalidates old one)')
|
|
97
97
|
.action(keys.regenerate);
|
|
98
98
|
|
|
99
|
-
keysCommand
|
|
100
|
-
.command('show')
|
|
101
|
-
.alias('info')
|
|
102
|
-
.description('Show API key information')
|
|
103
|
-
.action(keys.show);
|
|
104
|
-
|
|
105
99
|
// Git OAuth commands
|
|
106
100
|
const gitCommand = program
|
|
107
101
|
.command('git')
|
|
@@ -150,6 +144,7 @@ program
|
|
|
150
144
|
// Required options
|
|
151
145
|
.option('-s, --subdomain <subdomain>', 'Subdomain')
|
|
152
146
|
.option('-r, --repository <url>', 'Git repository URL (SSH format)')
|
|
147
|
+
.option('--org <organization_id>', 'Organization ID (required)')
|
|
153
148
|
// Basic options
|
|
154
149
|
.option('-b, --branch <branch>', 'Git branch', 'master')
|
|
155
150
|
.option('-d, --domain-suffix <suffix>', 'Domain suffix', 'startanaicompany.com')
|
|
@@ -231,6 +226,7 @@ program
|
|
|
231
226
|
.option('-t, --tail <lines>', 'Number of lines to show (runtime logs only)', '100')
|
|
232
227
|
.option('-f, --follow', 'Follow log output (runtime logs only)')
|
|
233
228
|
.option('--since <time>', 'Show logs since timestamp (runtime logs only)')
|
|
229
|
+
.option('--type <type>', 'Filter by log type: build, runtime, access (runtime logs only)')
|
|
234
230
|
.action(logs);
|
|
235
231
|
|
|
236
232
|
// Local development commands
|