tide-commander 1.95.0 → 1.97.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/dist/assets/{BossLogsModal-BNfB6g0E.js → BossLogsModal-CT25hD17.js} +1 -1
- package/dist/assets/{BossSpawnModal-BIcCbrjM.js → BossSpawnModal-9rS7AFkZ.js} +1 -1
- package/dist/assets/{ControlsModal-CS5jOEdY.js → ControlsModal-D-mymoM7.js} +1 -1
- package/dist/assets/{DockerLogsModal-B6sUNqY_.js → DockerLogsModal-Ae-ZCeeP.js} +1 -1
- package/dist/assets/EmbeddedEditor-DLOOpM0K.js +33 -0
- package/dist/assets/{GmailOAuthSetup-OPmwhJyE.js → GmailOAuthSetup-C9NLhWLo.js} +1 -1
- package/dist/assets/{GoogleOAuthSetup-BEc7lAua.js → GoogleOAuthSetup-1kzgrPV6.js} +1 -1
- package/dist/assets/{IframeModal-VrlQUMlO.js → IframeModal-DKS0IFsr.js} +1 -1
- package/dist/assets/{IntegrationsPanel-ta1yp-s4.js → IntegrationsPanel-CBvKOeud.js} +2 -2
- package/dist/assets/{LogViewerModal-B_4ke-1p.js → LogViewerModal-Dlt8JfVg.js} +1 -1
- package/dist/assets/{MonitoringModal-BHAuVdYA.js → MonitoringModal-BM1IEZv6.js} +1 -1
- package/dist/assets/{PM2LogsModal-BfKic3hD.js → PM2LogsModal-B1-HUHWZ.js} +1 -1
- package/dist/assets/{RestoreArchivedAreaModal-Bxk9GcPa.js → RestoreArchivedAreaModal-DXmYo7fp.js} +1 -1
- package/dist/assets/{Scene2DCanvas-COVSkNbV.js → Scene2DCanvas-CuUxSaPb.js} +1 -1
- package/dist/assets/{SceneManager-DWVI2idg.js → SceneManager-UD3IHY20.js} +1 -1
- package/dist/assets/{SkillsPanel-BnKqbJyg.js → SkillsPanel-DjRBVrO2.js} +1 -1
- package/dist/assets/SlackMultiInstanceSetup-Csp81Dqn.js +2 -0
- package/dist/assets/{SpawnModal-ClZUpgWy.js → SpawnModal-dg0mH3d9.js} +1 -1
- package/dist/assets/{SubordinateAssignmentModal-Dn8tejNU.js → SubordinateAssignmentModal-CeBPRNNX.js} +1 -1
- package/dist/assets/{TriggerManagerPanel-oBoHJdcv.js → TriggerManagerPanel-D1QPpFhP.js} +1 -1
- package/dist/assets/{WorkflowEditorPanel-Bwju9-46.js → WorkflowEditorPanel-IIsptZgp.js} +1 -1
- package/dist/assets/{index-Bu_n7vgB.js → index-BGh9tRSy.js} +1 -1
- package/dist/assets/{index-CfliOGe8.js → index-CIqkVLo1.js} +1 -1
- package/dist/assets/{index-CBh6qNCb.js → index-CNDUxsGy.js} +1 -1
- package/dist/assets/{index-umTVv-4x.js → index-CR9w26tq.js} +1 -1
- package/dist/assets/{index-DMUs4kjY.js → index-CsyPNc8u.js} +1 -1
- package/dist/assets/{index-DvBhO5je.js → index-DEI-vrXk.js} +1 -1
- package/dist/assets/{index-DgwVJN80.js → index-h-IcmGfB.js} +2 -2
- package/dist/assets/index-sDgBtEgH.js +19 -0
- package/dist/assets/{index-fIzifjgU.js → index-vJkimYqD.js} +1 -1
- package/dist/assets/main-BV_IuaBg.css +1 -0
- package/dist/assets/main-klWBzHh0.js +214 -0
- package/dist/assets/{web-Cp8n5FK3.js → web-BgPjNMBK.js} +1 -1
- package/dist/assets/{web-pfDqogx0.js → web-BmPSJLwQ.js} +1 -1
- package/dist/assets/{web-BD4VGICh.js → web-Dggt4D4N.js} +1 -1
- package/dist/index.html +2 -2
- package/dist/src/packages/server/data/builtin-skills/create-building.js +521 -484
- package/dist/src/packages/server/integrations/slack/slack-config.js +13 -0
- package/dist/src/packages/server/integrations/slack/slack-trigger-handler.js +12 -4
- package/dist/src/packages/server/routes/buildings.js +298 -0
- package/dist/src/packages/server/routes/index.js +3 -1
- package/dist/src/packages/server/services/building-service.js +400 -85
- package/dist/src/packages/server/websocket/handler.js +2 -4
- package/package.json +1 -1
- package/dist/assets/EmbeddedEditor-DiXmHZpX.js +0 -1
- package/dist/assets/SlackMultiInstanceSetup-BuA87Vlm.js +0 -2
- package/dist/assets/index-CXBrQLNP.js +0 -51
- package/dist/assets/main-BaGMbjuZ.js +0 -214
- package/dist/assets/main-BfT_95fk.css +0 -1
|
@@ -3,667 +3,704 @@ const BT3 = '```';
|
|
|
3
3
|
export const createBuilding = {
|
|
4
4
|
slug: 'create-building',
|
|
5
5
|
name: 'Create Building',
|
|
6
|
-
description: 'Create and
|
|
7
|
-
allowedTools: ['Bash(
|
|
6
|
+
description: 'Create, configure, control, and inspect buildings in Tide Commander via the /api/buildings REST API',
|
|
7
|
+
allowedTools: ['Bash(curl:*)', 'Bash(jq:*)'],
|
|
8
8
|
content: `# Create Building Skill
|
|
9
9
|
|
|
10
|
-
This skill
|
|
10
|
+
This skill manages buildings in Tide Commander's battlefield through the
|
|
11
|
+
REST API. The server validates input, assigns IDs, encrypts credentials,
|
|
12
|
+
broadcasts updates to connected clients, and reconciles PM2 / Docker /
|
|
13
|
+
Terminal runtime state. **Do not edit ${BT}buildings.json${BT} directly** — the
|
|
14
|
+
server is the authority for that file.
|
|
11
15
|
|
|
12
|
-
##
|
|
16
|
+
## API Calling Convention
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
- Auto-restart on crash
|
|
16
|
-
- CPU/memory/PID tracking
|
|
17
|
-
- Port auto-detection
|
|
18
|
-
- Process persistence across restarts
|
|
19
|
-
- Unified log streaming
|
|
20
|
-
- Status monitoring
|
|
18
|
+
Every call uses the standard scaffolding from your system prompt:
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
${BT3}bash
|
|
21
|
+
curl -s -X <METHOD> -H "X-Auth-Token: <TOKEN>" \\
|
|
22
|
+
http://localhost:5174/api/buildings<path> \\
|
|
23
|
+
-H "Content-Type: application/json" -d '<json-body>'
|
|
24
|
+
${BT3}
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
The substitutions on every call:
|
|
27
|
+
- ${BT}<METHOD>${BT} — HTTP verb (GET, POST, PATCH, DELETE)
|
|
28
|
+
- ${BT}<path>${BT} — endpoint path (begins with ${BT}/${BT})
|
|
29
|
+
- ${BT}<json-body>${BT} — JSON body (omit for GET/DELETE)
|
|
30
|
+
- ${BT}<TOKEN>${BT} — the auth token from your system prompt
|
|
31
|
+
- **No exclamation marks** anywhere in the command — bash history expansion will corrupt it.
|
|
32
|
+
|
|
33
|
+
## Endpoint Reference
|
|
34
|
+
|
|
35
|
+
| Method | Path | Purpose |
|
|
36
|
+
|--------|------|---------|
|
|
37
|
+
| GET | ${BT}/api/buildings${BT} | List all buildings (secrets redacted) |
|
|
38
|
+
| GET | ${BT}/api/buildings/:id${BT} | Get one building (secrets redacted) |
|
|
39
|
+
| POST | ${BT}/api/buildings${BT} | Create a building |
|
|
40
|
+
| PATCH | ${BT}/api/buildings/:id${BT} | Partial update |
|
|
41
|
+
| DELETE | ${BT}/api/buildings/:id?cleanup=false${BT} | Delete (default: tear down PM2/Docker/etc.) |
|
|
42
|
+
| POST | ${BT}/api/buildings/:id/command${BT} | ${BT}{"command":"start|stop|restart|healthCheck|logs|delete"}${BT} |
|
|
43
|
+
| GET | ${BT}/api/buildings/:id/logs?lines=200&service=foo${BT} | Snapshot logs (PM2/Docker/custom) |
|
|
44
|
+
| POST | ${BT}/api/buildings/:id/sync-status${BT} | Force PM2/Docker status refresh |
|
|
45
|
+
| POST | ${BT}/api/buildings/:id/subordinates${BT} | ${BT}{"subordinateBuildingIds":[...]}${BT} (boss only) |
|
|
46
|
+
| POST | ${BT}/api/buildings/boss/:id/command${BT} | ${BT}{"command":"start_all|stop_all|restart_all"}${BT} |
|
|
47
|
+
| GET | ${BT}/api/buildings/docker/containers${BT} | List adoptable Docker containers and compose projects |
|
|
48
|
+
|
|
49
|
+
The server assigns ${BT}id${BT}, ${BT}createdAt${BT}, ${BT}lastActivity${BT}, and initial
|
|
50
|
+
${BT}status${BT}. Do not send them. POST returns the full building (201). PATCH
|
|
51
|
+
returns the merged building. DELETE returns ${BT}{"deleted":true}${BT}.
|
|
52
|
+
|
|
53
|
+
Validation failures return ${BT}400${BT} with ${BT}{"error":"Validation failed","errors":[...]}${BT}.
|
|
54
|
+
|
|
55
|
+
## Step 1: Inspect what's there
|
|
27
56
|
|
|
28
57
|
${BT3}bash
|
|
29
|
-
# List all buildings with
|
|
30
|
-
|
|
58
|
+
# List all buildings — filter with jq for readability
|
|
59
|
+
curl -s -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
60
|
+
| jq '.buildings | map({id, name, type, status, cwd})'
|
|
31
61
|
|
|
32
|
-
#
|
|
33
|
-
|
|
62
|
+
# One building's full config
|
|
63
|
+
curl -s -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings/<id>
|
|
34
64
|
|
|
35
|
-
#
|
|
36
|
-
|
|
65
|
+
# All PM2 buildings
|
|
66
|
+
curl -s -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
67
|
+
| jq '.buildings[] | select(.pm2.enabled == true) | {name, port: .pm2.env.PORT, status}'
|
|
37
68
|
|
|
38
|
-
#
|
|
39
|
-
|
|
69
|
+
# Existing Docker containers ready to be adopted (mode "existing")
|
|
70
|
+
curl -s -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings/docker/containers \\
|
|
71
|
+
| jq '.containers | map({id: .id[0:12], name, image, status})'
|
|
72
|
+
${BT3}
|
|
40
73
|
|
|
41
|
-
|
|
42
|
-
jq '.buildings[] | select(.pm2.env.PORT != null) | {name, port: .pm2.env.PORT}' ~/.local/share/tide-commander/buildings.json
|
|
74
|
+
## Step 2: Building schema
|
|
43
75
|
|
|
44
|
-
|
|
45
|
-
|
|
76
|
+
These fields are accepted by ${BT}POST /api/buildings${BT}. ${BT}name${BT}, ${BT}type${BT}, and
|
|
77
|
+
${BT}position${BT} are always required. Style defaults per type if omitted.
|
|
46
78
|
|
|
47
|
-
|
|
48
|
-
|
|
79
|
+
${BT3}typescript
|
|
80
|
+
{
|
|
81
|
+
name: string, // Display name
|
|
82
|
+
type: 'server'|'link'|'database'|'docker'|'monitor'|'folder'|'boss'|'terminal',
|
|
83
|
+
position: { x: number, z: number },
|
|
84
|
+
style?: 'server-rack'|'tower'|'dome'|'pyramid'|'desktop'
|
|
85
|
+
| 'filing-cabinet'|'satellite'|'crystal'|'factory'|'command-center',
|
|
86
|
+
color?: string, // Hex (e.g. "#4a90d9")
|
|
87
|
+
scale?: number, // ~0.5 small, 1.0 large
|
|
88
|
+
cwd?: string, // Working directory
|
|
89
|
+
pm2?: { ... }, // Server type — see below
|
|
90
|
+
docker?: { ... }, // Docker type — see below
|
|
91
|
+
database?: { connections: [...] }, // Database type
|
|
92
|
+
terminal?: { ... }, // Terminal type
|
|
93
|
+
folderPath?: string, // Folder type — required
|
|
94
|
+
urls?: [{ label, url }], // Link type — required
|
|
95
|
+
commands?: { start, stop, restart, healthCheck, logs }, // Non-PM2 server custom commands
|
|
96
|
+
subordinateBuildingIds?: string[], // Boss type
|
|
97
|
+
}
|
|
49
98
|
${BT3}
|
|
50
99
|
|
|
51
|
-
|
|
100
|
+
### PM2 sub-schema (server buildings)
|
|
101
|
+
|
|
102
|
+
${BT3}typescript
|
|
103
|
+
pm2: {
|
|
104
|
+
enabled: true,
|
|
105
|
+
script: string, // REQUIRED
|
|
106
|
+
args?: string,
|
|
107
|
+
interpreter?: ''|'node'|'bun'|'python3'|'python'|'java'|'php'|'bash'|'none',
|
|
108
|
+
interpreterArgs?: string,
|
|
109
|
+
env?: Record<string, string>,
|
|
110
|
+
instances?: number, // Cluster mode (default 1)
|
|
111
|
+
autorestart?: boolean, // Default true
|
|
112
|
+
maxRestarts?: number, // Default 10
|
|
113
|
+
name?: string, // Custom PM2 app name
|
|
114
|
+
}
|
|
115
|
+
${BT3}
|
|
52
116
|
|
|
53
|
-
###
|
|
117
|
+
### Docker sub-schema
|
|
54
118
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
119
|
+
${BT3}typescript
|
|
120
|
+
docker: {
|
|
121
|
+
enabled: true,
|
|
122
|
+
mode: 'container' | 'compose' | 'existing',
|
|
123
|
+
|
|
124
|
+
// mode === 'container' (REQUIRED: image)
|
|
125
|
+
image?: string,
|
|
126
|
+
containerName?: string,
|
|
127
|
+
ports?: string[], // ["3000:3000"]
|
|
128
|
+
volumes?: string[], // ["/host:/container"]
|
|
129
|
+
env?: Record<string, string>,
|
|
130
|
+
network?: string,
|
|
131
|
+
command?: string,
|
|
132
|
+
restart?: 'no'|'always'|'unless-stopped'|'on-failure',
|
|
133
|
+
pull?: 'always'|'missing'|'never',
|
|
134
|
+
|
|
135
|
+
// mode === 'compose' (REQUIRED: composePath)
|
|
136
|
+
composePath?: string, // Relative to cwd
|
|
137
|
+
services?: string[],
|
|
138
|
+
composeProject?: string,
|
|
139
|
+
|
|
140
|
+
// mode === 'existing' (REQUIRED: containerName from /docker/containers)
|
|
141
|
+
}
|
|
142
|
+
${BT3}
|
|
62
143
|
|
|
63
|
-
###
|
|
144
|
+
### Database connection sub-schema
|
|
64
145
|
|
|
65
|
-
|
|
146
|
+
${BT3}typescript
|
|
147
|
+
database: {
|
|
148
|
+
activeConnectionId?: string,
|
|
149
|
+
activeDatabase?: string,
|
|
150
|
+
connections: [{
|
|
151
|
+
id: string,
|
|
152
|
+
name: string,
|
|
153
|
+
engine: 'mysql'|'postgresql'|'oracle'|'sqlite'|'mssql',
|
|
154
|
+
host: string, // omit for sqlite
|
|
155
|
+
port: number, // omit for sqlite
|
|
156
|
+
username?: string,
|
|
157
|
+
password?: string, // Encrypted at rest
|
|
158
|
+
database?: string, // Service/PDB name for Oracle
|
|
159
|
+
filepath?: string, // REQUIRED for sqlite
|
|
160
|
+
ssl?: boolean,
|
|
161
|
+
sslConfig?: { rejectUnauthorized, ca, cert, key },
|
|
162
|
+
ssh?: { // Optional SSH tunnel
|
|
163
|
+
enabled: true,
|
|
164
|
+
host, port, username,
|
|
165
|
+
authMethod: 'password'|'privateKey',
|
|
166
|
+
password?, privateKey?, privateKeyPath?, passphrase?,
|
|
167
|
+
localPort?, keepaliveIntervalMs?, readyTimeoutMs?,
|
|
168
|
+
},
|
|
169
|
+
}],
|
|
170
|
+
}
|
|
171
|
+
${BT3}
|
|
66
172
|
|
|
67
|
-
|
|
173
|
+
### Terminal sub-schema
|
|
68
174
|
|
|
69
|
-
|
|
175
|
+
${BT3}typescript
|
|
176
|
+
terminal: {
|
|
177
|
+
enabled: true, // REQUIRED for type 'terminal'
|
|
178
|
+
shell?: string, // Defaults to $SHELL or bash
|
|
179
|
+
port?: number, // Auto-assigned from 7681+
|
|
180
|
+
args?: string, // Extra ttyd args
|
|
181
|
+
saveSession?: boolean, // tmux-backed persistence
|
|
182
|
+
sessionName?: string,
|
|
183
|
+
}
|
|
184
|
+
${BT3}
|
|
185
|
+
|
|
186
|
+
Default ports: MySQL 3306, PostgreSQL 5432, Oracle 1521, SQL Server 1433.
|
|
187
|
+
|
|
188
|
+
## Step 3: Create the building
|
|
189
|
+
|
|
190
|
+
### Bun/Node service with PM2
|
|
70
191
|
|
|
71
192
|
${BT3}bash
|
|
72
|
-
|
|
73
|
-
"
|
|
193
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
194
|
+
-H "Content-Type: application/json" -d '{
|
|
195
|
+
"name": "Wind Front",
|
|
74
196
|
"type": "server",
|
|
75
|
-
"style": "
|
|
76
|
-
"color": "#
|
|
77
|
-
"position": {"x":
|
|
78
|
-
"cwd": "/home/
|
|
197
|
+
"style": "desktop",
|
|
198
|
+
"color": "#4a3a2a",
|
|
199
|
+
"position": {"x": -3.5, "z": -8.0},
|
|
200
|
+
"cwd": "/home/user/projects/wind/front",
|
|
79
201
|
"pm2": {
|
|
80
202
|
"enabled": true,
|
|
81
|
-
"script": "/home/
|
|
203
|
+
"script": "/home/user/.bun/bin/bun",
|
|
82
204
|
"args": "run dev",
|
|
83
205
|
"interpreter": "none",
|
|
84
|
-
"env": {"PORT": "
|
|
206
|
+
"env": {"PORT": "6205"}
|
|
85
207
|
},
|
|
86
|
-
"scale": 0.75
|
|
87
|
-
|
|
88
|
-
"status": "stopped",
|
|
89
|
-
"createdAt": 1707471234567,
|
|
90
|
-
"lastActivity": 1707471234567
|
|
91
|
-
}]' ~/.local/share/tide-commander/buildings.json > /tmp/b.json && mv /tmp/b.json ~/.local/share/tide-commander/buildings.json
|
|
208
|
+
"scale": 0.75
|
|
209
|
+
}'
|
|
92
210
|
${BT3}
|
|
93
211
|
|
|
94
|
-
|
|
212
|
+
For Vite frontends, the project's ${BT}vite.config.*${BT} must honour ${BT}process.env.PORT${BT}
|
|
213
|
+
(otherwise PM2 sets the var but Vite ignores it).
|
|
95
214
|
|
|
96
|
-
###
|
|
215
|
+
### Bun with port passed in args (no env var needed)
|
|
97
216
|
|
|
98
217
|
${BT3}bash
|
|
99
|
-
|
|
100
|
-
"
|
|
218
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
219
|
+
-H "Content-Type: application/json" -d '{
|
|
220
|
+
"name": "MDO Front",
|
|
221
|
+
"type": "server",
|
|
222
|
+
"position": {"x": -9.5, "z": 2.55},
|
|
223
|
+
"cwd": "/home/user/projects/mdo/front",
|
|
224
|
+
"pm2": { "enabled": true, "script": "bun", "args": "dev --port 6200", "interpreter": "none" }
|
|
225
|
+
}'
|
|
226
|
+
${BT3}
|
|
227
|
+
|
|
228
|
+
### Symfony service (port in args, no --daemon)
|
|
229
|
+
|
|
230
|
+
${BT3}bash
|
|
231
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
232
|
+
-H "Content-Type: application/json" -d '{
|
|
233
|
+
"name": "MDO Back",
|
|
101
234
|
"type": "server",
|
|
102
|
-
"style": "server-rack",
|
|
103
|
-
"color": "#2a3a3a",
|
|
104
235
|
"position": {"x": -11.67, "z": 2.55},
|
|
105
|
-
"cwd": "/home/
|
|
236
|
+
"cwd": "/home/user/projects/mdo/back",
|
|
106
237
|
"pm2": {
|
|
107
238
|
"enabled": true,
|
|
108
239
|
"script": "symfony",
|
|
109
240
|
"args": "server:start --allow-http --port=7200",
|
|
110
241
|
"interpreter": "none"
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
${
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
- Script: "symfony" (requires Symfony CLI installed and in PATH)
|
|
121
|
-
- Args: "server:start --allow-http --port=XXXX --no-tls"
|
|
122
|
-
- --allow-http: Allows HTTP (use for dev). Remove for HTTPS
|
|
123
|
-
- --no-tls: Disable TLS (useful for local dev behind proxy)
|
|
124
|
-
- **IMPORTANT: Do NOT use --daemon flag** - PM2 needs the process to run in foreground. The --daemon flag causes Symfony to fork and exit, which PM2 interprets as a crash
|
|
125
|
-
- Port goes in args, not env vars
|
|
126
|
-
- PM2 auto-detects port from startup output
|
|
127
|
-
- Note: Symfony server opens an extra port (42421 in example) for the server monitor
|
|
128
|
-
- Tip: If PM2 shows "errored", check if a Symfony daemon is already running with: symfony server:status. Stop it with: symfony server:stop
|
|
129
|
-
|
|
130
|
-
### PHP Built-in Server (Example - Port 7205)
|
|
242
|
+
}
|
|
243
|
+
}'
|
|
244
|
+
${BT3}
|
|
245
|
+
|
|
246
|
+
**Symfony notes:** never use ${BT}--daemon${BT} — Symfony forks and exits, PM2 marks it errored.
|
|
247
|
+
If PM2 shows errored with "already running", stop the external daemon first:
|
|
248
|
+
${BT}symfony server:stop${BT} from the project directory, then ${BT}POST .../command { start }${BT}.
|
|
249
|
+
|
|
250
|
+
### PHP built-in server
|
|
131
251
|
|
|
132
252
|
${BT3}bash
|
|
133
|
-
|
|
134
|
-
"
|
|
253
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
254
|
+
-H "Content-Type: application/json" -d '{
|
|
255
|
+
"name": "Laravel App",
|
|
135
256
|
"type": "server",
|
|
136
|
-
"style": "server-rack",
|
|
137
|
-
"color": "#2a3a4a",
|
|
138
257
|
"position": {"x": 0.77, "z": 3.96},
|
|
139
|
-
"cwd": "/home/
|
|
140
|
-
"pm2": {
|
|
141
|
-
|
|
142
|
-
"script": "php",
|
|
143
|
-
"args": "-S 0.0.0.0:7205 -t public",
|
|
144
|
-
"interpreter": "none"
|
|
145
|
-
},
|
|
146
|
-
"scale": 0.75,
|
|
147
|
-
"id": "building_1770769766821_myapp",
|
|
148
|
-
"status": "stopped",
|
|
149
|
-
"createdAt": 1770769766821
|
|
150
|
-
}]' ~/.local/share/tide-commander/buildings.json > /tmp/b.json && mv /tmp/b.json ~/.local/share/tide-commander/buildings.json
|
|
258
|
+
"cwd": "/home/user/projects/laravel-app",
|
|
259
|
+
"pm2": { "enabled": true, "script": "php", "args": "-S 0.0.0.0:7205 -t public", "interpreter": "none" }
|
|
260
|
+
}'
|
|
151
261
|
${BT3}
|
|
152
262
|
|
|
153
|
-
|
|
154
|
-
- Script: "php" (built-in web server, no extra tools needed)
|
|
155
|
-
- Args: "-S 0.0.0.0:PORT -t DOCROOT"
|
|
156
|
-
- -S: Start server on address:port
|
|
157
|
-
- -t: Document root directory
|
|
158
|
-
- Use 0.0.0.0 to listen on all interfaces (accessible from network)
|
|
159
|
-
- Port goes in args after -S flag
|
|
160
|
-
|
|
161
|
-
### Maven Java Project (Pagamento)
|
|
263
|
+
### Maven / Spring Boot
|
|
162
264
|
|
|
163
265
|
${BT3}bash
|
|
164
|
-
|
|
266
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
267
|
+
-H "Content-Type: application/json" -d '{
|
|
165
268
|
"name": "Pagamento",
|
|
166
269
|
"type": "server",
|
|
167
|
-
"style": "server-rack",
|
|
168
|
-
"color": "#3a2a3a",
|
|
169
270
|
"position": {"x": -11.85, "z": 9.59},
|
|
170
|
-
"cwd": "/home/
|
|
271
|
+
"cwd": "/home/user/projects/pagamento",
|
|
171
272
|
"pm2": {
|
|
172
|
-
"enabled": true,
|
|
173
|
-
"
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
},
|
|
177
|
-
"scale": 0.75,
|
|
178
|
-
"id": "building_1769555952700_pagamento",
|
|
179
|
-
"status": "stopped",
|
|
180
|
-
"createdAt": 1769555952700
|
|
181
|
-
}]' ~/.local/share/tide-commander/buildings.json > /tmp/b.json && mv /tmp/b.json ~/.local/share/tide-commander/buildings.json
|
|
273
|
+
"enabled": true, "script": "mvn", "interpreter": "none",
|
|
274
|
+
"args": "spring-boot:run -Dspring-boot.run.fork=false -Dspring-boot.run.profiles=dev"
|
|
275
|
+
}
|
|
276
|
+
}'
|
|
182
277
|
${BT3}
|
|
183
278
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
### Shell Script Binary (ActiveMQ)
|
|
279
|
+
### Shell-script server (ActiveMQ)
|
|
187
280
|
|
|
188
281
|
${BT3}bash
|
|
189
|
-
|
|
282
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
283
|
+
-H "Content-Type: application/json" -d '{
|
|
190
284
|
"name": "ActiveMQ",
|
|
191
285
|
"type": "server",
|
|
192
286
|
"style": "filing-cabinet",
|
|
193
|
-
"color": "#2a2a4a",
|
|
194
287
|
"position": {"x": -7.30, "z": -0.15},
|
|
195
288
|
"cwd": "/opt/apache-activemq-6.2.0",
|
|
196
|
-
"pm2": {
|
|
197
|
-
|
|
198
|
-
"script": "./bin/activemq",
|
|
199
|
-
"args": "console",
|
|
200
|
-
"interpreter": "bash"
|
|
201
|
-
},
|
|
202
|
-
"scale": 0.5,
|
|
203
|
-
"id": "building_1769556341280_activemq",
|
|
204
|
-
"status": "stopped",
|
|
205
|
-
"createdAt": 1769556341280
|
|
206
|
-
}]' ~/.local/share/tide-commander/buildings.json > /tmp/b.json && mv /tmp/b.json ~/.local/share/tide-commander/buildings.json
|
|
289
|
+
"pm2": { "enabled": true, "script": "./bin/activemq", "args": "console", "interpreter": "bash" }
|
|
290
|
+
}'
|
|
207
291
|
${BT3}
|
|
208
292
|
|
|
209
|
-
|
|
293
|
+
### Custom-command server (no PM2)
|
|
210
294
|
|
|
211
|
-
|
|
295
|
+
For servers where PM2 doesn't fit, define ${BT}commands${BT} directly. Each command runs in
|
|
296
|
+
${BT}cwd${BT}. Status transitions happen on command completion.
|
|
212
297
|
|
|
213
298
|
${BT3}bash
|
|
214
|
-
|
|
215
|
-
"
|
|
299
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
300
|
+
-H "Content-Type: application/json" -d '{
|
|
301
|
+
"name": "Legacy Service",
|
|
216
302
|
"type": "server",
|
|
217
|
-
"
|
|
218
|
-
"
|
|
219
|
-
"
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
"
|
|
223
|
-
"
|
|
224
|
-
"
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
},
|
|
228
|
-
"scale": 1.0,
|
|
229
|
-
"id": "building_1707471234571_tide_commander",
|
|
230
|
-
"status": "stopped",
|
|
231
|
-
"createdAt": 1707471234571
|
|
232
|
-
}]' ~/.local/share/tide-commander/buildings.json > /tmp/b.json && mv /tmp/b.json ~/.local/share/tide-commander/buildings.json
|
|
303
|
+
"position": {"x": 5, "z": 5},
|
|
304
|
+
"cwd": "/srv/legacy",
|
|
305
|
+
"commands": {
|
|
306
|
+
"start": "./bin/start.sh",
|
|
307
|
+
"stop": "./bin/stop.sh",
|
|
308
|
+
"restart": "./bin/restart.sh",
|
|
309
|
+
"healthCheck": "curl -fs http://localhost:9000/health",
|
|
310
|
+
"logs": "tail -n 200 /srv/legacy/log/app.log"
|
|
311
|
+
}
|
|
312
|
+
}'
|
|
233
313
|
${BT3}
|
|
234
314
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
### Bun Frontend with Port in Args (MDO Front - Port 6200)
|
|
315
|
+
### Docker — new container
|
|
238
316
|
|
|
239
317
|
${BT3}bash
|
|
240
|
-
|
|
241
|
-
"
|
|
242
|
-
"
|
|
243
|
-
"
|
|
244
|
-
"
|
|
245
|
-
"position": {"x": -
|
|
246
|
-
"cwd": "/home/
|
|
247
|
-
"
|
|
318
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
319
|
+
-H "Content-Type: application/json" -d '{
|
|
320
|
+
"name": "Redis",
|
|
321
|
+
"type": "docker",
|
|
322
|
+
"style": "dome",
|
|
323
|
+
"position": {"x": -8, "z": -3},
|
|
324
|
+
"cwd": "/home/user/projects/tide-commander",
|
|
325
|
+
"docker": {
|
|
248
326
|
"enabled": true,
|
|
249
|
-
"
|
|
250
|
-
"
|
|
251
|
-
"
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
"status": "stopped",
|
|
256
|
-
"createdAt": 1769553790570
|
|
257
|
-
}]' ~/.local/share/tide-commander/buildings.json > /tmp/b.json && mv /tmp/b.json ~/.local/share/tide-commander/buildings.json
|
|
327
|
+
"mode": "container",
|
|
328
|
+
"image": "redis:7-alpine",
|
|
329
|
+
"ports": ["6379:6379"],
|
|
330
|
+
"restart": "unless-stopped"
|
|
331
|
+
}
|
|
332
|
+
}'
|
|
258
333
|
${BT3}
|
|
259
334
|
|
|
260
|
-
|
|
261
|
-
- Script: "bun" (short name, assumes bun is in PATH)
|
|
262
|
-
- Args: "dev --port XXXX" passes port directly to the dev server
|
|
263
|
-
- No env var needed when the framework CLI accepts --port flag
|
|
264
|
-
- Works with frameworks like Vite, Next.js, Nuxt where ${BT}bun dev --port${BT} is supported
|
|
265
|
-
- Alternative: Use full path ${BT}/home/riven/.bun/bin/bun${BT} if bun is not in PATH
|
|
266
|
-
|
|
267
|
-
### Vite + Bun Frontend (Wind Front - Port 6205)
|
|
335
|
+
### Docker — compose project
|
|
268
336
|
|
|
269
337
|
${BT3}bash
|
|
270
|
-
|
|
271
|
-
"
|
|
272
|
-
"
|
|
273
|
-
"
|
|
274
|
-
"
|
|
275
|
-
"
|
|
276
|
-
"
|
|
277
|
-
"pm2": {
|
|
338
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
339
|
+
-H "Content-Type: application/json" -d '{
|
|
340
|
+
"name": "App Stack",
|
|
341
|
+
"type": "docker",
|
|
342
|
+
"position": {"x": -10, "z": 0},
|
|
343
|
+
"cwd": "/home/user/projects/app",
|
|
344
|
+
"docker": {
|
|
278
345
|
"enabled": true,
|
|
279
|
-
"
|
|
280
|
-
"
|
|
281
|
-
"
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
"scale": 0.75,
|
|
285
|
-
"id": "building_1707471234572_wind_front",
|
|
286
|
-
"status": "stopped",
|
|
287
|
-
"createdAt": 1707471234572
|
|
288
|
-
}]' ~/.local/share/tide-commander/buildings.json > /tmp/b.json && mv /tmp/b.json ~/.local/share/tide-commander/buildings.json
|
|
346
|
+
"mode": "compose",
|
|
347
|
+
"composePath": "docker-compose.yml",
|
|
348
|
+
"services": ["web", "worker"]
|
|
349
|
+
}
|
|
350
|
+
}'
|
|
289
351
|
${BT3}
|
|
290
352
|
|
|
291
|
-
|
|
292
|
-
- Script: Full path to bun binary (or "npm" if using npm)
|
|
293
|
-
- Args: "run dev" (Vite dev server command)
|
|
294
|
-
- **IMPORTANT: Update vite.config.mjs to read PORT env var:**
|
|
295
|
-
- Add to server config: ${BT}port: parseInt(process.env.PORT || "6205", 10)${BT}
|
|
296
|
-
- Add: ${BT}host: true${BT} to allow network access
|
|
297
|
-
- Set ${BT}open: false${BT} to prevent auto-opening browser
|
|
298
|
-
- Port passed via env var, not args
|
|
299
|
-
- Tip: Check config with: cat vite.config.mjs | grep -A 5 "server:"
|
|
353
|
+
### Docker — adopt existing container
|
|
300
354
|
|
|
301
|
-
|
|
355
|
+
First discover ${BT}containerName${BT}:
|
|
302
356
|
|
|
303
357
|
${BT3}bash
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
"type": "boss",
|
|
307
|
-
"style": "command-center",
|
|
308
|
-
"color": "#4a4a6a",
|
|
309
|
-
"position": {"x": 11.36, "z": -9.77},
|
|
310
|
-
"cwd": "/home/riven/d/navi",
|
|
311
|
-
"commands": {},
|
|
312
|
-
"subordinateBuildingIds": [
|
|
313
|
-
"building_1707471234567_navi_back",
|
|
314
|
-
"building_1707471234568_navi_front"
|
|
315
|
-
],
|
|
316
|
-
"scale": 0.6,
|
|
317
|
-
"id": "building_1707471234570_navi_boss",
|
|
318
|
-
"status": "running",
|
|
319
|
-
"createdAt": 1707471234570
|
|
320
|
-
}]' ~/.local/share/tide-commander/buildings.json > /tmp/b.json && mv /tmp/b.json ~/.local/share/tide-commander/buildings.json
|
|
358
|
+
curl -s -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings/docker/containers \\
|
|
359
|
+
| jq '.containers | map({name, image, status})'
|
|
321
360
|
${BT3}
|
|
322
361
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
### Docker Existing Container (Postgres 18)
|
|
362
|
+
Then adopt:
|
|
326
363
|
|
|
327
364
|
${BT3}bash
|
|
328
|
-
|
|
365
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
366
|
+
-H "Content-Type: application/json" -d '{
|
|
329
367
|
"name": "Postgres 18",
|
|
330
368
|
"type": "docker",
|
|
331
369
|
"style": "dome",
|
|
332
370
|
"color": "#336699",
|
|
333
371
|
"position": {"x": -11.49, "z": -2.31},
|
|
334
|
-
"cwd": "/home/
|
|
335
|
-
"docker": {
|
|
336
|
-
|
|
337
|
-
"mode": "existing",
|
|
338
|
-
"containerId": "fc1e2a1e0481",
|
|
339
|
-
"containerName": "postgres18"
|
|
340
|
-
},
|
|
341
|
-
"scale": 0.6,
|
|
342
|
-
"id": "building_1707471234569_postgres",
|
|
343
|
-
"status": "stopped",
|
|
344
|
-
"createdAt": 1707471234569
|
|
345
|
-
}]' ~/.local/share/tide-commander/buildings.json > /tmp/b.json && mv /tmp/b.json ~/.local/share/tide-commander/buildings.json
|
|
372
|
+
"cwd": "/home/user/projects/tide-commander",
|
|
373
|
+
"docker": { "enabled": true, "mode": "existing", "containerName": "postgres18" }
|
|
374
|
+
}'
|
|
346
375
|
${BT3}
|
|
347
376
|
|
|
348
|
-
|
|
377
|
+
Mode ${BT}existing${BT} is monitor-only: deleting the building never removes the container.
|
|
349
378
|
|
|
350
|
-
### Database
|
|
379
|
+
### Database — MySQL
|
|
351
380
|
|
|
352
381
|
${BT3}bash
|
|
353
|
-
|
|
354
|
-
"
|
|
382
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
383
|
+
-H "Content-Type: application/json" -d '{
|
|
384
|
+
"name": "MySQL",
|
|
355
385
|
"type": "database",
|
|
356
386
|
"style": "dome",
|
|
357
387
|
"position": {"x": -9.78, "z": -0.34},
|
|
358
|
-
"cwd": "/home/riven/d/tide-commander",
|
|
359
|
-
"commands": {},
|
|
360
388
|
"database": {
|
|
361
389
|
"connections": [{
|
|
362
|
-
"id": "
|
|
363
|
-
"name": "
|
|
390
|
+
"id": "conn_mysql_prod",
|
|
391
|
+
"name": "Primary",
|
|
364
392
|
"engine": "mysql",
|
|
365
393
|
"host": "localhost",
|
|
366
394
|
"port": 3306,
|
|
367
395
|
"username": "root",
|
|
368
396
|
"password": "root"
|
|
369
397
|
}],
|
|
370
|
-
"activeConnectionId": "
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
"status": "stopped",
|
|
374
|
-
"createdAt": 1769620533827
|
|
375
|
-
}]' ~/.local/share/tide-commander/buildings.json > /tmp/b.json && mv /tmp/b.json ~/.local/share/tide-commander/buildings.json
|
|
398
|
+
"activeConnectionId": "conn_mysql_prod"
|
|
399
|
+
}
|
|
400
|
+
}'
|
|
376
401
|
${BT3}
|
|
377
402
|
|
|
378
|
-
|
|
403
|
+
### Database — PostgreSQL
|
|
379
404
|
|
|
380
|
-
|
|
405
|
+
${BT3}bash
|
|
406
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
407
|
+
-H "Content-Type: application/json" -d '{
|
|
408
|
+
"name": "Postgres",
|
|
409
|
+
"type": "database",
|
|
410
|
+
"position": {"x": -8, "z": -0.34},
|
|
411
|
+
"database": {
|
|
412
|
+
"connections": [{
|
|
413
|
+
"id": "conn_pg_dev",
|
|
414
|
+
"name": "Dev",
|
|
415
|
+
"engine": "postgresql",
|
|
416
|
+
"host": "localhost",
|
|
417
|
+
"port": 5432,
|
|
418
|
+
"username": "postgres",
|
|
419
|
+
"password": "postgres",
|
|
420
|
+
"database": "appdb"
|
|
421
|
+
}]
|
|
422
|
+
}
|
|
423
|
+
}'
|
|
424
|
+
${BT3}
|
|
425
|
+
|
|
426
|
+
### Database — Oracle
|
|
381
427
|
|
|
382
428
|
${BT3}bash
|
|
383
|
-
|
|
429
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
430
|
+
-H "Content-Type: application/json" -d '{
|
|
384
431
|
"name": "Oracle",
|
|
385
432
|
"type": "database",
|
|
386
433
|
"style": "factory",
|
|
387
|
-
"position": {"x": -
|
|
388
|
-
"cwd": "/home/riven/d/tide-commander",
|
|
389
|
-
"commands": {},
|
|
434
|
+
"position": {"x": -7, "z": -0.34},
|
|
390
435
|
"database": {
|
|
391
436
|
"connections": [{
|
|
392
|
-
"id": "
|
|
393
|
-
"name": "
|
|
437
|
+
"id": "conn_ora_dev",
|
|
438
|
+
"name": "Dev",
|
|
394
439
|
"engine": "oracle",
|
|
395
440
|
"host": "127.0.0.1",
|
|
396
441
|
"port": 1521,
|
|
397
|
-
"username": "
|
|
398
|
-
"password": "
|
|
442
|
+
"username": "APP_USER",
|
|
443
|
+
"password": "secret",
|
|
399
444
|
"database": "ORCLPDB1"
|
|
400
|
-
}]
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
"id": "building_1769624489000_oracle",
|
|
404
|
-
"status": "stopped",
|
|
405
|
-
"createdAt": 1769624489000
|
|
406
|
-
}]' ~/.local/share/tide-commander/buildings.json > /tmp/b.json && mv /tmp/b.json ~/.local/share/tide-commander/buildings.json
|
|
445
|
+
}]
|
|
446
|
+
}
|
|
447
|
+
}'
|
|
407
448
|
${BT3}
|
|
408
449
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
-
|
|
450
|
+
### Database — SQLite
|
|
451
|
+
|
|
452
|
+
${BT3}bash
|
|
453
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
454
|
+
-H "Content-Type: application/json" -d '{
|
|
455
|
+
"name": "Local Cache",
|
|
456
|
+
"type": "database",
|
|
457
|
+
"position": {"x": -6, "z": -0.34},
|
|
458
|
+
"database": {
|
|
459
|
+
"connections": [{
|
|
460
|
+
"id": "conn_sqlite",
|
|
461
|
+
"name": "cache.db",
|
|
462
|
+
"engine": "sqlite",
|
|
463
|
+
"filepath": "/home/user/projects/app/cache.db"
|
|
464
|
+
}]
|
|
465
|
+
}
|
|
466
|
+
}'
|
|
467
|
+
${BT3}
|
|
413
468
|
|
|
414
|
-
###
|
|
469
|
+
### Database — with SSH tunnel
|
|
415
470
|
|
|
416
471
|
${BT3}bash
|
|
417
|
-
|
|
472
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
473
|
+
-H "Content-Type: application/json" -d '{
|
|
474
|
+
"name": "Prod MySQL via Bastion",
|
|
475
|
+
"type": "database",
|
|
476
|
+
"position": {"x": -5, "z": -0.34},
|
|
477
|
+
"database": {
|
|
478
|
+
"connections": [{
|
|
479
|
+
"id": "conn_prod_via_ssh",
|
|
480
|
+
"name": "Prod",
|
|
481
|
+
"engine": "mysql",
|
|
482
|
+
"host": "10.0.0.5",
|
|
483
|
+
"port": 3306,
|
|
484
|
+
"username": "appuser",
|
|
485
|
+
"password": "secret",
|
|
486
|
+
"ssh": {
|
|
487
|
+
"enabled": true,
|
|
488
|
+
"host": "bastion.example.com",
|
|
489
|
+
"port": 22,
|
|
490
|
+
"username": "ops",
|
|
491
|
+
"authMethod": "privateKey",
|
|
492
|
+
"privateKeyPath": "/home/user/.ssh/bastion_ed25519"
|
|
493
|
+
}
|
|
494
|
+
}]
|
|
495
|
+
}
|
|
496
|
+
}'
|
|
497
|
+
${BT3}
|
|
498
|
+
|
|
499
|
+
The ${BT}host${BT}/${BT}port${BT} are as seen *from the SSH server*. The server allocates a
|
|
500
|
+
local forwarded port automatically unless you set ${BT}ssh.localPort${BT}.
|
|
501
|
+
|
|
502
|
+
### Terminal (ttyd web shell)
|
|
503
|
+
|
|
504
|
+
${BT3}bash
|
|
505
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
506
|
+
-H "Content-Type: application/json" -d '{
|
|
418
507
|
"name": "Dev Terminal",
|
|
419
508
|
"type": "terminal",
|
|
420
509
|
"style": "desktop",
|
|
421
510
|
"color": "#a855f7",
|
|
422
|
-
"position": {"x": -8
|
|
423
|
-
"cwd": "/home/
|
|
424
|
-
"terminal": {
|
|
425
|
-
|
|
426
|
-
"shell": "/bin/zsh",
|
|
427
|
-
"saveSession": true
|
|
428
|
-
},
|
|
429
|
-
"id": "building_1707471234569_devterm",
|
|
430
|
-
"status": "stopped",
|
|
431
|
-
"createdAt": 1707471234569
|
|
432
|
-
}]' ~/.local/share/tide-commander/buildings.json > /tmp/b.json && mv /tmp/b.json ~/.local/share/tide-commander/buildings.json
|
|
511
|
+
"position": {"x": -8, "z": 1.5},
|
|
512
|
+
"cwd": "/home/user/projects/my-project",
|
|
513
|
+
"terminal": { "enabled": true, "shell": "/bin/zsh", "saveSession": true }
|
|
514
|
+
}'
|
|
433
515
|
${BT3}
|
|
434
516
|
|
|
435
|
-
|
|
517
|
+
Requires ${BT}ttyd${BT} installed; ${BT}saveSession: true${BT} also needs ${BT}tmux${BT}.
|
|
436
518
|
|
|
437
|
-
|
|
519
|
+
### Folder shortcut
|
|
438
520
|
|
|
439
521
|
${BT3}bash
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
522
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
523
|
+
-H "Content-Type: application/json" -d '{
|
|
524
|
+
"name": "Projects",
|
|
525
|
+
"type": "folder",
|
|
526
|
+
"style": "filing-cabinet",
|
|
527
|
+
"position": {"x": 8, "z": -2},
|
|
528
|
+
"folderPath": "/home/user/projects"
|
|
529
|
+
}'
|
|
448
530
|
${BT3}
|
|
449
531
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
### Symfony (PHP Framework)
|
|
453
|
-
|
|
454
|
-
**Requirements:**
|
|
455
|
-
- Symfony CLI must be installed and in PATH
|
|
456
|
-
- Use "server:start" command (Symfony local web server)
|
|
532
|
+
### Link shortcut
|
|
457
533
|
|
|
458
|
-
**Configuration:**
|
|
459
534
|
${BT3}bash
|
|
460
|
-
"
|
|
461
|
-
"
|
|
462
|
-
"
|
|
463
|
-
"
|
|
464
|
-
"
|
|
465
|
-
}
|
|
535
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
536
|
+
-H "Content-Type: application/json" -d '{
|
|
537
|
+
"name": "Docs",
|
|
538
|
+
"type": "link",
|
|
539
|
+
"style": "tower",
|
|
540
|
+
"position": {"x": 10, "z": 0},
|
|
541
|
+
"urls": [{"label": "Internal Wiki", "url": "https://wiki.example.com"}]
|
|
542
|
+
}'
|
|
466
543
|
${BT3}
|
|
467
544
|
|
|
468
|
-
|
|
469
|
-
- server:start: Start the Symfony local web server (runs in foreground - required for PM2)
|
|
470
|
-
- --allow-http: Allow HTTP (remove for production/HTTPS)
|
|
471
|
-
- --no-tls: Disable TLS certificate generation
|
|
472
|
-
- --port=XXXX: Listening port
|
|
473
|
-
- **NEVER use --daemon**: This forks the process and PM2 loses track of it
|
|
474
|
-
- Extra ports: Symfony opens additional monitoring ports (e.g., 42421)
|
|
475
|
-
- Auto-detects port from startup logs
|
|
545
|
+
### Monitor
|
|
476
546
|
|
|
477
|
-
**Debugging Symfony with PM2:**
|
|
478
547
|
${BT3}bash
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
548
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
549
|
+
-H "Content-Type: application/json" -d '{
|
|
550
|
+
"name": "Host Metrics",
|
|
551
|
+
"type": "monitor",
|
|
552
|
+
"style": "satellite",
|
|
553
|
+
"position": {"x": 12, "z": 4}
|
|
554
|
+
}'
|
|
555
|
+
${BT3}
|
|
484
556
|
|
|
485
|
-
|
|
486
|
-
cd /path/to/symfony/project && symfony server:stop
|
|
557
|
+
### Boss building
|
|
487
558
|
|
|
488
|
-
|
|
489
|
-
cd /path/to/symfony/project && symfony server:start --allow-http --port=7200
|
|
559
|
+
Subordinates must already exist. Get their IDs from a ${BT}GET /api/buildings${BT} list first.
|
|
490
560
|
|
|
491
|
-
|
|
492
|
-
|
|
561
|
+
${BT3}bash
|
|
562
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings \\
|
|
563
|
+
-H "Content-Type: application/json" -d '{
|
|
564
|
+
"name": "Navi",
|
|
565
|
+
"type": "boss",
|
|
566
|
+
"style": "command-center",
|
|
567
|
+
"position": {"x": 11.36, "z": -9.77},
|
|
568
|
+
"subordinateBuildingIds": ["building_..._navi_back", "building_..._navi_front"]
|
|
569
|
+
}'
|
|
493
570
|
${BT3}
|
|
494
571
|
|
|
495
|
-
|
|
572
|
+
To change the subordinate list later:
|
|
496
573
|
|
|
497
|
-
**Requirements:**
|
|
498
|
-
- PHP installed and in PATH
|
|
499
|
-
- No extra tools needed
|
|
500
|
-
|
|
501
|
-
**Configuration:**
|
|
502
574
|
${BT3}bash
|
|
503
|
-
"
|
|
504
|
-
|
|
505
|
-
"
|
|
506
|
-
"
|
|
507
|
-
"interpreter": "none"
|
|
508
|
-
}
|
|
575
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" \\
|
|
576
|
+
http://localhost:5174/api/buildings/<boss-id>/subordinates \\
|
|
577
|
+
-H "Content-Type: application/json" \\
|
|
578
|
+
-d '{"subordinateBuildingIds": ["<id1>", "<id2>"]}'
|
|
509
579
|
${BT3}
|
|
510
580
|
|
|
511
|
-
|
|
512
|
-
- -S address:port: Bind server to address and port
|
|
513
|
-
- 0.0.0.0: Listen on all interfaces (accessible from network)
|
|
514
|
-
- localhost: Only accessible locally
|
|
515
|
-
- -t docroot: Document root (where index.php is)
|
|
516
|
-
|
|
517
|
-
**Ideal for:**
|
|
518
|
-
- Laravel projects (document root: "public")
|
|
519
|
-
- Custom PHP apps
|
|
520
|
-
- Quick prototypes
|
|
521
|
-
- Development only (not production-grade)
|
|
522
|
-
|
|
523
|
-
## Lessons Learned from Real Deployments
|
|
524
|
-
|
|
525
|
-
### Symfony Server with PM2
|
|
526
|
-
- **Problem**: Symfony server with ${BT}--daemon${BT} forks to background and exits immediately. PM2 sees the parent exit and marks the process as "errored" or "stopped"
|
|
527
|
-
- **Solution**: Do NOT use ${BT}--daemon${BT} flag. PM2 must be the process manager, so Symfony must run in foreground: ${BT}server:start --allow-http --port=7200${BT}
|
|
528
|
-
- **Debugging**: If PM2 shows "errored" with "already running" in logs, a Symfony daemon is running outside PM2. Stop it first: ${BT}cd /project/dir && symfony server:stop${BT}, then restart via PM2
|
|
529
|
-
- **Port Monitoring**: Opens main port + monitor port (e.g., 7205 + 42421)
|
|
530
|
-
|
|
531
|
-
### Vite Configuration for Environment Variables
|
|
532
|
-
- **Problem**: PORT env var set in PM2 but Vite ignores it (uses hardcoded port)
|
|
533
|
-
- **Solution**: Update vite.config.mjs to read PORT from process.env:
|
|
534
|
-
- ${BT3}javascript
|
|
535
|
-
- server: {
|
|
536
|
-
- port: parseInt(process.env.PORT || "6205", 10),
|
|
537
|
-
- open: false,
|
|
538
|
-
- host: true,
|
|
539
|
-
- }
|
|
540
|
-
- ${BT3}
|
|
541
|
-
- **Verification**: ${BT}ss -tlnp | grep PORT_NUMBER${BT} shows process listening
|
|
542
|
-
- **Tip**: Set ${BT}open: false${BT} to prevent browser pop-ups in headless environments
|
|
543
|
-
|
|
544
|
-
### Binary Corruption Issues
|
|
545
|
-
- **Problem**: Bun binary shows "cannot execute binary file" errors
|
|
546
|
-
- **Solution**: Reinstall with ${BT}curl -fsSL https://bun.sh/install | bash${BT}
|
|
547
|
-
- **Verification**: ${BT}bun --version${BT} returns version number
|
|
548
|
-
|
|
549
|
-
## PM2 Configuration Rules
|
|
550
|
-
|
|
551
|
-
1. **Always use PM2 mode** for server buildings (pm2.enabled: true)
|
|
552
|
-
2. **Script paths**:
|
|
553
|
-
- Full path for binaries not in PATH: /home/riven/.bun/bin/bun
|
|
554
|
-
- Short name for PATH tools: symfony, php, mvn, node, bun
|
|
555
|
-
- Relative path for project scripts: ./bin/activemq
|
|
556
|
-
3. **Interpreter values**:
|
|
557
|
-
- "none": Direct binary execution (most common - php, mvn, symfony, bun)
|
|
558
|
-
- "bash": Shell scripts needing interpretation
|
|
559
|
-
- "node": Explicitly running a .js file
|
|
560
|
-
4. **Port strategy**:
|
|
561
|
-
- Vite/Node apps: set via env var (PORT)
|
|
562
|
-
- PHP/Symfony/Java: set via args (--port=XXXX or -S ADDR:PORT)
|
|
563
|
-
- PM2 auto-detects ports from console output
|
|
564
|
-
5. **Special cases**:
|
|
565
|
-
- Symfony: Do NOT use --daemon (PM2 needs foreground process)
|
|
566
|
-
- Vite: Update vite.config.mjs to read PORT env var
|
|
567
|
-
- Full bun path: Use /home/riven/.bun/bin/bun (not just "bun")
|
|
568
|
-
|
|
569
|
-
## Important Notes
|
|
570
|
-
|
|
571
|
-
- File: ~/.local/share/tide-commander/buildings.json
|
|
572
|
-
- IDs must be unique: building_<timestamp>_<name>
|
|
573
|
-
- Scale: 0.5 (small), 0.75 (normal), 1.0 (large)
|
|
574
|
-
- Always validate JSON after modifications
|
|
575
|
-
- Refresh Tide Commander UI to see new buildings
|
|
576
|
-
- Check "pm2 list" to verify building started correctly
|
|
577
|
-
- Position buildings inside their designated area (check areas.json for coordinates)
|
|
578
|
-
|
|
579
|
-
---
|
|
580
|
-
|
|
581
|
-
## Area Management
|
|
582
|
-
|
|
583
|
-
Areas are project zones on the battlefield that group agents and buildings. File: ~/.local/share/tide-commander/areas.json
|
|
584
|
-
|
|
585
|
-
### Area Schema (DrawingArea)
|
|
586
|
-
|
|
587
|
-
**CRITICAL: Follow this schema exactly. Incorrect fields will crash the application.**
|
|
581
|
+
## Step 4: Control buildings
|
|
588
582
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
"
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
"
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
583
|
+
### Start / stop / restart
|
|
584
|
+
|
|
585
|
+
${BT3}bash
|
|
586
|
+
# Start a single building
|
|
587
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" \\
|
|
588
|
+
http://localhost:5174/api/buildings/<id>/command \\
|
|
589
|
+
-H "Content-Type: application/json" -d '{"command":"start"}'
|
|
590
|
+
|
|
591
|
+
# Stop
|
|
592
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" \\
|
|
593
|
+
http://localhost:5174/api/buildings/<id>/command \\
|
|
594
|
+
-H "Content-Type: application/json" -d '{"command":"stop"}'
|
|
595
|
+
|
|
596
|
+
# Restart
|
|
597
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" \\
|
|
598
|
+
http://localhost:5174/api/buildings/<id>/command \\
|
|
599
|
+
-H "Content-Type: application/json" -d '{"command":"restart"}'
|
|
604
600
|
${BT3}
|
|
605
601
|
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
- Do NOT use ${BT}"depth"${BT} — use ${BT}"height"${BT}
|
|
609
|
-
- Do NOT omit ${BT}"type"${BT} — always specify ${BT}"rectangle"${BT} or ${BT}"circle"${BT}
|
|
602
|
+
Response: ${BT}{"success": true|false, "error?": "..."}${BT}. Status updates broadcast to
|
|
603
|
+
the UI separately — the response only confirms the command was dispatched.
|
|
610
604
|
|
|
611
|
-
###
|
|
605
|
+
### Health check
|
|
612
606
|
|
|
613
607
|
${BT3}bash
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
"
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
"directories": []
|
|
625
|
-
}]' ~/.local/share/tide-commander/areas.json > /tmp/a.json && mv /tmp/a.json ~/.local/share/tide-commander/areas.json
|
|
626
|
-
${BT3}
|
|
627
|
-
|
|
628
|
-
### Create a Circle Area
|
|
608
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" \\
|
|
609
|
+
http://localhost:5174/api/buildings/<id>/command \\
|
|
610
|
+
-H "Content-Type: application/json" -d '{"command":"healthCheck"}'
|
|
611
|
+
${BT3}
|
|
612
|
+
|
|
613
|
+
For PM2 buildings this checks the process is ${BT}online${BT}. For Docker buildings it
|
|
614
|
+
checks ${BT}status === 'running'${BT} and health check passing. For custom-command
|
|
615
|
+
buildings it runs ${BT}commands.healthCheck${BT}.
|
|
616
|
+
|
|
617
|
+
### Refresh status without running a command
|
|
629
618
|
|
|
630
619
|
${BT3}bash
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
"type": "circle",
|
|
635
|
-
"center": {"x": 10, "z": -5},
|
|
636
|
-
"radius": 6,
|
|
637
|
-
"color": "#d94a4a",
|
|
638
|
-
"zIndex": 0,
|
|
639
|
-
"assignedAgentIds": [],
|
|
640
|
-
"directories": []
|
|
641
|
-
}]' ~/.local/share/tide-commander/areas.json > /tmp/a.json && mv /tmp/a.json ~/.local/share/tide-commander/areas.json
|
|
620
|
+
# Pulls the latest PM2/Docker/Terminal status now, updates the building, broadcasts
|
|
621
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" \\
|
|
622
|
+
http://localhost:5174/api/buildings/<id>/sync-status
|
|
642
623
|
${BT3}
|
|
643
624
|
|
|
644
|
-
###
|
|
625
|
+
### Boss controls (start_all / stop_all / restart_all)
|
|
645
626
|
|
|
646
627
|
${BT3}bash
|
|
647
|
-
|
|
628
|
+
curl -s -X POST -H "X-Auth-Token: <TOKEN>" \\
|
|
629
|
+
http://localhost:5174/api/buildings/boss/<boss-id>/command \\
|
|
630
|
+
-H "Content-Type: application/json" -d '{"command":"start_all"}'
|
|
648
631
|
${BT3}
|
|
649
632
|
|
|
650
|
-
|
|
633
|
+
## Step 5: Inspect logs
|
|
651
634
|
|
|
652
635
|
${BT3}bash
|
|
653
|
-
|
|
636
|
+
# Snapshot the last 200 lines (default), works for PM2, Docker, and custom-command buildings
|
|
637
|
+
curl -s -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings/<id>/logs
|
|
638
|
+
|
|
639
|
+
# Last N lines (capped at 5000)
|
|
640
|
+
curl -s -H "X-Auth-Token: <TOKEN>" "http://localhost:5174/api/buildings/<id>/logs?lines=500"
|
|
641
|
+
|
|
642
|
+
# Compose-specific service
|
|
643
|
+
curl -s -H "X-Auth-Token: <TOKEN>" \\
|
|
644
|
+
"http://localhost:5174/api/buildings/<id>/logs?lines=200&service=web"
|
|
654
645
|
${BT3}
|
|
655
646
|
|
|
656
|
-
|
|
647
|
+
Response: ${BT}{"source": "pm2"|"docker"|"custom"|"none", "logs": "...", "lines": N}${BT}.
|
|
648
|
+
|
|
649
|
+
Live tail-following is **not** exposed over REST — the UI uses WebSocket
|
|
650
|
+
streaming for that. Use the snapshot endpoint for debugging.
|
|
651
|
+
|
|
652
|
+
## Step 6: Update or delete
|
|
657
653
|
|
|
658
654
|
${BT3}bash
|
|
659
|
-
|
|
655
|
+
# Partial update — only send the fields that change
|
|
656
|
+
curl -s -X PATCH -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings/<id> \\
|
|
657
|
+
-H "Content-Type: application/json" -d '{"position": {"x": 5.0, "z": -2.5}}'
|
|
658
|
+
|
|
659
|
+
# Change a PM2 env var (the server will restart the process if it was running)
|
|
660
|
+
curl -s -X PATCH -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings/<id> \\
|
|
661
|
+
-H "Content-Type: application/json" \\
|
|
662
|
+
-d '{"pm2": {"enabled": true, "script": "bun", "args": "run dev", "env": {"PORT": "6206"}}}'
|
|
663
|
+
|
|
664
|
+
# Delete (default: tears down PM2 process, Docker container, terminal, DB tunnel)
|
|
665
|
+
curl -s -X DELETE -H "X-Auth-Token: <TOKEN>" http://localhost:5174/api/buildings/<id>
|
|
666
|
+
|
|
667
|
+
# Delete record only, leave runtime artefacts (e.g. when adopting elsewhere)
|
|
668
|
+
curl -s -X DELETE -H "X-Auth-Token: <TOKEN>" \\
|
|
669
|
+
"http://localhost:5174/api/buildings/<id>?cleanup=false"
|
|
660
670
|
${BT3}
|
|
661
671
|
|
|
662
|
-
|
|
672
|
+
PATCH triggers reconciliation: if you change ${BT}pm2.script${BT}, ${BT}pm2.args${BT},
|
|
673
|
+
${BT}pm2.env${BT}, ${BT}cwd${BT}, or anything the PM2 process name derives from, the running
|
|
674
|
+
process is removed and restarted (if it was online). Docker container changes
|
|
675
|
+
behave the same way. DB tunnel SSH/host/port changes close the tunnel.
|
|
663
676
|
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
677
|
+
## Validation
|
|
678
|
+
|
|
679
|
+
Validation errors come back as ${BT}400${BT} with a list:
|
|
680
|
+
|
|
681
|
+
${BT3}json
|
|
682
|
+
{
|
|
683
|
+
"error": "Validation failed",
|
|
684
|
+
"errors": [
|
|
685
|
+
"pm2.script is required when pm2.enabled is true",
|
|
686
|
+
"position is required ({x: number, z: number})"
|
|
687
|
+
]
|
|
688
|
+
}
|
|
667
689
|
${BT3}
|
|
690
|
+
|
|
691
|
+
Cross-building checks (e.g. dangling ${BT}subordinateBuildingIds${BT}) also fail at 400.
|
|
692
|
+
|
|
693
|
+
## Conventions and tips
|
|
694
|
+
|
|
695
|
+
- **IDs** are server-assigned: ${BT}building_<timestamp>_<name-slug>${BT}. Don't pass them on POST.
|
|
696
|
+
- **${BT}status${BT}** is also server-managed — agents don't set it. Use the command
|
|
697
|
+
endpoint to change runtime state.
|
|
698
|
+
- **${BT}scale${BT}** is a free number; typical values 0.5 / 0.75 / 1.0 are guidance, not a constraint.
|
|
699
|
+
- **Position** should fall inside the building's intended area. Inspect zones
|
|
700
|
+
with ${BT}curl /api/areas | jq '.[] | {id, name, center, width, height, radius}'${BT}.
|
|
701
|
+
- **Credentials** (DB passwords, SSH keys) are encrypted at rest. Send plaintext
|
|
702
|
+
in the body; GET responses return ${BT}hasPassword: true${BT} flags instead of the value.
|
|
703
|
+
- **${BT}buildings.json${BT}** is server-owned. Reading it directly is fine; writing it
|
|
704
|
+
is not — your edits will be overwritten by the next client sync.
|
|
668
705
|
`,
|
|
669
706
|
};
|