Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
623 lines (580 loc) · 27.8 KB
/
Copy pathMakefile
File metadata and controls
623 lines (580 loc) · 27.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
# Makefile for Whisperer watchOS App
# Configuration
PROJECT_NAME = Whisperer
SCHEME = Whisperer
CONFIGURATION = Debug
WATCH_SIMULATOR_NAME = Apple Watch Series 11 (46mm)
WATCH_SE_SIMULATOR_NAME = Apple Watch SE 3 (44mm)
WATCH_SERIES11_SIMULATOR_NAME = Apple Watch Series 11 (46mm)
WATCH_SE3_SIMULATOR_NAME = Apple Watch SE 3 (44mm)
BUNDLE_ID = com.aspauldingcode.whisperer.watchkitapp
.PHONY: build install run debug logs filter-logs clean list-simulators deploy deploy-nix \
vercel-env-ls vercel-env-sync vercel-avatar setup help \
build-se install-se run-se debug-se \
build-s11 install-s11 run-s11 debug-s11 \
build-se3 install-se3 run-se3 debug-se3 \
logs-se logs-s11 logs-se3 \
wipe-simulators test test-api dogfood-watch dogfood-companion deploy-watch-device
# Default target
all: build
# Setup development environment (install Xcode, watchOS SDK, and SwiftLint)
setup:
@echo " Setting up development environment for watchOS..."
@echo "Checking for Homebrew installation..."
@if ! command -v brew >/dev/null 2>&1; then \
echo " Homebrew not found. Installing Homebrew..."; \
/bin/bash -c "$$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"; \
echo " Homebrew installed"; \
else \
echo " Homebrew is installed"; \
fi
@echo "Checking for SwiftLint installation..."
@if ! command -v swiftlint >/dev/null 2>&1; then \
echo " SwiftLint not found. Installing SwiftLint..."; \
brew install swiftlint; \
echo " SwiftLint installed"; \
else \
echo " SwiftLint is installed"; \
SWIFTLINT_VERSION=$$(swiftlint version); \
echo " SwiftLint version: $$SWIFTLINT_VERSION"; \
fi
@echo "Checking for Xcode installation..."
@if ! command -v xcodebuild >/dev/null 2>&1; then \
echo " Xcode not found. Installing Xcode..."; \
echo " Opening Mac App Store to install Xcode..."; \
open "macappstore://itunes.apple.com/app/xcode/id497799835"; \
echo " Please install Xcode from the App Store and run 'make setup' again."; \
exit 1; \
else \
echo " Xcode is installed"; \
fi
@echo "Checking for watchOS SDK..."
@if ! xcrun --sdk watchos --show-sdk-path >/dev/null 2>&1; then \
echo " watchOS SDK not found. Installing watchOS SDK..."; \
echo " Running xcode-select to ensure command line tools are set up..."; \
sudo xcode-select --install 2>/dev/null || true; \
echo " Installing watchOS SDK and Simulator..."; \
echo " This may take several minutes..."; \
xcodebuild -downloadPlatform watchOS || { \
echo " Automatic installation failed. Trying alternative method..."; \
echo " Opening Xcode to install additional components..."; \
open -a Xcode; \
echo " In Xcode, go to Settings > Platforms and install watchOS"; \
echo " After installation, run 'make setup' again to verify."; \
exit 1; \
}; \
echo " watchOS SDK installation completed"; \
else \
echo " watchOS SDK is available"; \
WATCHOS_SDK_VERSION=$$(xcrun --sdk watchos --show-sdk-version); \
echo " watchOS SDK version: $$WATCHOS_SDK_VERSION"; \
fi
@echo "Checking for Watch Simulator..."
@if ! xcrun simctl list devices watchOS | grep -q "Apple Watch"; then \
echo " Watch Simulator not found. Installing Watch Simulator..."; \
echo " Installing watchOS Simulator runtime..."; \
xcodebuild -downloadPlatform watchsimulator || { \
echo " Automatic simulator installation failed."; \
echo " Opening Xcode to install simulator manually..."; \
open -a Xcode; \
echo " In Xcode, go to Settings > Platforms and install watchOS Simulator"; \
echo " After installation, run 'make setup' again to verify."; \
exit 1; \
}; \
echo " Watch Simulator installation completed"; \
else \
echo " Watch Simulator is available"; \
fi
@echo "Verifying simulator availability..."
@WATCH_DEVICE_ID=$$(xcrun simctl list devices | grep "$(WATCH_SIMULATOR_NAME)" | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | head -1); \
if [ -z "$$WATCH_DEVICE_ID" ]; then \
echo " Preferred simulator '$(WATCH_SIMULATOR_NAME)' not found."; \
echo " Available Watch simulators:"; \
xcrun simctl list devices watchOS | grep -E "(Apple Watch|Booted|Shutdown)"; \
echo " You can change WATCH_SIMULATOR_NAME in the Makefile to match an available simulator."; \
else \
echo " Target simulator '$(WATCH_SIMULATOR_NAME)' is available"; \
fi
@echo " Development environment setup complete!"
@echo " You can now run 'make build' or 'make run' to build and test your app."
# Build the project
build:
@echo "Building Whisperer watchOS app..."
xcodebuild -project $(PROJECT_NAME).xcodeproj \
-scheme $(SCHEME) \
-configuration $(CONFIGURATION) \
-destination 'platform=watchOS Simulator,name=$(WATCH_SIMULATOR_NAME)' \
build
# Build for Apple Watch SE
build-se:
@echo "Building Whisperer watchOS app for Apple Watch SE..."
xcodebuild -project $(PROJECT_NAME).xcodeproj \
-scheme $(SCHEME) \
-configuration $(CONFIGURATION) \
-destination 'platform=watchOS Simulator,name=$(WATCH_SE_SIMULATOR_NAME)' \
build
# Build for Apple Watch SE 3
build-se3:
@echo "Building Whisperer watchOS app for Apple Watch SE 3..."
xcodebuild -project $(PROJECT_NAME).xcodeproj \
-scheme $(SCHEME) \
-configuration $(CONFIGURATION) \
-destination 'platform=watchOS Simulator,name=$(WATCH_SE3_SIMULATOR_NAME)' \
build
# Build for Apple Watch Series 11
build-s11:
@echo "Building Whisperer watchOS app for Apple Watch Series 11..."
xcodebuild -project $(PROJECT_NAME).xcodeproj \
-scheme $(SCHEME) \
-configuration $(CONFIGURATION) \
-destination 'platform=watchOS Simulator,name=$(WATCH_SERIES11_SIMULATOR_NAME)' \
build
# Install app on simulator
install: build
@echo "Installing Whisperer on Watch Simulator..."
@APP_PATH=$$(find ~/Library/Developer/Xcode/DerivedData -name "Whisperer.app" -path "*/Build/Products/Debug-watchsimulator/*" -not -path "*/Index.noindex/*" -type d 2>/dev/null | head -1); \
if [ -z "$$APP_PATH" ]; then \
echo "Error: Could not find built Whisperer.app"; \
exit 1; \
fi; \
echo "Found app at: $$APP_PATH"; \
WATCH_DEVICE_ID=$$(xcrun simctl list devices | grep "$(WATCH_SIMULATOR_NAME)" | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | head -1); \
if [ -z "$$WATCH_DEVICE_ID" ]; then \
echo "Error: Could not find Watch simulator device ID for $(WATCH_SIMULATOR_NAME)"; \
exit 1; \
fi; \
echo "Using Watch simulator: $$WATCH_DEVICE_ID"; \
xcrun simctl boot "$$WATCH_DEVICE_ID" 2>/dev/null || true; \
xcrun simctl install "$$WATCH_DEVICE_ID" "$$APP_PATH"
# Install app on Apple Watch SE simulator
install-se: build-se
@echo "Installing Whisperer on Apple Watch SE Simulator..."
@APP_PATH=$$(find ~/Library/Developer/Xcode/DerivedData -name "Whisperer.app" -path "*/Build/Products/Debug-watchsimulator/*" -not -path "*/Index.noindex/*" -type d 2>/dev/null | head -1); \
if [ -z "$$APP_PATH" ]; then \
echo "Error: Could not find built Whisperer.app"; \
exit 1; \
fi; \
echo "Found app at: $$APP_PATH"; \
WATCH_DEVICE_ID=$$(xcrun simctl list devices | grep "$(WATCH_SE_SIMULATOR_NAME)" | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | head -1); \
if [ -z "$$WATCH_DEVICE_ID" ]; then \
echo "Error: Could not find Watch simulator device ID for $(WATCH_SE_SIMULATOR_NAME)"; \
exit 1; \
fi; \
echo "Using Apple Watch SE simulator: $$WATCH_DEVICE_ID"; \
xcrun simctl boot "$$WATCH_DEVICE_ID" 2>/dev/null || true; \
xcrun simctl install "$$WATCH_DEVICE_ID" "$$APP_PATH"
# Install app on Apple Watch SE 3 simulator
install-se3: build-se3
@echo "Installing Whisperer on Apple Watch SE 3 Simulator..."
@APP_PATH=$$(find ~/Library/Developer/Xcode/DerivedData -name "Whisperer.app" -path "*/Build/Products/Debug-watchsimulator/*" -not -path "*/Index.noindex/*" -type d 2>/dev/null | head -1); \
if [ -z "$$APP_PATH" ]; then \
echo "Error: Could not find built Whisperer.app"; \
exit 1; \
fi; \
echo "Found app at: $$APP_PATH"; \
WATCH_DEVICE_ID=$$(xcrun simctl list devices | grep "$(WATCH_SE3_SIMULATOR_NAME)" | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | head -1); \
if [ -z "$$WATCH_DEVICE_ID" ]; then \
echo "Error: Could not find Watch simulator device ID for $(WATCH_SE3_SIMULATOR_NAME)"; \
exit 1; \
fi; \
echo "Using Apple Watch SE 3 simulator: $$WATCH_DEVICE_ID"; \
xcrun simctl boot "$$WATCH_DEVICE_ID" 2>/dev/null || true; \
xcrun simctl install "$$WATCH_DEVICE_ID" "$$APP_PATH"
# Install app on Apple Watch Series 11 simulator
install-s11: build-s11
@echo "Installing Whisperer on Apple Watch Series 11 Simulator..."
@APP_PATH=$$(find ~/Library/Developer/Xcode/DerivedData -name "Whisperer.app" -path "*/Build/Products/Debug-watchsimulator/*" -not -path "*/Index.noindex/*" -type d 2>/dev/null | head -1); \
if [ -z "$$APP_PATH" ]; then \
echo "Error: Could not find built Whisperer.app"; \
exit 1; \
fi; \
echo "Found app at: $$APP_PATH"; \
WATCH_DEVICE_ID=$$(xcrun simctl list devices | grep "$(WATCH_SERIES11_SIMULATOR_NAME)" | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | head -1); \
if [ -z "$$WATCH_DEVICE_ID" ]; then \
echo "Error: Could not find Watch simulator device ID for $(WATCH_SERIES11_SIMULATOR_NAME)"; \
exit 1; \
fi; \
echo "Using Apple Watch Series 11 simulator: $$WATCH_DEVICE_ID"; \
xcrun simctl boot "$$WATCH_DEVICE_ID" 2>/dev/null || true; \
xcrun simctl install "$$WATCH_DEVICE_ID" "$$APP_PATH"
# Run app on simulator (install + launch + open simulator)
run: install
@echo " Launching Whisperer on Watch Simulator..."
@if ! pgrep -f "Simulator" > /dev/null; then \
echo " Opening Simulator application..."; \
open -a Simulator; \
sleep 5; \
fi; \
WATCH_DEVICE_ID=$$(xcrun simctl list devices | grep "$(WATCH_SIMULATOR_NAME)" | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | head -1); \
if [ -z "$$WATCH_DEVICE_ID" ]; then \
echo " Error: Could not find Watch simulator device ID for $(WATCH_SIMULATOR_NAME)"; \
exit 1; \
else \
echo " Using Watch simulator: $$WATCH_DEVICE_ID"; \
xcrun simctl boot "$$WATCH_DEVICE_ID" 2>/dev/null || true; \
echo " App installed. Attempting to launch..."; \
if ! xcrun simctl launch "$$WATCH_DEVICE_ID" $(BUNDLE_ID); then \
echo " Auto-launch failed. This is common for watchOS."; \
echo " Please open the app manually in the Simulator."; \
fi; \
fi
# Run app on Apple Watch SE simulator
run-se: install-se
@echo " Launching Whisperer on Apple Watch SE Simulator..."
@if ! pgrep -f "Simulator" > /dev/null; then \
echo " Opening Simulator application..."; \
open -a Simulator; \
sleep 5; \
fi; \
WATCH_DEVICE_ID=$$(xcrun simctl list devices | grep "$(WATCH_SE_SIMULATOR_NAME)" | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | head -1); \
if [ -z "$$WATCH_DEVICE_ID" ]; then \
echo " Error: Could not find Watch simulator device ID for $(WATCH_SE_SIMULATOR_NAME)"; \
exit 1; \
else \
echo " Using Apple Watch SE simulator: $$WATCH_DEVICE_ID"; \
xcrun simctl boot "$$WATCH_DEVICE_ID" 2>/dev/null || true; \
echo " App installed. Attempting to launch..."; \
if ! xcrun simctl launch "$$WATCH_DEVICE_ID" $(BUNDLE_ID); then \
echo " Auto-launch failed. This is common for watchOS."; \
echo " Please open the app manually in the Simulator."; \
fi; \
fi
# Run app on Apple Watch SE 3 simulator
run-se3: install-se3
@echo " Launching Whisperer on Apple Watch SE 3 Simulator..."
@if ! pgrep -f "Simulator" > /dev/null; then \
echo " Opening Simulator application..."; \
open -a Simulator; \
sleep 5; \
fi; \
WATCH_DEVICE_ID=$$(xcrun simctl list devices | grep "$(WATCH_SE3_SIMULATOR_NAME)" | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | head -1); \
if [ -z "$$WATCH_DEVICE_ID" ]; then \
echo " Error: Could not find Watch simulator device ID for $(WATCH_SE3_SIMULATOR_NAME)"; \
exit 1; \
else \
echo " Using Apple Watch SE 3 simulator: $$WATCH_DEVICE_ID"; \
xcrun simctl boot "$$WATCH_DEVICE_ID" 2>/dev/null || true; \
echo " App installed. Attempting to launch..."; \
if ! xcrun simctl launch "$$WATCH_DEVICE_ID" $(BUNDLE_ID); then \
echo " Auto-launch failed. This is common for watchOS."; \
echo " Please open the app manually in the Simulator."; \
fi; \
fi
# Run app on Apple Watch Series 11 simulator
run-s11: install-s11
@echo " Launching Whisperer on Apple Watch Series 11 Simulator..."
@if ! pgrep -f "Simulator" > /dev/null; then \
echo " Opening Simulator application..."; \
open -a Simulator; \
sleep 5; \
fi; \
WATCH_DEVICE_ID=$$(xcrun simctl list devices | grep "$(WATCH_SERIES11_SIMULATOR_NAME)" | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | head -1); \
if [ -z "$$WATCH_DEVICE_ID" ]; then \
echo " Error: Could not find Watch simulator device ID for $(WATCH_SERIES11_SIMULATOR_NAME)"; \
exit 1; \
else \
echo " Using Apple Watch Series 11 simulator: $$WATCH_DEVICE_ID"; \
xcrun simctl boot "$$WATCH_DEVICE_ID" 2>/dev/null || true; \
echo " App installed. Attempting to launch..."; \
if ! xcrun simctl launch "$$WATCH_DEVICE_ID" $(BUNDLE_ID); then \
echo " Auto-launch failed. This is common for watchOS."; \
echo " Please open the app manually in the Simulator."; \
fi; \
fi
# Debug run - launches app and streams logs for debugging
debug: install
@echo " Launching Whisperer in debug mode..."
@if ! pgrep -f "Simulator" > /dev/null; then \
echo " Opening Simulator application..."; \
open -a Simulator; \
sleep 5; \
fi; \
WATCH_DEVICE_ID=$$(xcrun simctl list devices | grep "$(WATCH_SIMULATOR_NAME)" | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | head -1); \
if [ -z "$$WATCH_DEVICE_ID" ]; then \
echo " Error: Could not find Watch simulator device ID for $(WATCH_SIMULATOR_NAME)"; \
exit 1; \
else \
echo " Using Watch simulator: $$WATCH_DEVICE_ID"; \
xcrun simctl boot "$$WATCH_DEVICE_ID" 2>/dev/null || true; \
echo " App installed. Launching app..."; \
if ! xcrun simctl launch "$$WATCH_DEVICE_ID" $(BUNDLE_ID); then \
echo " Auto-launch failed. This is common for watchOS."; \
echo " Please open the app manually in the Simulator."; \
fi; \
echo " Streaming debug logs from Whisperer app..."; \
xcrun simctl spawn "$$WATCH_DEVICE_ID" log stream --predicate 'processImagePath contains "Whisperer"' --level debug; \
fi
# Debug run on Apple Watch SE simulator
debug-se: install-se
@echo " Launching Whisperer in debug mode on Apple Watch SE..."
@if ! pgrep -f "Simulator" > /dev/null; then \
echo " Opening Simulator application..."; \
open -a Simulator; \
sleep 5; \
fi; \
WATCH_DEVICE_ID=$$(xcrun simctl list devices | grep "$(WATCH_SE_SIMULATOR_NAME)" | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | head -1); \
if [ -z "$$WATCH_DEVICE_ID" ]; then \
echo " Error: Could not find Watch simulator device ID for $(WATCH_SE_SIMULATOR_NAME)"; \
exit 1; \
else \
echo " Using Apple Watch SE simulator: $$WATCH_DEVICE_ID"; \
xcrun simctl boot "$$WATCH_DEVICE_ID" 2>/dev/null || true; \
echo " App installed. Launching app..."; \
if ! xcrun simctl launch "$$WATCH_DEVICE_ID" $(BUNDLE_ID); then \
echo " Auto-launch failed. This is common for watchOS."; \
echo " Please open the app manually in the Simulator."; \
fi; \
echo " Streaming debug logs from Whisperer app..."; \
xcrun simctl spawn "$$WATCH_DEVICE_ID" log stream --predicate 'processImagePath contains "Whisperer"' --level debug; \
fi
# Debug run on Apple Watch SE 3 simulator
debug-se3: install-se3
@echo " Launching Whisperer in debug mode on Apple Watch SE 3..."
@if ! pgrep -f "Simulator" > /dev/null; then \
echo " Opening Simulator application..."; \
open -a Simulator; \
sleep 5; \
fi; \
WATCH_DEVICE_ID=$$(xcrun simctl list devices | grep "$(WATCH_SE3_SIMULATOR_NAME)" | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | head -1); \
if [ -z "$$WATCH_DEVICE_ID" ]; then \
echo " Error: Could not find Watch simulator device ID for $(WATCH_SE3_SIMULATOR_NAME)"; \
exit 1; \
else \
echo " Using Apple Watch SE 3 simulator: $$WATCH_DEVICE_ID"; \
xcrun simctl boot "$$WATCH_DEVICE_ID" 2>/dev/null || true; \
echo " App installed. Launching app..."; \
if ! xcrun simctl launch "$$WATCH_DEVICE_ID" $(BUNDLE_ID); then \
echo " Auto-launch failed. This is common for watchOS."; \
echo " Please open the app manually in the Simulator."; \
fi; \
echo " Streaming debug logs from Whisperer app..."; \
xcrun simctl spawn "$$WATCH_DEVICE_ID" log stream --predicate 'processImagePath contains "Whisperer"' --level debug; \
fi
# Debug run on Apple Watch Series 11 simulator
debug-s11: install-s11
@echo " Launching Whisperer in debug mode on Apple Watch Series 11..."
@if ! pgrep -f "Simulator" > /dev/null; then \
echo " Opening Simulator application..."; \
open -a Simulator; \
sleep 5; \
fi; \
WATCH_DEVICE_ID=$$(xcrun simctl list devices | grep "$(WATCH_SERIES11_SIMULATOR_NAME)" | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | head -1); \
if [ -z "$$WATCH_DEVICE_ID" ]; then \
echo " Error: Could not find Watch simulator device ID for $(WATCH_SERIES11_SIMULATOR_NAME)"; \
exit 1; \
else \
echo " Using Apple Watch Series 11 simulator: $$WATCH_DEVICE_ID"; \
xcrun simctl boot "$$WATCH_DEVICE_ID" 2>/dev/null || true; \
echo " App installed. Launching app..."; \
if ! xcrun simctl launch "$$WATCH_DEVICE_ID" $(BUNDLE_ID); then \
echo " Auto-launch failed. This is common for watchOS."; \
echo " Please open the app manually in the Simulator."; \
fi; \
echo " Streaming debug logs from Whisperer app..."; \
xcrun simctl spawn "$$WATCH_DEVICE_ID" log stream --predicate 'processImagePath contains "Whisperer"' --level debug; \
fi
# Deploy to Vercel
deploy:
@echo "Deploying to Vercel..."
@if ! command -v vercel >/dev/null 2>&1; then \
echo "Error: Vercel CLI not found. Install with: npm i -g vercel"; \
exit 1; \
fi
vercel --prod
# Set the Vercel dashboard project avatar to whisperer_icon.png
vercel-avatar:
@./scripts/set-vercel-project-avatar.sh
# Deploy to Vercel using nixpkgs + npx vercel
deploy-nix:
@echo "Deploying with nixpkgs node + Vercel CLI..."
nix shell nixpkgs#nodejs_22 -c npx -y vercel --prod
# List Vercel env vars using nixpkgs + npx vercel
vercel-env-ls:
@echo "Listing Vercel environment variables..."
nix shell nixpkgs#nodejs_22 -c npx -y vercel env ls
# Set Whisperer env vars (prompts securely for secrets)
vercel-env-sync:
@echo "Setting Whisperer environment variables..."
nix shell nixpkgs#nodejs_22 -c npx -y vercel env add OPENAI_CHAT_API_KEY production
nix shell nixpkgs#nodejs_22 -c npx -y vercel env add OPENAI_TRANSCRIBE_API_KEY production
nix shell nixpkgs#nodejs_22 -c npx -y vercel env add OPENAI_CHAT_MODEL production
nix shell nixpkgs#nodejs_22 -c npx -y vercel env add WHISPERER_REQUEST_SIGNING_SECRET production
nix shell nixpkgs#nodejs_22 -c npx -y vercel env add WHISPERER_CLIENT_ID production
nix shell nixpkgs#nodejs_22 -c npx -y vercel env add WHISPERER_OPENAI_TPM_LIMIT production
nix shell nixpkgs#nodejs_22 -c npx -y vercel env add WHISPERER_OPENAI_RPM_LIMIT production
nix shell nixpkgs#nodejs_22 -c npx -y vercel env add WHISPERER_OPENAI_MAX_CONCURRENT production
nix shell nixpkgs#nodejs_22 -c npx -y vercel env add WHISPERER_OPENAI_ADMISSION_MAX_WAIT_MS production
nix shell nixpkgs#nodejs_22 -c npx -y vercel env add WHISPERER_OPENAI_RETRY_MAX_ATTEMPTS production
nix shell nixpkgs#nodejs_22 -c npx -y vercel env add WHISPERER_OPENAI_RETRY_MAX_MS production
nix shell nixpkgs#nodejs_22 -c npx -y vercel env add WHISPERER_OPENAI_IMAGE_TOKEN_ESTIMATE production
# List available simulators
list-simulators:
@echo "Available Watch Simulators:"
xcrun simctl list devices watchOS | grep -E "(Apple Watch|Booted|Shutdown)"
# Clean build artifacts
clean:
@echo "Cleaning build artifacts..."
xcodebuild -project Whisperer.xcodeproj -scheme Whisperer clean
rm -rf build/
rm -rf .build/
# Open project in Xcode
open:
open Whisperer.xcodeproj
# Stream logs from the app
logs:
@echo " Streaming logs from Whisperer app..."
WATCH_DEVICE_ID=$$(xcrun simctl list devices | grep "$(WATCH_SIMULATOR_NAME)" | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | head -1); \
if [ -z "$$WATCH_DEVICE_ID" ]; then \
echo " Error: Could not find Watch simulator device ID for $(WATCH_SIMULATOR_NAME)"; \
exit 1; \
else \
echo " Using Watch simulator: $$WATCH_DEVICE_ID"; \
xcrun simctl spawn "$$WATCH_DEVICE_ID" log stream --predicate 'processImagePath contains "Whisperer"' --level debug; \
fi
# Stream logs from Apple Watch SE simulator
logs-se:
@echo " Streaming logs from Whisperer app on Apple Watch SE..."
WATCH_DEVICE_ID=$$(xcrun simctl list devices | grep "$(WATCH_SE_SIMULATOR_NAME)" | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | head -1); \
if [ -z "$$WATCH_DEVICE_ID" ]; then \
echo " Error: Could not find Watch simulator device ID for $(WATCH_SE_SIMULATOR_NAME)"; \
exit 1; \
else \
echo " Using Apple Watch SE simulator: $$WATCH_DEVICE_ID"; \
xcrun simctl spawn "$$WATCH_DEVICE_ID" log stream --predicate 'processImagePath contains "Whisperer"' --level debug; \
fi
# Stream logs from Apple Watch SE 3 simulator
logs-se3:
@echo " Streaming logs from Whisperer app on Apple Watch SE 3..."
WATCH_DEVICE_ID=$$(xcrun simctl list devices | grep "$(WATCH_SE3_SIMULATOR_NAME)" | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | head -1); \
if [ -z "$$WATCH_DEVICE_ID" ]; then \
echo " Error: Could not find Watch simulator device ID for $(WATCH_SE3_SIMULATOR_NAME)"; \
exit 1; \
else \
echo " Using Apple Watch SE 3 simulator: $$WATCH_DEVICE_ID"; \
xcrun simctl spawn "$$WATCH_DEVICE_ID" log stream --predicate 'processImagePath contains "Whisperer"' --level debug; \
fi
# Stream logs from Apple Watch Series 11 simulator
logs-s11:
@echo " Streaming logs from Whisperer app on Apple Watch Series 11..."
WATCH_DEVICE_ID=$$(xcrun simctl list devices | grep "$(WATCH_SERIES11_SIMULATOR_NAME)" | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | head -1); \
if [ -z "$$WATCH_DEVICE_ID" ]; then \
echo " Error: Could not find Watch simulator device ID for $(WATCH_SERIES11_SIMULATOR_NAME)"; \
exit 1; \
else \
echo " Using Apple Watch Series 11 simulator: $$WATCH_DEVICE_ID"; \
xcrun simctl spawn "$$WATCH_DEVICE_ID" log stream --predicate 'processImagePath contains "Whisperer"' --level debug; \
fi
# Stream filtered logs from the app
# Usage: make filter-logs FILTER="title API"
filter-logs:
@echo " Streaming filtered logs from Whisperer app..."
@if [ -z "$(FILTER)" ]; then \
echo " No filter specified. Use FILTER=\"keyword1 keyword2\" to filter logs."; \
echo " Example: make filter-logs FILTER=\"title API\""; \
echo " Defaulting to all logs..."; \
make logs; \
else \
WATCH_DEVICE_ID=$$(xcrun simctl list devices | grep "$(WATCH_SIMULATOR_NAME)" | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | head -1); \
if [ -z "$$WATCH_DEVICE_ID" ]; then \
echo " Error: Could not find Watch simulator device ID for $(WATCH_SIMULATOR_NAME)"; \
exit 1; \
else \
echo " Using Watch simulator: $$WATCH_DEVICE_ID"; \
echo " Filtering logs with: $(FILTER)"; \
FILTER_PREDICATE="processImagePath contains \"Whisperer\" AND ("; \
for keyword in $(FILTER); do \
FILTER_PREDICATE="$$FILTER_PREDICATE eventMessage contains \"$$keyword\" OR "; \
done; \
FILTER_PREDICATE="$${FILTER_PREDICATE%OR }"; \
FILTER_PREDICATE="$$FILTER_PREDICATE)"; \
echo " Using predicate: $$FILTER_PREDICATE"; \
xcrun simctl spawn "$$WATCH_DEVICE_ID" log stream --predicate "$$FILTER_PREDICATE" --level debug; \
fi; \
fi
# Wipe watchOS simulators only
wipe-simulators:
@echo " Shutting down watchOS simulators..."
@xcrun simctl list devices watchOS | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | while read -r id; do xcrun simctl shutdown "$$id" || true; done
@echo " Erasing all watchOS simulators..."
@xcrun simctl list devices watchOS | grep -E -o -i '([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})' | while read -r id; do xcrun simctl erase "$$id" || true; done
@echo " Clearing CoreSimulator caches..."
@rm -rf ~/Library/Caches/com.apple.CoreSimulator || true
@echo " Clearing Xcode DerivedData..."
@rm -rf ~/Library/Developer/Xcode/DerivedData || true
@echo " watchOS simulators wiped and caches cleared."
# API unit tests (Node)
test-api:
@cd api && npm run typecheck && npm test
# Apple unit + UI tests (requires WhispererTests / WhispererUITests schemes)
test: test-api
@echo " Running WhispererTests / WhispererUITests when schemes exist..."
@xcodebuild test \
-project Whisperer.xcodeproj \
-scheme Whisperer \
-destination 'platform=watchOS Simulator,name=$(WATCH_SIMULATOR_NAME)' \
-only-testing:WhispererTests \
-only-testing:WhispererUITests \
|| echo " NOTE: XCTest targets may need first-time scheme enablement in Xcode."
# agent-device dogfood harnesses
dogfood-watch: install
@chmod +x scripts/agent-device/dogfood-watch.sh
@BUNDLE_ID=$(BUNDLE_ID) scripts/agent-device/dogfood-watch.sh
dogfood-companion:
@chmod +x scripts/agent-device/dogfood-companion-iap.sh
@scripts/agent-device/dogfood-companion-iap.sh
deploy-watch-device:
@./scripts/agent-device/deploy-physical-watch.sh
# Show help
help:
@echo "Available targets:"
@echo " setup - Set up development environment (install Xcode and watchOS SDK)"
@echo ""
@echo "Build targets:"
@echo " build - Build the watchOS app (default: Series 11)"
@echo " build-se - Build the watchOS app for Apple Watch SE"
@echo " build-se3 - Build the watchOS app for Apple Watch SE 3"
@echo " build-s11 - Build the watchOS app for Apple Watch Series 11"
@echo ""
@echo "Install targets:"
@echo " install - Build and install app on Watch Simulator (default: Series 11)"
@echo " install-se - Build and install app on Apple Watch SE Simulator"
@echo " install-se3 - Build and install app on Apple Watch SE 3 Simulator"
@echo " install-s11 - Build and install app on Apple Watch Series 11 Simulator"
@echo ""
@echo "Run targets:"
@echo " run - Build, install, and launch app on Watch Simulator (default: Series 11)"
@echo " run-se - Build, install, and launch app on Apple Watch SE Simulator"
@echo " run-se3 - Build, install, and launch app on Apple Watch SE 3 Simulator"
@echo " run-s11 - Build, install, and launch app on Apple Watch Series 11 Simulator"
@echo " deploy-watch-device - Build, install, and launch app on physical Apple Watch"
@echo ""
@echo "Debug targets:"
@echo " debug - Build, install, and launch app ready for debugging with logs (default: Series 11)"
@echo " debug-se - Build, install, and launch app ready for debugging on Apple Watch SE"
@echo " debug-se3 - Build, install, and launch app ready for debugging on Apple Watch SE 3"
@echo " debug-s11 - Build, install, and launch app ready for debugging on Apple Watch Series 11"
@echo ""
@echo "Log targets:"
@echo " logs - Stream debug logs from the running app (default: Series 11)"
@echo " logs-se - Stream debug logs from Apple Watch SE Simulator"
@echo " logs-se3 - Stream debug logs from Apple Watch SE 3 Simulator"
@echo " logs-s11 - Stream debug logs from Apple Watch Series 11 Simulator"
@echo " filter-logs - Stream filtered logs (usage: make filter-logs FILTER=\"keyword1 keyword2\")"
@echo ""
@echo "Test / dogfood:"
@echo " test-api - Run Node metering/gateway tests"
@echo " test - Run API tests + XCTest targets (when present)"
@echo " dogfood-watch - Install + agent-device watch smoke"
@echo " dogfood-companion - agent-device Companion IAP smoke"
@echo ""
@echo "Other targets:"
@echo " deploy - Deploy Vercel API endpoints"
@echo " deploy-nix - Deploy Vercel using nixpkgs + npx vercel"
@echo " vercel-avatar - Set Vercel project avatar to whisperer_icon.png"
@echo " vercel-env-ls - List Vercel env vars using nixpkgs + npx vercel"
@echo " vercel-env-sync - Add Whisperer Vercel env vars (production)"
@echo " list-simulators - List available Watch Simulators"
@echo " clean - Clean build artifacts"
@echo " open - Open project in Xcode"
@echo " wipe-simulators - Shutdown, erase watchOS simulators, clear caches"
@echo " help - Show this help message"