@startanaicompany/cli 1.4.17 → 1.4.19
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.md +428 -29
- package/bin/saac.js +56 -4
- package/package.json +3 -2
- package/src/commands/delete.js +191 -4
- package/src/commands/deployments.js +130 -0
- package/src/commands/domain.js +204 -3
- package/src/commands/env.js +264 -3
- package/src/commands/exec.js +277 -0
- package/src/commands/logs.js +232 -4
- package/src/commands/run.js +170 -0
- package/src/commands/shell.js +403 -0
- package/src/commands/whoami.js +90 -4
- package/src/lib/api.js +54 -0
package/CLAUDE.md
CHANGED
|
@@ -651,16 +651,405 @@ Uses the same status display logic as the status command (see "Application Statu
|
|
|
651
651
|
- Domains fallback to `{subdomain}.startanaicompany.com` if not set
|
|
652
652
|
- Branch defaults to 'master' if not specified
|
|
653
653
|
|
|
654
|
-
###
|
|
654
|
+
### Deployments Command Implementation
|
|
655
655
|
|
|
656
|
-
|
|
657
|
-
- `src/commands/env.js` - Not implemented (stub only)
|
|
658
|
-
- `src/commands/domain.js` - Not implemented (stub only)
|
|
659
|
-
- `src/commands/logs.js` - Not implemented (stub only)
|
|
660
|
-
- `src/commands/delete.js` - Not implemented (stub only)
|
|
661
|
-
- `src/commands/whoami.js` - Not implemented (stub only)
|
|
656
|
+
The `deployments` command displays deployment history for the current application in a formatted table.
|
|
662
657
|
|
|
663
|
-
**
|
|
658
|
+
**Usage:**
|
|
659
|
+
```bash
|
|
660
|
+
saac deployments
|
|
661
|
+
saac deploys # Alias
|
|
662
|
+
|
|
663
|
+
# With pagination
|
|
664
|
+
saac deployments --limit 10
|
|
665
|
+
saac deployments --limit 20 --offset 20
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
**How It Works:**
|
|
669
|
+
1. Validates authentication (session token not expired)
|
|
670
|
+
2. Checks for project config (`.saac/config.json`)
|
|
671
|
+
3. Fetches deployment history from `/api/v1/applications/:uuid/deployments`
|
|
672
|
+
4. Displays table with columns: UUID, Status, Branch, Commit, Duration, Trigger, Date
|
|
673
|
+
5. Shows pagination info if more deployments available
|
|
674
|
+
|
|
675
|
+
**Options:**
|
|
676
|
+
- `-l, --limit <number>` - Number of deployments to show (default: 20)
|
|
677
|
+
- `-o, --offset <number>` - Offset for pagination (default: 0)
|
|
678
|
+
|
|
679
|
+
**Status Display:**
|
|
680
|
+
- ✅ `finished` - Displayed in green
|
|
681
|
+
- ✗ `failed` - Displayed in red
|
|
682
|
+
- ⏳ `running`, `queued` - Displayed in yellow
|
|
683
|
+
- `unknown` - Displayed in gray
|
|
684
|
+
|
|
685
|
+
**Table Formatting:**
|
|
686
|
+
- UUID truncated to 26 characters for readability
|
|
687
|
+
- Commit SHA truncated to 7 characters
|
|
688
|
+
- Duration shown in seconds
|
|
689
|
+
- Date formatted with `toLocaleString()`
|
|
690
|
+
|
|
691
|
+
**Response Fields:**
|
|
692
|
+
```json
|
|
693
|
+
{
|
|
694
|
+
"deployments": [
|
|
695
|
+
{
|
|
696
|
+
"deployment_uuid": "...",
|
|
697
|
+
"status": "finished",
|
|
698
|
+
"git_branch": "master",
|
|
699
|
+
"git_commit": "abc1234",
|
|
700
|
+
"duration_seconds": 45,
|
|
701
|
+
"triggered_by": "api",
|
|
702
|
+
"started_at": "2024-01-20T12:00:00Z"
|
|
703
|
+
}
|
|
704
|
+
],
|
|
705
|
+
"total": 100
|
|
706
|
+
}
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
**Next Steps:**
|
|
710
|
+
After viewing deployment history, use:
|
|
711
|
+
- `saac logs --deployment` - View latest deployment logs
|
|
712
|
+
- `saac logs --deployment <uuid>` - View specific deployment logs
|
|
713
|
+
|
|
714
|
+
### Logs Command Implementation
|
|
715
|
+
|
|
716
|
+
The `logs` command displays application logs with support for both deployment logs (build logs) and runtime logs (container logs).
|
|
717
|
+
|
|
718
|
+
**Usage:**
|
|
719
|
+
```bash
|
|
720
|
+
# View latest deployment logs (build logs)
|
|
721
|
+
saac logs --deployment
|
|
722
|
+
saac logs -d
|
|
723
|
+
|
|
724
|
+
# View specific deployment logs
|
|
725
|
+
saac logs --deployment abc123-def456-...
|
|
726
|
+
saac logs abc123-def456-... --deployment
|
|
727
|
+
|
|
728
|
+
# View deployment logs in raw format
|
|
729
|
+
saac logs --deployment --raw
|
|
730
|
+
|
|
731
|
+
# View runtime logs (container logs)
|
|
732
|
+
saac logs
|
|
733
|
+
saac logs --tail 200
|
|
734
|
+
saac logs --follow
|
|
735
|
+
saac logs --since 1h
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
**Two Modes:**
|
|
739
|
+
|
|
740
|
+
**1. Deployment Logs Mode (Build Logs)**
|
|
741
|
+
- Enabled with `--deployment` flag
|
|
742
|
+
- Shows logs from the build/deployment process
|
|
743
|
+
- Includes build output, errors, and deployment status
|
|
744
|
+
- Supports both parsed (colorized) and raw formats
|
|
745
|
+
|
|
746
|
+
**Options:**
|
|
747
|
+
- `--deployment [uuid]` - View deployment logs (omit UUID for latest)
|
|
748
|
+
- `--raw` - Show raw log output (no parsing or colorization)
|
|
749
|
+
- `--include-hidden` - Include hidden log lines
|
|
750
|
+
|
|
751
|
+
**Display:**
|
|
752
|
+
- Header with deployment UUID, status, commit, duration
|
|
753
|
+
- Parsed logs with stderr highlighted in red
|
|
754
|
+
- Error summary if deployment failed
|
|
755
|
+
- Structured error information with types and details
|
|
756
|
+
|
|
757
|
+
**2. Runtime Logs Mode (Container Logs)**
|
|
758
|
+
- Default mode when no `--deployment` flag
|
|
759
|
+
- Shows logs from the running container
|
|
760
|
+
- Real-time application output
|
|
761
|
+
|
|
762
|
+
**Options:**
|
|
763
|
+
- `-t, --tail <lines>` - Number of lines to show (default: 100)
|
|
764
|
+
- `-f, --follow` - Follow log output (not yet implemented)
|
|
765
|
+
- `--since <time>` - Show logs since timestamp
|
|
766
|
+
|
|
767
|
+
**Error Handling:**
|
|
768
|
+
- 404 error → No deployments found, suggests `saac deploy`
|
|
769
|
+
- 501 error → Runtime logs not implemented, suggests deployment logs
|
|
770
|
+
|
|
771
|
+
**Response Fields (Deployment Logs):**
|
|
772
|
+
```json
|
|
773
|
+
{
|
|
774
|
+
"deployment_uuid": "...",
|
|
775
|
+
"status": "finished",
|
|
776
|
+
"commit": "abc1234",
|
|
777
|
+
"commit_message": "Fix bug",
|
|
778
|
+
"started_at": "2024-01-20T12:00:00Z",
|
|
779
|
+
"finished_at": "2024-01-20T12:02:00Z",
|
|
780
|
+
"duration_seconds": 120,
|
|
781
|
+
"log_count": 150,
|
|
782
|
+
"logs": [
|
|
783
|
+
{
|
|
784
|
+
"type": "stdout",
|
|
785
|
+
"output": "Installing dependencies..."
|
|
786
|
+
},
|
|
787
|
+
{
|
|
788
|
+
"type": "stderr",
|
|
789
|
+
"output": "npm WARN deprecated package@1.0.0"
|
|
790
|
+
}
|
|
791
|
+
],
|
|
792
|
+
"raw_logs": "...",
|
|
793
|
+
"errors": [
|
|
794
|
+
{
|
|
795
|
+
"type": "BUILD_FAILED",
|
|
796
|
+
"message": "Build failed with exit code 1",
|
|
797
|
+
"detail": "npm ERR! code ELIFECYCLE"
|
|
798
|
+
}
|
|
799
|
+
]
|
|
800
|
+
}
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
### Local Development Commands (NEW in 1.5.0)
|
|
804
|
+
|
|
805
|
+
#### Run Command Implementation
|
|
806
|
+
|
|
807
|
+
The `run` command allows executing local commands with remote environment variables from the deployed application.
|
|
808
|
+
|
|
809
|
+
**Usage:**
|
|
810
|
+
```bash
|
|
811
|
+
saac run <command> # Run command with remote env vars
|
|
812
|
+
saac run npm start # Start app with production env
|
|
813
|
+
saac run --sync npm run build # Force refresh env vars (skip cache)
|
|
814
|
+
saac run -q npm test # Quiet mode (suppress warnings)
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
**Implementation Details:**
|
|
818
|
+
- Fetches env vars from `GET /applications/:uuid/env/export`
|
|
819
|
+
- Uses 5-minute in-memory cache (TTL: 300 seconds)
|
|
820
|
+
- Creates temp file at `/tmp/saac-env-{uuid}.sh` with 0600 permissions
|
|
821
|
+
- Sources env file and executes command in subshell
|
|
822
|
+
- Automatic cleanup on exit (SIGINT/SIGTERM handlers)
|
|
823
|
+
- Rate limit handling (10 requests/minute per user)
|
|
824
|
+
|
|
825
|
+
**Security Features:**
|
|
826
|
+
- Temp files with 0600 permissions (owner read-write only)
|
|
827
|
+
- Automatic cleanup on process exit
|
|
828
|
+
- Warning message about exposed secrets
|
|
829
|
+
- Cache reduces API calls (rate limit protection)
|
|
830
|
+
|
|
831
|
+
**Error Handling:**
|
|
832
|
+
- 429 Rate Limit: Shows retry time, mentions caching
|
|
833
|
+
- 403 Forbidden: User doesn't own application
|
|
834
|
+
- 404 Not Found: Application doesn't exist
|
|
835
|
+
- Network failures: Graceful error messages
|
|
836
|
+
|
|
837
|
+
**Location:** `src/commands/run.js`
|
|
838
|
+
|
|
839
|
+
---
|
|
840
|
+
|
|
841
|
+
#### Shell Command Implementation (Project Aurora)
|
|
842
|
+
|
|
843
|
+
The `shell` command provides a **TRUE remote shell** - you're actually inside the Docker container, not just a local shell with env vars loaded. This is powered by Project Aurora (WebSocket + Docker + tmux).
|
|
844
|
+
|
|
845
|
+
**Key Difference from Phase 1:**
|
|
846
|
+
- **OLD (Phase 1)**: Local shell with remote env vars → wrong filesystem, wrong tools, wrong paths
|
|
847
|
+
- **NEW (Aurora)**: Remote shell inside container → TRUE remote experience like SSH/Railway
|
|
848
|
+
|
|
849
|
+
**Usage:**
|
|
850
|
+
```bash
|
|
851
|
+
saac shell # Connect to remote container shell
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
**Architecture:**
|
|
855
|
+
- WebSocket client connects to backend server
|
|
856
|
+
- Backend creates Docker container with tmux session
|
|
857
|
+
- Commands sent via WebSocket, executed in container
|
|
858
|
+
- Terminal output captured from tmux and streamed back
|
|
859
|
+
- Session persists even after disconnect (up to 1 hour idle)
|
|
860
|
+
|
|
861
|
+
**Implementation Details:**
|
|
862
|
+
- Uses `ws` package for WebSocket client
|
|
863
|
+
- Connects to: `wss://apps.startanaicompany.com/api/v1/shell/connect`
|
|
864
|
+
- Authentication via session token or API key
|
|
865
|
+
- Readline interface for local terminal interaction
|
|
866
|
+
- Automatic reconnection on disconnect (up to 3 attempts)
|
|
867
|
+
- Heartbeat ping/pong every 30 seconds
|
|
868
|
+
|
|
869
|
+
**Session Lifecycle:**
|
|
870
|
+
1. CLI connects via WebSocket with auth token
|
|
871
|
+
2. Backend creates session record in database (status: 'creating')
|
|
872
|
+
3. Python daemon creates Docker container with tmux
|
|
873
|
+
4. Container ready, status updates to 'active'
|
|
874
|
+
5. User interacts with remote shell
|
|
875
|
+
6. On disconnect, session marked 'idle' (persists for 1 hour)
|
|
876
|
+
7. Idle timeout or manual termination cleans up container
|
|
877
|
+
|
|
878
|
+
**Features:**
|
|
879
|
+
- ✅ TRUE remote shell (inside container, not local)
|
|
880
|
+
- ✅ Persistent session (survives reconnections)
|
|
881
|
+
- ✅ Interactive commands (vim, nano, etc work!)
|
|
882
|
+
- ✅ Working directory persists between commands
|
|
883
|
+
- ✅ Command history (up arrow works)
|
|
884
|
+
- ✅ Real-time output streaming
|
|
885
|
+
- ✅ Ctrl+C sends to remote shell
|
|
886
|
+
|
|
887
|
+
**Connection Handling:**
|
|
888
|
+
- 30-second timeout for initial container creation
|
|
889
|
+
- Auto-reconnect on network issues (3 attempts, exponential backoff)
|
|
890
|
+
- Graceful cleanup on exit (Ctrl+D or "exit" command)
|
|
891
|
+
|
|
892
|
+
**User Experience:**
|
|
893
|
+
```bash
|
|
894
|
+
$ saac shell
|
|
895
|
+
|
|
896
|
+
Remote Shell: my-app
|
|
897
|
+
|
|
898
|
+
Connecting to container...
|
|
899
|
+
This may take up to 30 seconds for container creation.
|
|
900
|
+
|
|
901
|
+
✓ Connected to remote container
|
|
902
|
+
Container is being created, please wait...
|
|
903
|
+
✓ Container is ready!
|
|
904
|
+
Type commands below. Press Ctrl+D or type "exit" to quit.
|
|
905
|
+
|
|
906
|
+
root@container:/app# ls -la
|
|
907
|
+
total 48
|
|
908
|
+
drwxr-xr-x 6 root root 4096 Jan 28 20:00 .
|
|
909
|
+
drwxr-xr-x 18 root root 4096 Jan 28 20:00 ..
|
|
910
|
+
-rw-r--r-- 1 root root 220 Jan 28 20:00 package.json
|
|
911
|
+
drwxr-xr-x 2 root root 4096 Jan 28 20:00 src
|
|
912
|
+
|
|
913
|
+
root@container:/app# cd src && pwd
|
|
914
|
+
/app/src
|
|
915
|
+
|
|
916
|
+
root@container:/app/src# exit
|
|
917
|
+
|
|
918
|
+
Disconnecting from remote shell...
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
**Error Handling:**
|
|
922
|
+
- `Authentication failed` → Token expired, run `saac login`
|
|
923
|
+
- `Access denied` → User doesn't own the application
|
|
924
|
+
- `Connection timeout` → Server unavailable or container failed to start
|
|
925
|
+
- `Max reconnection attempts` → Network issue, try again later
|
|
926
|
+
|
|
927
|
+
**Backend Requirements:**
|
|
928
|
+
- WebSocket server at `/api/v1/shell/connect` endpoint
|
|
929
|
+
- PostgreSQL tables: `shell_sessions`, `shell_commands`, `shell_output`
|
|
930
|
+
- Python daemon managing Docker containers with tmux
|
|
931
|
+
- Session cleanup after 1 hour idle or 4 hours total
|
|
932
|
+
|
|
933
|
+
**Location:** `src/commands/shell.js` (403 lines, complete rewrite for Aurora)
|
|
934
|
+
|
|
935
|
+
**Note:** Backend infrastructure (WebSocket server + Python daemon) must be deployed before this command works. CLI is ready, waiting for backend Phase 3.5 deployment.
|
|
936
|
+
|
|
937
|
+
**Location:** `src/commands/shell.js`
|
|
938
|
+
|
|
939
|
+
---
|
|
940
|
+
|
|
941
|
+
### Remote Execution Commands (NEW in 1.6.0)
|
|
942
|
+
|
|
943
|
+
#### Exec Command Implementation
|
|
944
|
+
|
|
945
|
+
The `exec` command allows executing commands directly in the deployed application's container.
|
|
946
|
+
|
|
947
|
+
**Usage:**
|
|
948
|
+
```bash
|
|
949
|
+
saac exec "npm run db:migrate" # Run database migrations
|
|
950
|
+
saac exec "npm run build" --timeout 120 # With custom timeout
|
|
951
|
+
saac exec "python manage.py collectstatic" --workdir /app/backend
|
|
952
|
+
saac exec --history # View execution history
|
|
953
|
+
saac exec --history --limit 50 # Show more history
|
|
954
|
+
```
|
|
955
|
+
|
|
956
|
+
**Implementation Details:**
|
|
957
|
+
- Sends command to `POST /applications/:uuid/exec`
|
|
958
|
+
- Backend validates command against allowlist
|
|
959
|
+
- Python daemon executes via Docker API (no shell interpretation!)
|
|
960
|
+
- Returns: execution_id, exit_code, stdout, stderr, duration
|
|
961
|
+
- Command runs in container as detected user (not root)
|
|
962
|
+
|
|
963
|
+
**Architecture:**
|
|
964
|
+
```
|
|
965
|
+
CLI → Backend API → Database (exec_requests table) → Python Daemon → Docker Container
|
|
966
|
+
```
|
|
967
|
+
|
|
968
|
+
**Security Features:**
|
|
969
|
+
- ✅ **3-layer validation:** Backend allowlist + daemon validation + Docker array execution
|
|
970
|
+
- ✅ **Command allowlist:** npm, node, python, bash, etc. (dangerous commands blocked)
|
|
971
|
+
- ✅ **Dangerous pattern detection:** Blocks `rm -rf`, `| sh`, `$(...)`, etc.
|
|
972
|
+
- ✅ **Rate limiting:** 30 requests per 5 minutes per user
|
|
973
|
+
- ✅ **No shell interpretation:** Commands executed as arrays, not strings
|
|
974
|
+
- ✅ **Non-root execution:** Commands run as app user, never privileged
|
|
975
|
+
- ✅ **Audit logging:** All executions logged with user, command, exit code
|
|
976
|
+
|
|
977
|
+
**Allowed Commands:**
|
|
978
|
+
- Node.js: `npm`, `node`, `npx`, `yarn`, `pnpm`
|
|
979
|
+
- Python: `python`, `python3`, `pip`, `poetry`
|
|
980
|
+
- Ruby: `bundle`, `rake`, `rails`
|
|
981
|
+
- Build tools: `make`, `cmake`, `go`, `cargo`
|
|
982
|
+
- Shell: `sh`, `bash`, `echo`, `cat`, `ls`, `pwd`, `env`
|
|
983
|
+
- Database: `psql`, `mysql`, `mongosh`
|
|
984
|
+
|
|
985
|
+
**Error Handling:**
|
|
986
|
+
- 400 Validation Error: Command not in allowlist or dangerous pattern detected
|
|
987
|
+
- 408 Timeout: Command exceeded timeout limit (default: 30s, max: 300s)
|
|
988
|
+
- 429 Rate Limit: Too many exec requests (30 per 5 minutes)
|
|
989
|
+
- 503 Container Not Running: Application container is not active
|
|
990
|
+
- 500 Execution Failed: Container error or daemon issue
|
|
991
|
+
|
|
992
|
+
**Example Output:**
|
|
993
|
+
```bash
|
|
994
|
+
$ saac exec "echo 'Hello from container!'"
|
|
995
|
+
|
|
996
|
+
Executing Command: myapp
|
|
997
|
+
──────────────────────────
|
|
998
|
+
|
|
999
|
+
Command: echo 'Hello from container!'
|
|
1000
|
+
Working Directory: /app
|
|
1001
|
+
Timeout: 30s
|
|
1002
|
+
|
|
1003
|
+
✓ Command executed
|
|
1004
|
+
|
|
1005
|
+
✓ Execution ID: eb41b197-e215-4f9e-87ac-80ce57e732a6
|
|
1006
|
+
|
|
1007
|
+
Exit Code: 0
|
|
1008
|
+
Duration: 3531ms
|
|
1009
|
+
Started: 1/28/2026, 8:55:37 PM
|
|
1010
|
+
Completed: 1/28/2026, 8:55:41 PM
|
|
1011
|
+
|
|
1012
|
+
Standard Output:
|
|
1013
|
+
────────────────────────────────────────────────────────────
|
|
1014
|
+
Hello from container!
|
|
1015
|
+
────────────────────────────────────────────────────────────
|
|
1016
|
+
```
|
|
1017
|
+
|
|
1018
|
+
**History Command:**
|
|
1019
|
+
```bash
|
|
1020
|
+
$ saac exec --history
|
|
1021
|
+
|
|
1022
|
+
Execution History: myapp
|
|
1023
|
+
────────────────────────
|
|
1024
|
+
|
|
1025
|
+
╔══════════╤═══════════╤═════════════╤═══════════╤══════════╤═══════════════╗
|
|
1026
|
+
║ ID │ Command │ Status │ Exit Code │ Duration │ Started ║
|
|
1027
|
+
╠══════════╪═══════════╪═════════════╪═══════════╪══════════╪═══════════════╣
|
|
1028
|
+
║ eb41b197 │ echo '...'│ ✓ completed │ 0 │ 0s │ 1/28/26, 8:55 ║
|
|
1029
|
+
║ a3f2c891 │ npm run...│ ✗ completed │ 1 │ 5s │ 1/28/26, 8:50 ║
|
|
1030
|
+
╚══════════╧═══════════╧═════════════╧═══════════╧══════════╧═══════════════╝
|
|
1031
|
+
|
|
1032
|
+
Showing 2 of 5 executions
|
|
1033
|
+
```
|
|
1034
|
+
|
|
1035
|
+
**Location:** `src/commands/exec.js`
|
|
1036
|
+
|
|
1037
|
+
**Backend Implementation:**
|
|
1038
|
+
- Database table: `exec_requests` (status: pending → running → completed/failed/timeout)
|
|
1039
|
+
- Python daemon: `/root/exec-daemon/exec_daemon.py` (polls every 2 seconds)
|
|
1040
|
+
- Systemd service: `exec-daemon.service` (auto-restart, logs to `/var/log/exec-daemon.log`)
|
|
1041
|
+
|
|
1042
|
+
---
|
|
1043
|
+
|
|
1044
|
+
**Backend Requirements (Implemented):**
|
|
1045
|
+
- `GET /api/v1/applications/:uuid/env/export` - Export endpoint (deployed 2026-01-28)
|
|
1046
|
+
- Returns: `environment` (object), `export_script` (bash format), `dotenv_format` (dotenv format)
|
|
1047
|
+
- Rate limit: 10 requests/minute per user
|
|
1048
|
+
- Authentication: X-Session-Token or X-API-Key
|
|
1049
|
+
- Response includes `expires_in: 300` (5-minute cache recommendation)
|
|
1050
|
+
- `POST /api/v1/applications/:uuid/exec` - Execute command in container (deployed 2026-01-28)
|
|
1051
|
+
- `GET /api/v1/applications/:uuid/exec/history` - View execution history (deployed 2026-01-28)
|
|
1052
|
+
- Rate limit: 30 requests per 5 minutes per user
|
|
664
1053
|
|
|
665
1054
|
**Implementation Pattern for New Commands:**
|
|
666
1055
|
1. Require flags, no interactive prompts (exception: `init` uses inquirer for app selection)
|
|
@@ -669,15 +1058,6 @@ Several commands still need implementation:
|
|
|
669
1058
|
4. Use spinners for async operations
|
|
670
1059
|
5. Handle errors with descriptive messages
|
|
671
1060
|
|
|
672
|
-
**Example Module Structure for env.js:**
|
|
673
|
-
```javascript
|
|
674
|
-
async function set(vars) { /* implementation */ }
|
|
675
|
-
async function get(key) { /* implementation */ }
|
|
676
|
-
async function list() { /* implementation */ }
|
|
677
|
-
|
|
678
|
-
module.exports = { set, get, list };
|
|
679
|
-
```
|
|
680
|
-
|
|
681
1061
|
### MailHog Integration
|
|
682
1062
|
|
|
683
1063
|
The system uses MailHog for email verification in development:
|
|
@@ -697,7 +1077,7 @@ The wrapper API expects Git repositories to be hosted on the StartAnAiCompany Gi
|
|
|
697
1077
|
- During registration, Gitea username can be auto-detected or manually provided
|
|
698
1078
|
- Applications reference repositories in the format: `git@git.startanaicompany.com:user/repo.git`
|
|
699
1079
|
|
|
700
|
-
## Current Status - Version 1.
|
|
1080
|
+
## Current Status - Version 1.6.0
|
|
701
1081
|
|
|
702
1082
|
### Completed Features
|
|
703
1083
|
|
|
@@ -728,17 +1108,33 @@ The wrapper API expects Git repositories to be hosted on the StartAnAiCompany Gi
|
|
|
728
1108
|
- ✅ `saac update` - Update application configuration (PATCH endpoint)
|
|
729
1109
|
- ✅ `saac init` - Link existing application to current directory (interactive)
|
|
730
1110
|
- ✅ `saac deploy` - Trigger deployment for current application
|
|
1111
|
+
- ✅ `saac deployments` - List deployment history with table display
|
|
1112
|
+
- ✅ `saac logs` - View deployment logs (build logs) or runtime logs (container logs)
|
|
731
1113
|
- ✅ `saac list` - List all applications with table display
|
|
732
1114
|
- ✅ `saac status` - Show login status, user info, and applications
|
|
1115
|
+
- ✅ `saac delete` - Delete application with confirmation prompt
|
|
1116
|
+
- ✅ `saac whoami` - Show current user information
|
|
1117
|
+
|
|
1118
|
+
**Environment & Domain Management:**
|
|
1119
|
+
- ✅ `saac env set/get/list` - Manage environment variables (fully implemented)
|
|
1120
|
+
- ✅ `saac domain set/show` - Manage application domain (fully implemented)
|
|
1121
|
+
|
|
1122
|
+
**Local Development (Phase 1):**
|
|
1123
|
+
- ✅ `saac run <command>` - Execute local command with remote environment variables
|
|
1124
|
+
- Features: 5-minute caching, secure temp files (0600), automatic cleanup, rate limit handling
|
|
1125
|
+
|
|
1126
|
+
**Remote Shell (Project Aurora - Phase 3.5):**
|
|
1127
|
+
- ✅ `saac shell` - TRUE remote shell inside Docker container via WebSocket
|
|
1128
|
+
- Features: Persistent sessions (tmux), interactive (vim/nano work), real-time output, auto-reconnect
|
|
1129
|
+
- Architecture: WebSocket client + PostgreSQL + Python daemon + Docker + tmux
|
|
1130
|
+
- **Status:** CLI ready, waiting for backend deployment
|
|
1131
|
+
|
|
1132
|
+
**Remote Execution (NEW in 1.6.0):**
|
|
1133
|
+
- ✅ `saac exec <command>` - Execute commands in remote container
|
|
1134
|
+
- ✅ `saac exec --history` - View execution history
|
|
1135
|
+
- Features: Command allowlist, dangerous pattern detection, rate limiting (30/5min), audit logging
|
|
733
1136
|
|
|
734
|
-
**
|
|
735
|
-
- ⏳ `saac logs` - Not implemented (stub only)
|
|
736
|
-
- ⏳ `saac env` - Not implemented (stub only, needs to export object with set/get/list methods)
|
|
737
|
-
- ⏳ `saac domain` - Not implemented (stub only, needs to export object with set/show methods)
|
|
738
|
-
- ⏳ `saac delete` - Not implemented (stub only)
|
|
739
|
-
- ⏳ `saac whoami` - Not implemented (stub only)
|
|
740
|
-
- ✅ `saac deploy` - Fully implemented
|
|
741
|
-
- ✅ `saac list` - Fully implemented
|
|
1137
|
+
**All Commands Implemented!** ✅ No incomplete commands remain
|
|
742
1138
|
|
|
743
1139
|
### Critical Learnings & Bug Fixes
|
|
744
1140
|
|
|
@@ -780,7 +1176,7 @@ The wrapper API expects Git repositories to be hosted on the StartAnAiCompany Gi
|
|
|
780
1176
|
|
|
781
1177
|
### API Endpoint Reference
|
|
782
1178
|
|
|
783
|
-
**Correct Endpoint Paths (v1.
|
|
1179
|
+
**Correct Endpoint Paths (v1.5.0):**
|
|
784
1180
|
- `POST /api/v1/users/register` - Register (email only, git_username optional)
|
|
785
1181
|
- `POST /api/v1/users/verify` - Verify email with code
|
|
786
1182
|
- `POST /api/v1/auth/login` - Login with API key, get session token
|
|
@@ -796,7 +1192,10 @@ The wrapper API expects Git repositories to be hosted on the StartAnAiCompany Gi
|
|
|
796
1192
|
- `GET /api/v1/applications` - List applications
|
|
797
1193
|
- `PATCH /api/v1/applications/:uuid` - Update application
|
|
798
1194
|
- `POST /api/v1/applications/:uuid/deploy` - Deploy application
|
|
799
|
-
- `GET /api/v1/applications/:uuid/
|
|
1195
|
+
- `GET /api/v1/applications/:uuid/deployments` - Get deployment history (NEW in 1.4.17)
|
|
1196
|
+
- `GET /api/v1/applications/:uuid/deployment-logs` - Get deployment logs (NEW in 1.4.17)
|
|
1197
|
+
- `GET /api/v1/applications/:uuid/logs` - Get runtime logs (container logs)
|
|
1198
|
+
- `GET /api/v1/applications/:uuid/env/export` - Export environment variables (NEW in 1.5.0)
|
|
800
1199
|
- `DELETE /api/v1/applications/:uuid` - Delete application
|
|
801
1200
|
|
|
802
1201
|
**Important:** OAuth endpoints (`/oauth/*`) do NOT have the `/api/v1` prefix!
|
|
@@ -917,4 +1316,4 @@ Before publishing to npm:
|
|
|
917
1316
|
- `dotenv` - Environment variables
|
|
918
1317
|
- `open` - Open browser for OAuth (v8.4.2 for compatibility with chalk v4)
|
|
919
1318
|
|
|
920
|
-
**Version:** 1.
|
|
1319
|
+
**Version:** 1.5.0 (current)
|
package/bin/saac.js
CHANGED
|
@@ -22,6 +22,7 @@ const init = require('../src/commands/init');
|
|
|
22
22
|
const create = require('../src/commands/create');
|
|
23
23
|
const update = require('../src/commands/update');
|
|
24
24
|
const deploy = require('../src/commands/deploy');
|
|
25
|
+
const deployments = require('../src/commands/deployments');
|
|
25
26
|
const logs = require('../src/commands/logs');
|
|
26
27
|
const env = require('../src/commands/env');
|
|
27
28
|
const domain = require('../src/commands/domain');
|
|
@@ -30,6 +31,9 @@ const list = require('../src/commands/list');
|
|
|
30
31
|
const status = require('../src/commands/status');
|
|
31
32
|
const whoami = require('../src/commands/whoami');
|
|
32
33
|
const manual = require('../src/commands/manual');
|
|
34
|
+
const run = require('../src/commands/run');
|
|
35
|
+
const shell = require('../src/commands/shell');
|
|
36
|
+
const execCmd = require('../src/commands/exec');
|
|
33
37
|
|
|
34
38
|
// Configure CLI
|
|
35
39
|
program
|
|
@@ -200,12 +204,60 @@ program
|
|
|
200
204
|
.action(deploy);
|
|
201
205
|
|
|
202
206
|
program
|
|
203
|
-
.command('
|
|
204
|
-
.
|
|
205
|
-
.
|
|
206
|
-
.option('-
|
|
207
|
+
.command('deployments')
|
|
208
|
+
.alias('deploys')
|
|
209
|
+
.description('List deployment history')
|
|
210
|
+
.option('-l, --limit <number>', 'Number of deployments to show', '20')
|
|
211
|
+
.option('-o, --offset <number>', 'Offset for pagination', '0')
|
|
212
|
+
.action(deployments);
|
|
213
|
+
|
|
214
|
+
program
|
|
215
|
+
.command('logs [deploymentUuid]')
|
|
216
|
+
.description('View application logs (runtime or deployment logs)')
|
|
217
|
+
.option('-d, --deployment [uuid]', 'View deployment logs (build logs)')
|
|
218
|
+
.option('--raw', 'Show raw log output (deployment logs only)')
|
|
219
|
+
.option('--include-hidden', 'Include hidden log lines (deployment logs only)')
|
|
220
|
+
.option('-t, --tail <lines>', 'Number of lines to show (runtime logs only)', '100')
|
|
221
|
+
.option('-f, --follow', 'Follow log output (runtime logs only)')
|
|
222
|
+
.option('--since <time>', 'Show logs since timestamp (runtime logs only)')
|
|
207
223
|
.action(logs);
|
|
208
224
|
|
|
225
|
+
// Local development commands
|
|
226
|
+
program
|
|
227
|
+
.command('run <command>')
|
|
228
|
+
.description('Run local command with remote environment variables')
|
|
229
|
+
.option('--sync', 'Force refresh environment variables (skip cache)')
|
|
230
|
+
.option('-q, --quiet', 'Quiet mode (suppress warnings)')
|
|
231
|
+
.action(run);
|
|
232
|
+
|
|
233
|
+
program
|
|
234
|
+
.command('shell')
|
|
235
|
+
.description('Open interactive remote shell (inside container via WebSocket)')
|
|
236
|
+
.action(shell);
|
|
237
|
+
|
|
238
|
+
// Remote execution commands
|
|
239
|
+
program
|
|
240
|
+
.command('exec [command]')
|
|
241
|
+
.description('Execute command in remote container')
|
|
242
|
+
.option('--workdir <path>', 'Working directory (default: /app)')
|
|
243
|
+
.option('--timeout <seconds>', 'Timeout in seconds (default: 30, max: 300)', '30')
|
|
244
|
+
.option('--history', 'View execution history')
|
|
245
|
+
.option('--limit <number>', 'Limit for history (default: 20, max: 100)', '20')
|
|
246
|
+
.option('--offset <number>', 'Offset for history pagination (default: 0)', '0')
|
|
247
|
+
.action((command, options) => {
|
|
248
|
+
if (options.history) {
|
|
249
|
+
execCmd.history(options);
|
|
250
|
+
} else if (command) {
|
|
251
|
+
execCmd.exec(command, options);
|
|
252
|
+
} else {
|
|
253
|
+
console.error('Error: command is required (unless using --history)');
|
|
254
|
+
console.log('\nUsage:');
|
|
255
|
+
console.log(' saac exec <command> Execute command');
|
|
256
|
+
console.log(' saac exec --history View execution history');
|
|
257
|
+
process.exit(1);
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
|
|
209
261
|
// Environment variable commands
|
|
210
262
|
const envCommand = program
|
|
211
263
|
.command('env')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@startanaicompany/cli",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.19",
|
|
4
4
|
"description": "Official CLI for StartAnAiCompany.com - Deploy AI recruitment sites with ease",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -44,7 +44,8 @@
|
|
|
44
44
|
"open": "^8.4.2",
|
|
45
45
|
"ora": "^5.4.1",
|
|
46
46
|
"table": "^6.8.1",
|
|
47
|
-
"validator": "^13.11.0"
|
|
47
|
+
"validator": "^13.11.0",
|
|
48
|
+
"ws": "^8.19.0"
|
|
48
49
|
},
|
|
49
50
|
"devDependencies": {
|
|
50
51
|
"eslint": "^8.54.0"
|