@agent-link/server 0.1.124 → 0.1.126

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/web/landing.html CHANGED
@@ -1,1241 +1,1262 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>AgentLink — Remote Control for Claude Code</title>
7
- <meta name="description" content="Remote control for Claude Code. Start a task in your terminal, walk away, and continue from your phone or any browser. Multi-session, end-to-end encrypted.">
8
- <meta name="keywords" content="Claude Code, remote control, browser IDE, AI coding assistant, AgentLink, end-to-end encrypted, self-hosted, mobile coding">
9
- <link rel="canonical" href="https://msclaude.ai/">
10
- <!-- Open Graph -->
11
- <meta property="og:type" content="website">
12
- <meta property="og:title" content="AgentLink — Remote Control for Claude Code">
13
- <meta property="og:description" content="Remote control for Claude Code. Start a task in your terminal, walk away, and continue from your phone or any browser. Multi-session, end-to-end encrypted.">
14
- <meta property="og:url" content="https://msclaude.ai/">
15
- <meta property="og:image" content="https://msclaude.ai/iPad.png">
16
- <meta property="og:site_name" content="AgentLink">
17
- <!-- Twitter Card -->
18
- <meta name="twitter:card" content="summary_large_image">
19
- <meta name="twitter:title" content="AgentLink — Remote Control for Claude Code">
20
- <meta name="twitter:description" content="Remote control for Claude Code. Start a task in your terminal, walk away, and continue from your phone or any browser. Multi-session, end-to-end encrypted.">
21
- <meta name="twitter:image" content="https://msclaude.ai/iPad.png">
22
- <link rel="icon" type="image/svg+xml" href="/favicon.svg">
23
- <script type="application/ld+json">
24
- {
25
- "@context": "https://schema.org",
26
- "@type": "SoftwareApplication",
27
- "name": "AgentLink",
28
- "description": "Remote control for Claude Code. Start a task in your terminal, walk away, and continue from your phone or any browser. Multi-session, end-to-end encrypted.",
29
- "url": "https://msclaude.ai/",
30
- "applicationCategory": "DeveloperApplication",
31
- "operatingSystem": "Windows, macOS, Linux",
32
- "offers": { "@type": "Offer", "price": "0", "priceCurrency": "USD" },
33
- "screenshot": "https://msclaude.ai/iPad.png"
34
- }
35
- </script>
36
- <style>
37
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500&display=swap');
38
-
39
- * { margin: 0; padding: 0; box-sizing: border-box; }
40
-
41
- :root {
42
- --bg: #06080f;
43
- --surface: rgba(255,255,255,0.03);
44
- --surface-hover: rgba(255,255,255,0.06);
45
- --border: rgba(255,255,255,0.06);
46
- --border-hover: rgba(255,255,255,0.12);
47
- --text: #eaeaea;
48
- --text-dim: rgba(255,255,255,0.45);
49
- --text-mid: rgba(255,255,255,0.65);
50
- --accent: #3b82f6;
51
- --accent-soft: rgba(59,130,246,0.15);
52
- --accent-glow: rgba(59,130,246,0.4);
53
- --rose: #f59e0b;
54
- --amber: #f59e0b;
55
- --cyan: #22d3ee;
56
- --green: #34d399;
57
- --blue: #60a5fa;
58
- }
59
-
60
- body {
61
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
62
- background: var(--bg);
63
- color: var(--text);
64
- line-height: 1.6;
65
- min-height: 100vh;
66
- overflow-x: hidden;
67
- }
68
-
69
- /* ── Ambient Background ── */
70
- .ambient {
71
- position: fixed;
72
- top: 0;
73
- left: 0;
74
- width: 100%;
75
- height: 100%;
76
- pointer-events: none;
77
- z-index: 0;
78
- overflow: hidden;
79
- }
80
-
81
- .ambient-orb {
82
- position: absolute;
83
- border-radius: 50%;
84
- filter: blur(120px);
85
- opacity: 0.35;
86
- animation: float 20s ease-in-out infinite;
87
- }
88
-
89
- .ambient-orb:nth-child(1) {
90
- width: 600px; height: 600px;
91
- background: radial-gradient(circle, var(--accent) 0%, transparent 70%);
92
- top: -10%; left: -5%;
93
- animation-delay: 0s;
94
- animation-duration: 25s;
95
- }
96
-
97
- .ambient-orb:nth-child(2) {
98
- width: 500px; height: 500px;
99
- background: radial-gradient(circle, var(--rose) 0%, transparent 70%);
100
- top: 20%; right: -10%;
101
- animation-delay: -8s;
102
- animation-duration: 22s;
103
- }
104
-
105
- .ambient-orb:nth-child(3) {
106
- width: 400px; height: 400px;
107
- background: radial-gradient(circle, var(--cyan) 0%, transparent 70%);
108
- bottom: 10%; left: 20%;
109
- animation-delay: -15s;
110
- animation-duration: 28s;
111
- }
112
-
113
- @keyframes float {
114
- 0%, 100% { transform: translate(0, 0) scale(1); }
115
- 25% { transform: translate(30px, -40px) scale(1.05); }
116
- 50% { transform: translate(-20px, 20px) scale(0.95); }
117
- 75% { transform: translate(40px, 10px) scale(1.02); }
118
- }
119
-
120
- /* ── Grain overlay ── */
121
- .grain {
122
- position: fixed;
123
- top: 0; left: 0;
124
- width: 100%; height: 100%;
125
- pointer-events: none;
126
- z-index: 1;
127
- opacity: 0.025;
128
- background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
129
- background-repeat: repeat;
130
- background-size: 256px 256px;
131
- }
132
-
133
- /* ── Content wrapper ── */
134
- .content {
135
- position: relative;
136
- z-index: 2;
137
- }
138
-
139
- /* ── Nav ── */
140
- nav {
141
- display: flex;
142
- align-items: center;
143
- justify-content: space-between;
144
- padding: 1.5rem 2.5rem;
145
- max-width: 1200px;
146
- margin: 0 auto;
147
- }
148
-
149
- .logo {
150
- font-size: 1.2rem;
151
- font-weight: 700;
152
- letter-spacing: -0.03em;
153
- display: flex;
154
- align-items: center;
155
- gap: 0.5rem;
156
- }
157
-
158
- .logo-mark {
159
- width: 28px; height: 28px;
160
- border-radius: 8px;
161
- background: linear-gradient(135deg, var(--accent), var(--rose));
162
- display: flex;
163
- align-items: center;
164
- justify-content: center;
165
- font-size: 0.75rem;
166
- font-weight: 800;
167
- color: #fff;
168
- box-shadow: 0 0 20px var(--accent-glow);
169
- }
170
-
171
- .logo-text span {
172
- background: linear-gradient(135deg, var(--accent), var(--rose));
173
- -webkit-background-clip: text;
174
- -webkit-text-fill-color: transparent;
175
- background-clip: text;
176
- }
177
-
178
- .nav-links {
179
- display: flex;
180
- align-items: center;
181
- gap: 2rem;
182
- }
183
-
184
- .nav-links a {
185
- color: var(--text-dim);
186
- text-decoration: none;
187
- font-size: 0.85rem;
188
- font-weight: 500;
189
- transition: color 0.3s;
190
- letter-spacing: 0.02em;
191
- }
192
-
193
- .nav-links a:hover { color: var(--text); }
194
-
195
- .nav-gh {
196
- display: flex;
197
- align-items: center;
198
- gap: 0.4rem;
199
- background: var(--surface);
200
- border: 1px solid var(--border);
201
- border-radius: 8px;
202
- padding: 0.45rem 0.85rem;
203
- transition: all 0.3s;
204
- }
205
-
206
- .nav-gh:hover {
207
- background: var(--surface-hover);
208
- border-color: var(--border-hover);
209
- }
210
-
211
- .nav-gh svg { width: 16px; height: 16px; fill: currentColor; }
212
-
213
- /* ── Hero ── */
214
- .hero {
215
- text-align: center;
216
- padding: 5rem 2rem 4rem;
217
- max-width: 900px;
218
- margin: 0 auto;
219
- position: relative;
220
- }
221
-
222
- .hero-badge {
223
- display: inline-flex;
224
- align-items: center;
225
- gap: 0.5rem;
226
- background: var(--accent-soft);
227
- border: 1px solid rgba(59,130,246,0.2);
228
- border-radius: 100px;
229
- padding: 0.4rem 1rem 0.4rem 0.5rem;
230
- font-size: 0.8rem;
231
- color: var(--accent);
232
- font-weight: 500;
233
- margin-bottom: 2.5rem;
234
- letter-spacing: 0.01em;
235
- animation: fadeInUp 0.8s ease-out;
236
- }
237
-
238
- .hero-badge-dot {
239
- width: 8px; height: 8px;
240
- border-radius: 50%;
241
- background: var(--green);
242
- box-shadow: 0 0 8px var(--green);
243
- animation: pulse 2s ease-in-out infinite;
244
- }
245
-
246
- @keyframes pulse {
247
- 0%, 100% { opacity: 1; transform: scale(1); }
248
- 50% { opacity: 0.6; transform: scale(0.85); }
249
- }
250
-
251
- .hero h1 {
252
- font-size: clamp(2.8rem, 6vw, 4.5rem);
253
- font-weight: 800;
254
- letter-spacing: -0.04em;
255
- line-height: 1.08;
256
- margin-bottom: 1.75rem;
257
- animation: fadeInUp 0.8s ease-out 0.1s both;
258
- }
259
-
260
- .hero h1 .line {
261
- display: block;
262
- }
263
-
264
- .hero h1 em {
265
- font-style: normal;
266
- position: relative;
267
- background: linear-gradient(135deg, var(--accent), #60a5fa, var(--rose));
268
- background-size: 200% 200%;
269
- -webkit-background-clip: text;
270
- -webkit-text-fill-color: transparent;
271
- background-clip: text;
272
- animation: shimmer 6s ease-in-out infinite;
273
- }
274
-
275
- @keyframes shimmer {
276
- 0%, 100% { background-position: 0% 50%; }
277
- 50% { background-position: 100% 50%; }
278
- }
279
-
280
- .hero-sub {
281
- font-size: 1.2rem;
282
- color: var(--text-mid);
283
- max-width: 600px;
284
- margin: 0 auto 3rem;
285
- font-weight: 400;
286
- line-height: 1.7;
287
- animation: fadeInUp 0.8s ease-out 0.2s both;
288
- }
289
-
290
- .hero-sub strong {
291
- color: var(--text);
292
- font-weight: 500;
293
- }
294
-
295
- @keyframes fadeInUp {
296
- from { opacity: 0; transform: translateY(20px); }
297
- to { opacity: 1; transform: translateY(0); }
298
- }
299
-
300
- /* ── CTA Group ── */
301
- .cta-group {
302
- display: flex;
303
- align-items: center;
304
- justify-content: center;
305
- gap: 1rem;
306
- margin-bottom: 1.5rem;
307
- animation: fadeInUp 0.8s ease-out 0.3s both;
308
- }
309
-
310
- .cta-primary {
311
- display: inline-flex;
312
- align-items: center;
313
- gap: 0.5rem;
314
- background: linear-gradient(135deg, var(--accent), #60a5fa);
315
- color: #fff;
316
- font-weight: 600;
317
- font-size: 0.95rem;
318
- padding: 0.8rem 1.75rem;
319
- border-radius: 12px;
320
- text-decoration: none;
321
- transition: all 0.3s;
322
- box-shadow: 0 0 30px rgba(59,130,246,0.3), 0 4px 15px rgba(0,0,0,0.3);
323
- border: none;
324
- cursor: pointer;
325
- font-family: inherit;
326
- }
327
-
328
- .cta-primary:hover {
329
- transform: translateY(-2px);
330
- box-shadow: 0 0 40px rgba(59,130,246,0.45), 0 8px 25px rgba(0,0,0,0.4);
331
- }
332
-
333
- .cta-secondary {
334
- display: inline-flex;
335
- align-items: center;
336
- gap: 0.5rem;
337
- background: var(--surface);
338
- border: 1px solid var(--border);
339
- color: var(--text);
340
- font-weight: 500;
341
- font-size: 0.95rem;
342
- padding: 0.8rem 1.75rem;
343
- border-radius: 12px;
344
- text-decoration: none;
345
- transition: all 0.3s;
346
- cursor: pointer;
347
- font-family: inherit;
348
- }
349
-
350
- .cta-secondary:hover {
351
- background: var(--surface-hover);
352
- border-color: var(--border-hover);
353
- transform: translateY(-2px);
354
- }
355
-
356
- .cta-secondary svg { width: 18px; height: 18px; fill: currentColor; }
357
-
358
- /* ── Terminal Install ── */
359
- .terminal {
360
- max-width: 520px;
361
- margin: 0 auto;
362
- background: rgba(10,10,20,0.7);
363
- backdrop-filter: blur(20px);
364
- -webkit-backdrop-filter: blur(20px);
365
- border: 1px solid var(--border);
366
- border-radius: 14px;
367
- overflow: hidden;
368
- animation: fadeInUp 0.8s ease-out 0.4s both;
369
- box-shadow: 0 20px 60px rgba(0,0,0,0.4);
370
- }
371
-
372
- .terminal-bar {
373
- display: flex;
374
- align-items: center;
375
- gap: 6px;
376
- padding: 0.75rem 1rem;
377
- background: rgba(255,255,255,0.03);
378
- border-bottom: 1px solid var(--border);
379
- }
380
-
381
- .terminal-dot {
382
- width: 10px; height: 10px;
383
- border-radius: 50%;
384
- }
385
-
386
- .terminal-dot:nth-child(1) { background: #ff5f57; }
387
- .terminal-dot:nth-child(2) { background: #ffbd2e; }
388
- .terminal-dot:nth-child(3) { background: #28c840; }
389
-
390
- .terminal-title {
391
- flex: 1;
392
- text-align: center;
393
- font-size: 0.72rem;
394
- color: var(--text-dim);
395
- font-weight: 500;
396
- letter-spacing: 0.03em;
397
- }
398
-
399
- .terminal-body {
400
- padding: 1.25rem 1.5rem;
401
- font-family: 'JetBrains Mono', 'SF Mono', 'Fira Code', monospace;
402
- font-size: 0.85rem;
403
- line-height: 1.8;
404
- }
405
-
406
- .terminal-line {
407
- display: flex;
408
- align-items: center;
409
- gap: 0.5rem;
410
- cursor: pointer;
411
- padding: 0.15rem 0.35rem;
412
- margin: 0 -0.35rem;
413
- border-radius: 6px;
414
- transition: background 0.2s;
415
- }
416
-
417
- .terminal-line:hover { background: rgba(255,255,255,0.04); }
418
-
419
- .terminal-prompt { color: var(--accent); user-select: none; }
420
- .terminal-cmd { color: var(--green); }
421
-
422
- .terminal-output {
423
- color: var(--text-dim);
424
- font-size: 0.8rem;
425
- padding-left: 1.1rem;
426
- margin-top: 0.15rem;
427
- }
428
-
429
- .terminal-output a {
430
- color: var(--cyan);
431
- text-decoration: none;
432
- }
433
-
434
- .terminal-copy-toast {
435
- position: fixed;
436
- bottom: 2rem;
437
- left: 50%;
438
- transform: translateX(-50%) translateY(20px);
439
- background: var(--accent);
440
- color: #fff;
441
- padding: 0.5rem 1.25rem;
442
- border-radius: 8px;
443
- font-size: 0.8rem;
444
- font-weight: 500;
445
- opacity: 0;
446
- transition: all 0.3s;
447
- pointer-events: none;
448
- z-index: 100;
449
- font-family: 'Inter', sans-serif;
450
- }
451
-
452
- .terminal-copy-toast.show {
453
- opacity: 1;
454
- transform: translateX(-50%) translateY(0);
455
- }
456
-
457
- /* ── Showcase ── */
458
- .showcase {
459
- max-width: 1000px;
460
- margin: 6rem auto 0;
461
- padding: 0 2rem;
462
- position: relative;
463
- display: grid;
464
- grid-template-columns: 5fr 2fr;
465
- align-items: end;
466
- gap: 2rem;
467
- animation: fadeInUp 1s ease-out 0.6s both;
468
- }
469
-
470
- .showcase::before {
471
- content: '';
472
- position: absolute;
473
- top: 50%;
474
- left: 50%;
475
- transform: translate(-50%, -50%);
476
- width: 120%;
477
- height: 120%;
478
- background:
479
- radial-gradient(ellipse at 35% 50%, rgba(59,130,246,0.12) 0%, transparent 55%),
480
- radial-gradient(ellipse at 65% 50%, rgba(245,158,11,0.08) 0%, transparent 55%);
481
- pointer-events: none;
482
- z-index: 0;
483
- filter: blur(60px);
484
- }
485
-
486
- /* Subtle connecting line between devices */
487
- .showcase::after {
488
- content: '';
489
- position: absolute;
490
- top: 50%;
491
- left: 50%;
492
- transform: translate(-50%, -50%);
493
- width: 1px;
494
- height: 35%;
495
- background: linear-gradient(180deg, transparent, rgba(59,130,246,0.2), rgba(245,158,11,0.2), transparent);
496
- pointer-events: none;
497
- z-index: 0;
498
- }
499
-
500
- .device {
501
- position: relative;
502
- overflow: hidden;
503
- transition: transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
504
- }
505
-
506
- .device:hover {
507
- transform: translateY(-8px);
508
- }
509
-
510
- .device img, .device picture { display: block; width: 100%; height: auto; border-radius: inherit; }
511
-
512
- .device-ipad {
513
- width: 100%;
514
- border-radius: 4.2%;
515
- z-index: 1;
516
- box-shadow:
517
- 0 0 0 1px rgba(255,255,255,0.08),
518
- 0 40px 100px rgba(0,0,0,0.5),
519
- 0 15px 50px rgba(0,0,0,0.3),
520
- 0 0 80px rgba(59,130,246,0.08);
521
- transform: rotate(-1deg);
522
- }
523
-
524
- .device-ipad:hover {
525
- transform: rotate(-1deg) translateY(-8px);
526
- }
527
-
528
- .device-iphone {
529
- width: 90%;
530
- border-radius: 12%;
531
- z-index: 2;
532
- justify-self: center;
533
- align-self: center;
534
- box-shadow:
535
- 0 0 0 1px rgba(255,255,255,0.1),
536
- 0 45px 100px rgba(0,0,0,0.55),
537
- 0 15px 50px rgba(0,0,0,0.35),
538
- 0 0 80px rgba(245,158,11,0.08);
539
- transform: rotate(2deg);
540
- }
541
-
542
- .device-iphone:hover {
543
- transform: rotate(2deg) translateY(-8px);
544
- }
545
-
546
- /* ── Divider ── */
547
- .section-divider {
548
- max-width: 200px;
549
- margin: 6rem auto;
550
- height: 1px;
551
- background: linear-gradient(90deg, transparent, var(--border-hover), transparent);
552
- }
553
-
554
- /* ── Philosophy Section ── */
555
- .philosophy {
556
- max-width: 700px;
557
- margin: 0 auto;
558
- padding: 0 2rem;
559
- text-align: center;
560
- }
561
-
562
- .philosophy-label {
563
- font-size: 0.7rem;
564
- font-weight: 600;
565
- letter-spacing: 0.15em;
566
- text-transform: uppercase;
567
- color: var(--accent);
568
- margin-bottom: 1.5rem;
569
- }
570
-
571
- .philosophy h2 {
572
- font-size: clamp(1.6rem, 3.5vw, 2.4rem);
573
- font-weight: 700;
574
- letter-spacing: -0.03em;
575
- line-height: 1.25;
576
- margin-bottom: 1.5rem;
577
- }
578
-
579
- .philosophy h2 em {
580
- font-style: normal;
581
- color: var(--text-dim);
582
- }
583
-
584
- .philosophy p {
585
- color: var(--text-mid);
586
- font-size: 1.05rem;
587
- line-height: 1.8;
588
- max-width: 560px;
589
- margin: 0 auto;
590
- }
591
-
592
- /* ── Bento Grid ── */
593
- .bento {
594
- max-width: 1000px;
595
- margin: 6rem auto;
596
- padding: 0 2rem;
597
- display: grid;
598
- grid-template-columns: repeat(3, 1fr);
599
- grid-auto-rows: minmax(200px, auto);
600
- gap: 1rem;
601
- }
602
-
603
- .bento-card {
604
- background: var(--surface);
605
- border: 1px solid var(--border);
606
- border-radius: 20px;
607
- padding: 2rem;
608
- position: relative;
609
- overflow: hidden;
610
- transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
611
- display: flex;
612
- flex-direction: column;
613
- justify-content: flex-end;
614
- }
615
-
616
- .bento-card:hover {
617
- border-color: var(--border-hover);
618
- background: var(--surface-hover);
619
- transform: translateY(-4px);
620
- box-shadow: 0 20px 60px rgba(0,0,0,0.3);
621
- }
622
-
623
- .bento-card.wide { grid-column: span 2; }
624
- .bento-card.tall { grid-row: span 2; }
625
-
626
- .bento-visual {
627
- flex: 1;
628
- display: flex;
629
- align-items: center;
630
- justify-content: center;
631
- margin-bottom: 1.5rem;
632
- position: relative;
633
- }
634
-
635
- .bento-icon {
636
- width: 56px; height: 56px;
637
- border-radius: 16px;
638
- display: flex;
639
- align-items: center;
640
- justify-content: center;
641
- font-size: 1.5rem;
642
- }
643
-
644
- .bento-icon.purple { background: linear-gradient(135deg, rgba(59,130,246,0.2), rgba(59,130,246,0.05)); color: var(--accent); }
645
- .bento-icon.rose { background: linear-gradient(135deg, rgba(245,158,11,0.2), rgba(245,158,11,0.05)); color: var(--rose); }
646
- .bento-icon.cyan { background: linear-gradient(135deg, rgba(34,211,238,0.2), rgba(34,211,238,0.05)); color: var(--cyan); }
647
- .bento-icon.green { background: linear-gradient(135deg, rgba(52,211,153,0.2), rgba(52,211,153,0.05)); color: var(--green); }
648
- .bento-icon.amber { background: linear-gradient(135deg, rgba(245,158,11,0.2), rgba(245,158,11,0.05)); color: var(--amber); }
649
- .bento-icon.blue { background: linear-gradient(135deg, rgba(96,165,250,0.2), rgba(96,165,250,0.05)); color: var(--blue); }
650
-
651
- /* Encryption visual */
652
- .encrypt-visual {
653
- display: flex;
654
- align-items: center;
655
- gap: 0.75rem;
656
- font-family: 'JetBrains Mono', monospace;
657
- font-size: 0.72rem;
658
- color: var(--text-dim);
659
- }
660
-
661
- .encrypt-block {
662
- padding: 0.4rem 0.7rem;
663
- border-radius: 8px;
664
- background: rgba(255,255,255,0.04);
665
- border: 1px solid var(--border);
666
- white-space: nowrap;
667
- }
668
-
669
- .encrypt-arrow { color: var(--accent); font-size: 1rem; }
670
-
671
- .encrypt-block.locked {
672
- color: var(--green);
673
- border-color: rgba(52,211,153,0.2);
674
- background: rgba(52,211,153,0.05);
675
- }
676
-
677
- /* Device flow visual */
678
- .device-flow {
679
- display: flex;
680
- align-items: center;
681
- gap: 1rem;
682
- }
683
-
684
- .device-pill {
685
- display: flex;
686
- align-items: center;
687
- gap: 0.4rem;
688
- padding: 0.5rem 0.8rem;
689
- border-radius: 10px;
690
- background: rgba(255,255,255,0.04);
691
- border: 1px solid var(--border);
692
- font-size: 0.75rem;
693
- color: var(--text-mid);
694
- }
695
-
696
- .device-pill svg { width: 14px; height: 14px; fill: currentColor; opacity: 0.6; }
697
-
698
- .flow-line {
699
- flex: 1;
700
- height: 1px;
701
- background: linear-gradient(90deg, var(--border-hover), transparent);
702
- position: relative;
703
- }
704
-
705
- .flow-line::after {
706
- content: '';
707
- position: absolute;
708
- right: 0; top: -2px;
709
- width: 5px; height: 5px;
710
- border-radius: 50%;
711
- background: var(--accent);
712
- box-shadow: 0 0 8px var(--accent-glow);
713
- animation: flowPulse 2s ease-in-out infinite;
714
- }
715
-
716
- @keyframes flowPulse {
717
- 0%, 100% { opacity: 0.4; }
718
- 50% { opacity: 1; }
719
- }
720
-
721
- .bento-card h3 {
722
- font-size: 1.05rem;
723
- font-weight: 600;
724
- margin-bottom: 0.4rem;
725
- letter-spacing: -0.01em;
726
- }
727
-
728
- .bento-card p {
729
- font-size: 0.85rem;
730
- color: var(--text-dim);
731
- line-height: 1.55;
732
- }
733
-
734
- /* ── How It Works ── */
735
- .workflow {
736
- max-width: 700px;
737
- margin: 0 auto 6rem;
738
- padding: 0 2rem;
739
- }
740
-
741
- .workflow-label {
742
- font-size: 0.7rem;
743
- font-weight: 600;
744
- letter-spacing: 0.15em;
745
- text-transform: uppercase;
746
- color: var(--accent);
747
- text-align: center;
748
- margin-bottom: 1.5rem;
749
- }
750
-
751
- .workflow h2 {
752
- font-size: clamp(1.6rem, 3.5vw, 2.2rem);
753
- font-weight: 700;
754
- text-align: center;
755
- letter-spacing: -0.03em;
756
- margin-bottom: 3rem;
757
- }
758
-
759
- .workflow-steps {
760
- position: relative;
761
- display: flex;
762
- flex-direction: column;
763
- gap: 0;
764
- }
765
-
766
- .workflow-steps::before {
767
- content: '';
768
- position: absolute;
769
- left: 23px;
770
- top: 48px;
771
- bottom: 48px;
772
- width: 1px;
773
- background: linear-gradient(180deg, var(--accent), var(--cyan), var(--green));
774
- opacity: 0.3;
775
- }
776
-
777
- .workflow-step {
778
- display: flex;
779
- align-items: flex-start;
780
- gap: 1.5rem;
781
- padding: 1.5rem 0;
782
- position: relative;
783
- }
784
-
785
- .step-marker {
786
- width: 48px; height: 48px;
787
- border-radius: 14px;
788
- display: flex;
789
- align-items: center;
790
- justify-content: center;
791
- flex-shrink: 0;
792
- font-size: 1.1rem;
793
- background: var(--surface);
794
- border: 1px solid var(--border);
795
- position: relative;
796
- z-index: 1;
797
- }
798
-
799
- .workflow-step:nth-child(1) .step-marker { border-color: rgba(59,130,246,0.3); }
800
- .workflow-step:nth-child(2) .step-marker { border-color: rgba(34,211,238,0.3); }
801
- .workflow-step:nth-child(3) .step-marker { border-color: rgba(52,211,153,0.3); }
802
-
803
- .step-content h3 {
804
- font-size: 1rem;
805
- font-weight: 600;
806
- margin-bottom: 0.35rem;
807
- letter-spacing: -0.01em;
808
- }
809
-
810
- .step-content p {
811
- font-size: 0.88rem;
812
- color: var(--text-dim);
813
- line-height: 1.6;
814
- }
815
-
816
- .step-content code {
817
- font-family: 'JetBrains Mono', monospace;
818
- font-size: 0.8rem;
819
- color: var(--green);
820
- background: rgba(52,211,153,0.08);
821
- padding: 0.15rem 0.45rem;
822
- border-radius: 5px;
823
- border: 1px solid rgba(52,211,153,0.12);
824
- }
825
-
826
- /* ── Footer ── */
827
- footer {
828
- text-align: center;
829
- padding: 3rem 2rem;
830
- color: var(--text-dim);
831
- font-size: 0.8rem;
832
- position: relative;
833
- }
834
-
835
- footer::before {
836
- content: '';
837
- display: block;
838
- max-width: 200px;
839
- margin: 0 auto 2rem;
840
- height: 1px;
841
- background: linear-gradient(90deg, transparent, var(--border-hover), transparent);
842
- }
843
-
844
- footer a {
845
- color: var(--text-mid);
846
- text-decoration: none;
847
- transition: color 0.3s;
848
- }
849
-
850
- footer a:hover { color: var(--text); }
851
-
852
- .footer-links {
853
- display: flex;
854
- align-items: center;
855
- justify-content: center;
856
- gap: 1.5rem;
857
- margin-bottom: 1rem;
858
- }
859
-
860
- .footer-brand {
861
- font-weight: 600;
862
- letter-spacing: -0.02em;
863
- }
864
-
865
- /* ── Responsive ── */
866
- @media (max-width: 768px) {
867
- .bento {
868
- grid-template-columns: 1fr;
869
- }
870
- .bento-card.wide { grid-column: span 1; }
871
- .bento-card.tall { grid-row: span 1; }
872
- .hero { padding: 5rem 1.5rem 3rem; }
873
- .cta-group { flex-direction: column; }
874
- .nav-links { gap: 1rem; }
875
- .nav-links a:not(.nav-gh) { display: none; }
876
- .encrypt-visual { flex-wrap: wrap; justify-content: center; gap: 0.5rem; }
877
- .encrypt-visual .encrypt-arrow { display: none; }
878
- .encrypt-block { font-size: 0.65rem; }
879
- .device-flow { flex-wrap: wrap; justify-content: center; gap: 0.6rem; }
880
- .device-flow .flow-line { display: none; }
881
- .device-pill { font-size: 0.7rem; }
882
- }
883
-
884
- @media (max-width: 640px) {
885
- nav { padding: 1rem 1.25rem; }
886
- .showcase {
887
- margin-top: 3rem;
888
- display: flex;
889
- justify-content: center;
890
- align-items: flex-end;
891
- gap: 0;
892
- }
893
- .showcase::after { display: none; }
894
- .device-ipad {
895
- width: 78%;
896
- transform: rotate(0deg);
897
- flex-shrink: 0;
898
- }
899
- .device-ipad:hover { transform: translateY(-8px); }
900
- .device-iphone {
901
- width: 28%;
902
- transform: rotate(0deg) translateY(5%);
903
- margin-left: -12%;
904
- flex-shrink: 0;
905
- justify-self: auto;
906
- align-self: auto;
907
- }
908
- .device-iphone:hover { transform: translateY(-3%); }
909
- .terminal { margin: 0 1rem; max-width: calc(100vw - 2rem); }
910
- .terminal-body { padding: 1rem; font-size: 0.75rem; overflow-x: auto; }
911
- .terminal-line { gap: 0.4rem; white-space: nowrap; }
912
- .terminal-output { font-size: 0.7rem; padding-left: 0.9rem; }
913
- .section-divider { margin: 4rem auto; }
914
- .bento { padding: 0 1rem; margin: 4rem auto; }
915
- .bento-card { padding: 1.5rem; border-radius: 16px; overflow: visible; }
916
- .encrypt-visual { gap: 0.4rem; }
917
- .encrypt-block { padding: 0.3rem 0.5rem; font-size: 0.6rem; }
918
- .device-flow { gap: 0.5rem; }
919
- .device-pill { padding: 0.4rem 0.6rem; font-size: 0.65rem; }
920
- .workflow-step { gap: 1rem; }
921
- .step-marker { width: 40px; height: 40px; border-radius: 12px; font-size: 1rem; }
922
- .workflow-steps::before { left: 19px; }
923
- }
924
-
925
- /* ── Scroll animations ── */
926
- .reveal {
927
- opacity: 0;
928
- transform: translateY(30px);
929
- transition: opacity 0.8s ease, transform 0.8s ease;
930
- }
931
-
932
- .reveal.visible {
933
- opacity: 1;
934
- transform: translateY(0);
935
- }
936
-
937
- .sr-only {
938
- position: absolute;
939
- width: 1px; height: 1px;
940
- padding: 0; margin: -1px;
941
- overflow: hidden;
942
- clip: rect(0,0,0,0);
943
- white-space: nowrap;
944
- border: 0;
945
- }
946
- </style>
947
- </head>
948
- <body>
949
-
950
- <!-- Ambient background -->
951
- <div class="ambient" aria-hidden="true">
952
- <div class="ambient-orb"></div>
953
- <div class="ambient-orb"></div>
954
- <div class="ambient-orb"></div>
955
- </div>
956
- <div class="grain" aria-hidden="true"></div>
957
-
958
- <div class="content">
959
-
960
- <!-- Nav -->
961
- <header>
962
- <nav>
963
- <div class="logo">
964
- <div class="logo-mark">A</div>
965
- <div class="logo-text">Agent<span>Link</span></div>
966
- </div>
967
- <div class="nav-links">
968
- <a href="#features">Features</a>
969
- <a href="#how-it-works">How It Works</a>
970
- <a href="https://github.com/yilee/agentlink" target="_blank" rel="noopener" class="nav-gh">
971
- <svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
972
- GitHub
973
- </a>
974
- </div>
975
- </nav>
976
- </header>
977
-
978
- <main>
979
-
980
- <!-- Hero -->
981
- <section class="hero">
982
- <div class="hero-badge">
983
- <div class="hero-badge-dot"></div>
984
- Open Source &middot; End-to-End Encrypted
985
- </div>
986
- <h1>
987
- <span class="line">Control Claude Code.</span>
988
- <span class="line"><em>From anywhere.</em></span>
989
- </h1>
990
- <p class="hero-sub">
991
- Start Claude Code on your machine. Walk away.
992
- <strong>Pick it up from your phone, tablet, or any browser</strong> &mdash;
993
- end-to-end encrypted, zero configuration.
994
- </p>
995
- <div class="cta-group">
996
- <button class="cta-primary" onclick="copyInstall()">
997
- <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" y1="19" x2="20" y2="19"></line></svg>
998
- Quick Install
999
- </button>
1000
- <a href="https://github.com/yilee/agentlink" target="_blank" rel="noopener" class="cta-secondary">
1001
- <svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
1002
- View on GitHub
1003
- </a>
1004
- </div>
1005
-
1006
- <!-- Terminal -->
1007
- <div class="terminal">
1008
- <div class="terminal-bar">
1009
- <div class="terminal-dot"></div>
1010
- <div class="terminal-dot"></div>
1011
- <div class="terminal-dot"></div>
1012
- <div class="terminal-title">Terminal</div>
1013
- </div>
1014
- <div class="terminal-body">
1015
- <div class="terminal-line" onclick="copyCmd('npm install -g @agent-link/agent')">
1016
- <span class="terminal-prompt">$</span>
1017
- <span class="terminal-cmd">npm install -g @agent-link/agent</span>
1018
- </div>
1019
- <div class="terminal-line" onclick="copyCmd('agentlink-client start -D')">
1020
- <span class="terminal-prompt">$</span>
1021
- <span class="terminal-cmd">agentlink-client start -D</span>
1022
- </div>
1023
- <div class="terminal-output">
1024
- Session ready &rarr; <a>https://msclaude.ai/s/abc123</a>
1025
- </div>
1026
- </div>
1027
- </div>
1028
- </section>
1029
-
1030
- <!-- Device Showcase -->
1031
- <section class="showcase reveal">
1032
- <div class="device device-ipad">
1033
- <picture>
1034
- <source srcset="/iPad.webp" type="image/webp">
1035
- <img src="/iPad.png" alt="AgentLink web interface running Claude Code on an iPad" loading="eager">
1036
- </picture>
1037
- </div>
1038
- <div class="device device-iphone">
1039
- <picture>
1040
- <source srcset="/iPhone.webp" type="image/webp">
1041
- <img src="/iPhone.png" alt="AgentLink mobile interface on iPhone" loading="eager">
1042
- </picture>
1043
- </div>
1044
- </section>
1045
-
1046
- <div class="section-divider"></div>
1047
-
1048
- <!-- Philosophy -->
1049
- <section class="philosophy reveal">
1050
- <div class="philosophy-label">Philosophy</div>
1051
- <h2>Code shouldn't be <em>chained to a desk.</em></h2>
1052
- <p>
1053
- AgentLink turns Claude Code into a truly portable experience.
1054
- One command, one URL &mdash; your AI assistant is accessible from any device,
1055
- with real encryption and zero accounts required.
1056
- </p>
1057
- </section>
1058
-
1059
- <div class="section-divider"></div>
1060
-
1061
- <!-- Bento Features -->
1062
- <section class="bento reveal" id="features">
1063
- <h2 class="sr-only">Features</h2>
1064
-
1065
- <!-- E2E Encryption — wide -->
1066
- <div class="bento-card wide">
1067
- <div class="bento-visual">
1068
- <div class="encrypt-visual">
1069
- <div class="encrypt-block">hello world</div>
1070
- <div class="encrypt-arrow">&rarr;</div>
1071
- <div class="encrypt-block locked">x9f#k2$mQ...</div>
1072
- <div class="encrypt-arrow">&rarr;</div>
1073
- <div class="encrypt-block">hello world</div>
1074
- </div>
1075
- </div>
1076
- <h3>End-to-End Encrypted</h3>
1077
- <p>XSalsa20-Poly1305 encryption. The relay server is a blind forwarder &mdash; it never sees your code, your prompts, or your data.</p>
1078
- </div>
1079
-
1080
- <!-- Zero Config -->
1081
- <div class="bento-card">
1082
- <div class="bento-visual">
1083
- <div class="bento-icon purple">
1084
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon></svg>
1085
- </div>
1086
- </div>
1087
- <h3>Zero Config</h3>
1088
- <p>No accounts. No registration. Install, start, open &mdash; done.</p>
1089
- </div>
1090
-
1091
- <!-- Any Device -->
1092
- <div class="bento-card">
1093
- <div class="bento-visual">
1094
- <div class="bento-icon cyan">
1095
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="2" width="14" height="20" rx="2" ry="2"></rect><line x1="12" y1="18" x2="12.01" y2="18"></line></svg>
1096
- </div>
1097
- </div>
1098
- <h3>Any Device</h3>
1099
- <p>Phone, tablet, laptop &mdash; any browser becomes your Claude Code terminal.</p>
1100
- </div>
1101
-
1102
- <!-- Full Claude Code — wide -->
1103
- <div class="bento-card wide">
1104
- <div class="bento-visual">
1105
- <div class="device-flow">
1106
- <div class="device-pill">
1107
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" y1="19" x2="20" y2="19"></line></svg>
1108
- Terminal
1109
- </div>
1110
- <div class="flow-line"></div>
1111
- <div class="device-pill">
1112
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path><polyline points="14 2 14 8 20 8"></polyline></svg>
1113
- Files
1114
- </div>
1115
- <div class="flow-line"></div>
1116
- <div class="device-pill">
1117
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
1118
- Search
1119
- </div>
1120
- <div class="flow-line"></div>
1121
- <div class="device-pill">
1122
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>
1123
- Chat
1124
- </div>
1125
- </div>
1126
- </div>
1127
- <h3>Full Claude Code Experience</h3>
1128
- <p>File editing, shell commands, search, multi-turn conversations &mdash; every capability, now in your browser.</p>
1129
- </div>
1130
-
1131
- <!-- Self-hostable -->
1132
- <div class="bento-card">
1133
- <div class="bento-visual">
1134
- <div class="bento-icon green">
1135
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="2" width="20" height="8" rx="2" ry="2"></rect><rect x="2" y="14" width="20" height="8" rx="2" ry="2"></rect><line x1="6" y1="6" x2="6.01" y2="6"></line><line x1="6" y1="18" x2="6.01" y2="18"></line></svg>
1136
- </div>
1137
- </div>
1138
- <h3>Self-Hostable</h3>
1139
- <p>Run your own relay server. Your infrastructure, your rules, your data.</p>
1140
- </div>
1141
-
1142
- <!-- Multi Session -->
1143
- <div class="bento-card">
1144
- <div class="bento-visual">
1145
- <div class="bento-icon blue">
1146
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="8" height="8" rx="1.5"></rect><rect x="14" y="3" width="8" height="8" rx="1.5"></rect><rect x="2" y="13" width="8" height="8" rx="1.5"></rect><rect x="14" y="13" width="8" height="8" rx="1.5"></rect></svg>
1147
- </div>
1148
- </div>
1149
- <h3>Multi Session</h3>
1150
- <p>Run multiple conversations in parallel. Switch between tasks without losing context.</p>
1151
- </div>
1152
-
1153
- <!-- Password Protection -->
1154
- <div class="bento-card">
1155
- <div class="bento-visual">
1156
- <div class="bento-icon amber">
1157
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>
1158
- </div>
1159
- </div>
1160
- <h3>Optional Password</h3>
1161
- <p>Add <code style="color:var(--green);font-family:'JetBrains Mono',monospace;font-size:0.8rem">--password</code> to lock your session. Brute-force protection built in.</p>
1162
- </div>
1163
- </section>
1164
-
1165
- <div class="section-divider"></div>
1166
-
1167
- <!-- How It Works -->
1168
- <section class="workflow reveal" id="how-it-works">
1169
- <div class="workflow-label">How It Works</div>
1170
- <h2>Three steps. That's it.</h2>
1171
- <div class="workflow-steps">
1172
- <div class="workflow-step">
1173
- <div class="step-marker">01</div>
1174
- <div class="step-content">
1175
- <h3>Start the agent</h3>
1176
- <p>Run <code>agentlink-client start -D</code> in your project directory. It prints a unique session URL.</p>
1177
- </div>
1178
- </div>
1179
- <div class="workflow-step">
1180
- <div class="step-marker">02</div>
1181
- <div class="step-content">
1182
- <h3>Open the URL, anywhere</h3>
1183
- <p>Phone, tablet, a friend's laptop &mdash; any browser works. Traffic is end-to-end encrypted automatically; the relay never sees your data.</p>
1184
- </div>
1185
- </div>
1186
- <div class="workflow-step">
1187
- <div class="step-marker">03</div>
1188
- <div class="step-content">
1189
- <h3>Run sessions in parallel, switch freely</h3>
1190
- <p>Multiple conversations, multiple projects &mdash; all running at once. Jump between them from any device, with full history preserved.</p>
1191
- </div>
1192
- </div>
1193
- </div>
1194
- </section>
1195
-
1196
- </main>
1197
-
1198
- <footer>
1199
- <div class="footer-links">
1200
- <span class="footer-brand">AgentLink</span>
1201
- <a href="https://github.com/yilee/agentlink" rel="noopener">GitHub</a>
1202
- </div>
1203
- <p>Open source. Free forever. Built for developers who ship from anywhere.</p>
1204
- </footer>
1205
-
1206
- </div>
1207
-
1208
- <!-- Toast for copy -->
1209
- <div class="terminal-copy-toast" id="copyToast">Copied to clipboard</div>
1210
-
1211
- <script>
1212
- function copyCmd(text) {
1213
- navigator.clipboard.writeText(text);
1214
- showToast();
1215
- }
1216
-
1217
- function copyInstall() {
1218
- navigator.clipboard.writeText('npm install -g @agent-link/agent && agentlink-client start -D');
1219
- showToast();
1220
- }
1221
-
1222
- function showToast() {
1223
- const toast = document.getElementById('copyToast');
1224
- toast.classList.add('show');
1225
- setTimeout(() => toast.classList.remove('show'), 1800);
1226
- }
1227
-
1228
- // Scroll reveal
1229
- const observer = new IntersectionObserver((entries) => {
1230
- entries.forEach(entry => {
1231
- if (entry.isIntersecting) {
1232
- entry.target.classList.add('visible');
1233
- }
1234
- });
1235
- }, { threshold: 0.1, rootMargin: '0px 0px -50px 0px' });
1236
-
1237
- document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
1238
- </script>
1239
-
1240
- </body>
1241
- </html>
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>AgentLink — Remote Control for Claude Code</title>
7
+ <meta name="description" content="Remote control for Claude Code. Start a task in your terminal, walk away, and continue from your phone or any browser. Multi-session, end-to-end encrypted.">
8
+ <meta name="keywords" content="Claude Code, remote control, browser IDE, AI coding assistant, AgentLink, end-to-end encrypted, self-hosted, mobile coding">
9
+ <link rel="canonical" href="https://msclaude.ai/">
10
+ <link rel="alternate" hreflang="en" href="https://msclaude.ai/">
11
+ <link rel="alternate" hreflang="zh" href="https://msclaude.ai/zh">
12
+ <link rel="alternate" hreflang="x-default" href="https://msclaude.ai/">
13
+ <!-- Open Graph -->
14
+ <meta property="og:type" content="website">
15
+ <meta property="og:title" content="AgentLink — Remote Control for Claude Code">
16
+ <meta property="og:description" content="Remote control for Claude Code. Start a task in your terminal, walk away, and continue from your phone or any browser. Multi-session, end-to-end encrypted.">
17
+ <meta property="og:url" content="https://msclaude.ai/">
18
+ <meta property="og:image" content="https://msclaude.ai/iPad.png">
19
+ <meta property="og:site_name" content="AgentLink">
20
+ <!-- Twitter Card -->
21
+ <meta name="twitter:card" content="summary_large_image">
22
+ <meta name="twitter:title" content="AgentLink — Remote Control for Claude Code">
23
+ <meta name="twitter:description" content="Remote control for Claude Code. Start a task in your terminal, walk away, and continue from your phone or any browser. Multi-session, end-to-end encrypted.">
24
+ <meta name="twitter:image" content="https://msclaude.ai/iPad.png">
25
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg">
26
+ <script type="application/ld+json">
27
+ {
28
+ "@context": "https://schema.org",
29
+ "@type": "SoftwareApplication",
30
+ "name": "AgentLink",
31
+ "description": "Remote control for Claude Code. Start a task in your terminal, walk away, and continue from your phone or any browser. Multi-session, end-to-end encrypted.",
32
+ "url": "https://msclaude.ai/",
33
+ "applicationCategory": "DeveloperApplication",
34
+ "operatingSystem": "Windows, macOS, Linux",
35
+ "offers": { "@type": "Offer", "price": "0", "priceCurrency": "USD" },
36
+ "screenshot": "https://msclaude.ai/iPad.png"
37
+ }
38
+ </script>
39
+ <style>
40
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500&display=swap');
41
+
42
+ * { margin: 0; padding: 0; box-sizing: border-box; }
43
+
44
+ :root {
45
+ --bg: #06080f;
46
+ --surface: rgba(255,255,255,0.03);
47
+ --surface-hover: rgba(255,255,255,0.06);
48
+ --border: rgba(255,255,255,0.06);
49
+ --border-hover: rgba(255,255,255,0.12);
50
+ --text: #eaeaea;
51
+ --text-dim: rgba(255,255,255,0.45);
52
+ --text-mid: rgba(255,255,255,0.65);
53
+ --accent: #3b82f6;
54
+ --accent-soft: rgba(59,130,246,0.15);
55
+ --accent-glow: rgba(59,130,246,0.4);
56
+ --rose: #f59e0b;
57
+ --amber: #f59e0b;
58
+ --cyan: #22d3ee;
59
+ --green: #34d399;
60
+ --blue: #60a5fa;
61
+ }
62
+
63
+ body {
64
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
65
+ background: var(--bg);
66
+ color: var(--text);
67
+ line-height: 1.6;
68
+ min-height: 100vh;
69
+ overflow-x: hidden;
70
+ }
71
+
72
+ /* ── Ambient Background ── */
73
+ .ambient {
74
+ position: fixed;
75
+ top: 0;
76
+ left: 0;
77
+ width: 100%;
78
+ height: 100%;
79
+ pointer-events: none;
80
+ z-index: 0;
81
+ overflow: hidden;
82
+ }
83
+
84
+ .ambient-orb {
85
+ position: absolute;
86
+ border-radius: 50%;
87
+ filter: blur(120px);
88
+ opacity: 0.35;
89
+ animation: float 20s ease-in-out infinite;
90
+ }
91
+
92
+ .ambient-orb:nth-child(1) {
93
+ width: 600px; height: 600px;
94
+ background: radial-gradient(circle, var(--accent) 0%, transparent 70%);
95
+ top: -10%; left: -5%;
96
+ animation-delay: 0s;
97
+ animation-duration: 25s;
98
+ }
99
+
100
+ .ambient-orb:nth-child(2) {
101
+ width: 500px; height: 500px;
102
+ background: radial-gradient(circle, var(--rose) 0%, transparent 70%);
103
+ top: 20%; right: -10%;
104
+ animation-delay: -8s;
105
+ animation-duration: 22s;
106
+ }
107
+
108
+ .ambient-orb:nth-child(3) {
109
+ width: 400px; height: 400px;
110
+ background: radial-gradient(circle, var(--cyan) 0%, transparent 70%);
111
+ bottom: 10%; left: 20%;
112
+ animation-delay: -15s;
113
+ animation-duration: 28s;
114
+ }
115
+
116
+ @keyframes float {
117
+ 0%, 100% { transform: translate(0, 0) scale(1); }
118
+ 25% { transform: translate(30px, -40px) scale(1.05); }
119
+ 50% { transform: translate(-20px, 20px) scale(0.95); }
120
+ 75% { transform: translate(40px, 10px) scale(1.02); }
121
+ }
122
+
123
+ /* ── Grain overlay ── */
124
+ .grain {
125
+ position: fixed;
126
+ top: 0; left: 0;
127
+ width: 100%; height: 100%;
128
+ pointer-events: none;
129
+ z-index: 1;
130
+ opacity: 0.025;
131
+ background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
132
+ background-repeat: repeat;
133
+ background-size: 256px 256px;
134
+ }
135
+
136
+ /* ── Content wrapper ── */
137
+ .content {
138
+ position: relative;
139
+ z-index: 2;
140
+ }
141
+
142
+ /* ── Nav ── */
143
+ nav {
144
+ display: flex;
145
+ align-items: center;
146
+ justify-content: space-between;
147
+ padding: 1.5rem 2.5rem;
148
+ max-width: 1200px;
149
+ margin: 0 auto;
150
+ }
151
+
152
+ .logo {
153
+ font-size: 1.2rem;
154
+ font-weight: 700;
155
+ letter-spacing: -0.03em;
156
+ display: flex;
157
+ align-items: center;
158
+ gap: 0.5rem;
159
+ }
160
+
161
+ .logo-mark {
162
+ width: 28px; height: 28px;
163
+ border-radius: 8px;
164
+ background: linear-gradient(135deg, var(--accent), var(--rose));
165
+ display: flex;
166
+ align-items: center;
167
+ justify-content: center;
168
+ font-size: 0.75rem;
169
+ font-weight: 800;
170
+ color: #fff;
171
+ box-shadow: 0 0 20px var(--accent-glow);
172
+ }
173
+
174
+ .logo-text span {
175
+ background: linear-gradient(135deg, var(--accent), var(--rose));
176
+ -webkit-background-clip: text;
177
+ -webkit-text-fill-color: transparent;
178
+ background-clip: text;
179
+ }
180
+
181
+ .nav-links {
182
+ display: flex;
183
+ align-items: center;
184
+ gap: 2rem;
185
+ }
186
+
187
+ .nav-links a {
188
+ color: var(--text-dim);
189
+ text-decoration: none;
190
+ font-size: 0.85rem;
191
+ font-weight: 500;
192
+ transition: color 0.3s;
193
+ letter-spacing: 0.02em;
194
+ }
195
+
196
+ .nav-links a:hover { color: var(--text); }
197
+
198
+ .nav-gh {
199
+ display: flex;
200
+ align-items: center;
201
+ gap: 0.4rem;
202
+ background: var(--surface);
203
+ border: 1px solid var(--border);
204
+ border-radius: 8px;
205
+ padding: 0.45rem 0.85rem;
206
+ transition: all 0.3s;
207
+ }
208
+
209
+ .nav-gh:hover {
210
+ background: var(--surface-hover);
211
+ border-color: var(--border-hover);
212
+ }
213
+
214
+ .nav-gh svg { width: 16px; height: 16px; fill: currentColor; }
215
+
216
+ .nav-lang {
217
+ font-size: 0.8rem;
218
+ color: var(--text-dim);
219
+ padding: 0.35rem 0.7rem;
220
+ border: 1px solid var(--border);
221
+ border-radius: 6px;
222
+ transition: all 0.3s;
223
+ }
224
+
225
+ .nav-lang:hover {
226
+ color: var(--text);
227
+ border-color: var(--border-hover);
228
+ }
229
+
230
+ /* ── Hero ── */
231
+ .hero {
232
+ text-align: center;
233
+ padding: 5rem 2rem 4rem;
234
+ max-width: 900px;
235
+ margin: 0 auto;
236
+ position: relative;
237
+ }
238
+
239
+ .hero-badge {
240
+ display: inline-flex;
241
+ align-items: center;
242
+ gap: 0.5rem;
243
+ background: var(--accent-soft);
244
+ border: 1px solid rgba(59,130,246,0.2);
245
+ border-radius: 100px;
246
+ padding: 0.4rem 1rem 0.4rem 0.5rem;
247
+ font-size: 0.8rem;
248
+ color: var(--accent);
249
+ font-weight: 500;
250
+ margin-bottom: 2.5rem;
251
+ letter-spacing: 0.01em;
252
+ animation: fadeInUp 0.8s ease-out;
253
+ }
254
+
255
+ .hero-badge-dot {
256
+ width: 8px; height: 8px;
257
+ border-radius: 50%;
258
+ background: var(--green);
259
+ box-shadow: 0 0 8px var(--green);
260
+ animation: pulse 2s ease-in-out infinite;
261
+ }
262
+
263
+ @keyframes pulse {
264
+ 0%, 100% { opacity: 1; transform: scale(1); }
265
+ 50% { opacity: 0.6; transform: scale(0.85); }
266
+ }
267
+
268
+ .hero h1 {
269
+ font-size: clamp(2.8rem, 6vw, 4.5rem);
270
+ font-weight: 800;
271
+ letter-spacing: -0.04em;
272
+ line-height: 1.08;
273
+ margin-bottom: 1.75rem;
274
+ animation: fadeInUp 0.8s ease-out 0.1s both;
275
+ }
276
+
277
+ .hero h1 .line {
278
+ display: block;
279
+ }
280
+
281
+ .hero h1 em {
282
+ font-style: normal;
283
+ position: relative;
284
+ background: linear-gradient(135deg, var(--accent), #60a5fa, var(--rose));
285
+ background-size: 200% 200%;
286
+ -webkit-background-clip: text;
287
+ -webkit-text-fill-color: transparent;
288
+ background-clip: text;
289
+ animation: shimmer 6s ease-in-out infinite;
290
+ }
291
+
292
+ @keyframes shimmer {
293
+ 0%, 100% { background-position: 0% 50%; }
294
+ 50% { background-position: 100% 50%; }
295
+ }
296
+
297
+ .hero-sub {
298
+ font-size: 1.2rem;
299
+ color: var(--text-mid);
300
+ max-width: 600px;
301
+ margin: 0 auto 3rem;
302
+ font-weight: 400;
303
+ line-height: 1.7;
304
+ animation: fadeInUp 0.8s ease-out 0.2s both;
305
+ }
306
+
307
+ .hero-sub strong {
308
+ color: var(--text);
309
+ font-weight: 500;
310
+ }
311
+
312
+ @keyframes fadeInUp {
313
+ from { opacity: 0; transform: translateY(20px); }
314
+ to { opacity: 1; transform: translateY(0); }
315
+ }
316
+
317
+ /* ── CTA Group ── */
318
+ .cta-group {
319
+ display: flex;
320
+ align-items: center;
321
+ justify-content: center;
322
+ gap: 1rem;
323
+ margin-bottom: 1.5rem;
324
+ animation: fadeInUp 0.8s ease-out 0.3s both;
325
+ }
326
+
327
+ .cta-primary {
328
+ display: inline-flex;
329
+ align-items: center;
330
+ gap: 0.5rem;
331
+ background: linear-gradient(135deg, var(--accent), #60a5fa);
332
+ color: #fff;
333
+ font-weight: 600;
334
+ font-size: 0.95rem;
335
+ padding: 0.8rem 1.75rem;
336
+ border-radius: 12px;
337
+ text-decoration: none;
338
+ transition: all 0.3s;
339
+ box-shadow: 0 0 30px rgba(59,130,246,0.3), 0 4px 15px rgba(0,0,0,0.3);
340
+ border: none;
341
+ cursor: pointer;
342
+ font-family: inherit;
343
+ }
344
+
345
+ .cta-primary:hover {
346
+ transform: translateY(-2px);
347
+ box-shadow: 0 0 40px rgba(59,130,246,0.45), 0 8px 25px rgba(0,0,0,0.4);
348
+ }
349
+
350
+ .cta-secondary {
351
+ display: inline-flex;
352
+ align-items: center;
353
+ gap: 0.5rem;
354
+ background: var(--surface);
355
+ border: 1px solid var(--border);
356
+ color: var(--text);
357
+ font-weight: 500;
358
+ font-size: 0.95rem;
359
+ padding: 0.8rem 1.75rem;
360
+ border-radius: 12px;
361
+ text-decoration: none;
362
+ transition: all 0.3s;
363
+ cursor: pointer;
364
+ font-family: inherit;
365
+ }
366
+
367
+ .cta-secondary:hover {
368
+ background: var(--surface-hover);
369
+ border-color: var(--border-hover);
370
+ transform: translateY(-2px);
371
+ }
372
+
373
+ .cta-secondary svg { width: 18px; height: 18px; fill: currentColor; }
374
+
375
+ /* ── Terminal Install ── */
376
+ .terminal {
377
+ max-width: 520px;
378
+ margin: 0 auto;
379
+ background: rgba(10,10,20,0.7);
380
+ backdrop-filter: blur(20px);
381
+ -webkit-backdrop-filter: blur(20px);
382
+ border: 1px solid var(--border);
383
+ border-radius: 14px;
384
+ overflow: hidden;
385
+ animation: fadeInUp 0.8s ease-out 0.4s both;
386
+ box-shadow: 0 20px 60px rgba(0,0,0,0.4);
387
+ }
388
+
389
+ .terminal-bar {
390
+ display: flex;
391
+ align-items: center;
392
+ gap: 6px;
393
+ padding: 0.75rem 1rem;
394
+ background: rgba(255,255,255,0.03);
395
+ border-bottom: 1px solid var(--border);
396
+ }
397
+
398
+ .terminal-dot {
399
+ width: 10px; height: 10px;
400
+ border-radius: 50%;
401
+ }
402
+
403
+ .terminal-dot:nth-child(1) { background: #ff5f57; }
404
+ .terminal-dot:nth-child(2) { background: #ffbd2e; }
405
+ .terminal-dot:nth-child(3) { background: #28c840; }
406
+
407
+ .terminal-title {
408
+ flex: 1;
409
+ text-align: center;
410
+ font-size: 0.72rem;
411
+ color: var(--text-dim);
412
+ font-weight: 500;
413
+ letter-spacing: 0.03em;
414
+ }
415
+
416
+ .terminal-body {
417
+ padding: 1.25rem 1.5rem;
418
+ font-family: 'JetBrains Mono', 'SF Mono', 'Fira Code', monospace;
419
+ font-size: 0.85rem;
420
+ line-height: 1.8;
421
+ }
422
+
423
+ .terminal-line {
424
+ display: flex;
425
+ align-items: center;
426
+ gap: 0.5rem;
427
+ cursor: pointer;
428
+ padding: 0.15rem 0.35rem;
429
+ margin: 0 -0.35rem;
430
+ border-radius: 6px;
431
+ transition: background 0.2s;
432
+ }
433
+
434
+ .terminal-line:hover { background: rgba(255,255,255,0.04); }
435
+
436
+ .terminal-prompt { color: var(--accent); user-select: none; }
437
+ .terminal-cmd { color: var(--green); }
438
+
439
+ .terminal-output {
440
+ color: var(--text-dim);
441
+ font-size: 0.8rem;
442
+ padding-left: 1.1rem;
443
+ margin-top: 0.15rem;
444
+ }
445
+
446
+ .terminal-output a {
447
+ color: var(--cyan);
448
+ text-decoration: none;
449
+ }
450
+
451
+ .terminal-copy-toast {
452
+ position: fixed;
453
+ bottom: 2rem;
454
+ left: 50%;
455
+ transform: translateX(-50%) translateY(20px);
456
+ background: var(--accent);
457
+ color: #fff;
458
+ padding: 0.5rem 1.25rem;
459
+ border-radius: 8px;
460
+ font-size: 0.8rem;
461
+ font-weight: 500;
462
+ opacity: 0;
463
+ transition: all 0.3s;
464
+ pointer-events: none;
465
+ z-index: 100;
466
+ font-family: 'Inter', sans-serif;
467
+ }
468
+
469
+ .terminal-copy-toast.show {
470
+ opacity: 1;
471
+ transform: translateX(-50%) translateY(0);
472
+ }
473
+
474
+ /* ── Showcase ── */
475
+ .showcase {
476
+ max-width: 1000px;
477
+ margin: 6rem auto 0;
478
+ padding: 0 2rem;
479
+ position: relative;
480
+ display: grid;
481
+ grid-template-columns: 5fr 2fr;
482
+ align-items: end;
483
+ gap: 2rem;
484
+ animation: fadeInUp 1s ease-out 0.6s both;
485
+ }
486
+
487
+ .showcase::before {
488
+ content: '';
489
+ position: absolute;
490
+ top: 50%;
491
+ left: 50%;
492
+ transform: translate(-50%, -50%);
493
+ width: 120%;
494
+ height: 120%;
495
+ background:
496
+ radial-gradient(ellipse at 35% 50%, rgba(59,130,246,0.12) 0%, transparent 55%),
497
+ radial-gradient(ellipse at 65% 50%, rgba(245,158,11,0.08) 0%, transparent 55%);
498
+ pointer-events: none;
499
+ z-index: 0;
500
+ filter: blur(60px);
501
+ }
502
+
503
+ /* Subtle connecting line between devices */
504
+ .showcase::after {
505
+ content: '';
506
+ position: absolute;
507
+ top: 50%;
508
+ left: 50%;
509
+ transform: translate(-50%, -50%);
510
+ width: 1px;
511
+ height: 35%;
512
+ background: linear-gradient(180deg, transparent, rgba(59,130,246,0.2), rgba(245,158,11,0.2), transparent);
513
+ pointer-events: none;
514
+ z-index: 0;
515
+ }
516
+
517
+ .device {
518
+ position: relative;
519
+ transition: transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
520
+ }
521
+
522
+ .device:hover {
523
+ transform: translateY(-8px);
524
+ }
525
+
526
+ .device img, .device picture { display: block; width: 100%; height: auto; }
527
+
528
+ .device-ipad {
529
+ width: 100%;
530
+ z-index: 1;
531
+ transform: rotate(-1deg);
532
+ }
533
+
534
+ .device-ipad:hover {
535
+ transform: rotate(-1deg) translateY(-8px);
536
+ }
537
+
538
+ .device-ipad img {
539
+ border-radius: 4.2%;
540
+ box-shadow:
541
+ 0 40px 100px rgba(0,0,0,0.5),
542
+ 0 15px 50px rgba(0,0,0,0.3),
543
+ 0 0 80px rgba(59,130,246,0.08);
544
+ }
545
+
546
+ .device-iphone {
547
+ width: 90%;
548
+ z-index: 2;
549
+ justify-self: center;
550
+ align-self: center;
551
+ transform: rotate(2deg);
552
+ }
553
+
554
+ .device-iphone:hover {
555
+ transform: rotate(2deg) translateY(-8px);
556
+ }
557
+
558
+ .device-iphone img {
559
+ border-radius: 12%;
560
+ box-shadow:
561
+ 0 45px 100px rgba(0,0,0,0.55),
562
+ 0 15px 50px rgba(0,0,0,0.35),
563
+ 0 0 80px rgba(245,158,11,0.08);
564
+ }
565
+
566
+ /* ── Divider ── */
567
+ .section-divider {
568
+ max-width: 200px;
569
+ margin: 6rem auto;
570
+ height: 1px;
571
+ background: linear-gradient(90deg, transparent, var(--border-hover), transparent);
572
+ }
573
+
574
+ /* ── Philosophy Section ── */
575
+ .philosophy {
576
+ max-width: 700px;
577
+ margin: 0 auto;
578
+ padding: 0 2rem;
579
+ text-align: center;
580
+ }
581
+
582
+ .philosophy-label {
583
+ font-size: 0.7rem;
584
+ font-weight: 600;
585
+ letter-spacing: 0.15em;
586
+ text-transform: uppercase;
587
+ color: var(--accent);
588
+ margin-bottom: 1.5rem;
589
+ }
590
+
591
+ .philosophy h2 {
592
+ font-size: clamp(1.6rem, 3.5vw, 2.4rem);
593
+ font-weight: 700;
594
+ letter-spacing: -0.03em;
595
+ line-height: 1.25;
596
+ margin-bottom: 1.5rem;
597
+ }
598
+
599
+ .philosophy h2 em {
600
+ font-style: normal;
601
+ color: var(--text-dim);
602
+ }
603
+
604
+ .philosophy p {
605
+ color: var(--text-mid);
606
+ font-size: 1.05rem;
607
+ line-height: 1.8;
608
+ max-width: 560px;
609
+ margin: 0 auto;
610
+ }
611
+
612
+ /* ── Bento Grid ── */
613
+ .bento {
614
+ max-width: 1000px;
615
+ margin: 6rem auto;
616
+ padding: 0 2rem;
617
+ display: grid;
618
+ grid-template-columns: repeat(3, 1fr);
619
+ grid-auto-rows: minmax(200px, auto);
620
+ gap: 1rem;
621
+ }
622
+
623
+ .bento-card {
624
+ background: var(--surface);
625
+ border: 1px solid var(--border);
626
+ border-radius: 20px;
627
+ padding: 2rem;
628
+ position: relative;
629
+ overflow: hidden;
630
+ transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
631
+ display: flex;
632
+ flex-direction: column;
633
+ justify-content: flex-end;
634
+ }
635
+
636
+ .bento-card:hover {
637
+ border-color: var(--border-hover);
638
+ background: var(--surface-hover);
639
+ transform: translateY(-4px);
640
+ box-shadow: 0 20px 60px rgba(0,0,0,0.3);
641
+ }
642
+
643
+ .bento-card.wide { grid-column: span 2; }
644
+ .bento-card.tall { grid-row: span 2; }
645
+
646
+ .bento-visual {
647
+ flex: 1;
648
+ display: flex;
649
+ align-items: center;
650
+ justify-content: center;
651
+ margin-bottom: 1.5rem;
652
+ position: relative;
653
+ }
654
+
655
+ .bento-icon {
656
+ width: 56px; height: 56px;
657
+ border-radius: 16px;
658
+ display: flex;
659
+ align-items: center;
660
+ justify-content: center;
661
+ font-size: 1.5rem;
662
+ }
663
+
664
+ .bento-icon.purple { background: linear-gradient(135deg, rgba(59,130,246,0.2), rgba(59,130,246,0.05)); color: var(--accent); }
665
+ .bento-icon.rose { background: linear-gradient(135deg, rgba(245,158,11,0.2), rgba(245,158,11,0.05)); color: var(--rose); }
666
+ .bento-icon.cyan { background: linear-gradient(135deg, rgba(34,211,238,0.2), rgba(34,211,238,0.05)); color: var(--cyan); }
667
+ .bento-icon.green { background: linear-gradient(135deg, rgba(52,211,153,0.2), rgba(52,211,153,0.05)); color: var(--green); }
668
+ .bento-icon.amber { background: linear-gradient(135deg, rgba(245,158,11,0.2), rgba(245,158,11,0.05)); color: var(--amber); }
669
+ .bento-icon.blue { background: linear-gradient(135deg, rgba(96,165,250,0.2), rgba(96,165,250,0.05)); color: var(--blue); }
670
+
671
+ /* Encryption visual */
672
+ .encrypt-visual {
673
+ display: flex;
674
+ align-items: center;
675
+ gap: 0.75rem;
676
+ font-family: 'JetBrains Mono', monospace;
677
+ font-size: 0.72rem;
678
+ color: var(--text-dim);
679
+ }
680
+
681
+ .encrypt-block {
682
+ padding: 0.4rem 0.7rem;
683
+ border-radius: 8px;
684
+ background: rgba(255,255,255,0.04);
685
+ border: 1px solid var(--border);
686
+ white-space: nowrap;
687
+ }
688
+
689
+ .encrypt-arrow { color: var(--accent); font-size: 1rem; }
690
+
691
+ .encrypt-block.locked {
692
+ color: var(--green);
693
+ border-color: rgba(52,211,153,0.2);
694
+ background: rgba(52,211,153,0.05);
695
+ }
696
+
697
+ /* Device flow visual */
698
+ .device-flow {
699
+ display: flex;
700
+ align-items: center;
701
+ gap: 1rem;
702
+ }
703
+
704
+ .device-pill {
705
+ display: flex;
706
+ align-items: center;
707
+ gap: 0.4rem;
708
+ padding: 0.5rem 0.8rem;
709
+ border-radius: 10px;
710
+ background: rgba(255,255,255,0.04);
711
+ border: 1px solid var(--border);
712
+ font-size: 0.75rem;
713
+ color: var(--text-mid);
714
+ }
715
+
716
+ .device-pill svg { width: 14px; height: 14px; fill: currentColor; opacity: 0.6; }
717
+
718
+ .flow-line {
719
+ flex: 1;
720
+ height: 1px;
721
+ background: linear-gradient(90deg, var(--border-hover), transparent);
722
+ position: relative;
723
+ }
724
+
725
+ .flow-line::after {
726
+ content: '';
727
+ position: absolute;
728
+ right: 0; top: -2px;
729
+ width: 5px; height: 5px;
730
+ border-radius: 50%;
731
+ background: var(--accent);
732
+ box-shadow: 0 0 8px var(--accent-glow);
733
+ animation: flowPulse 2s ease-in-out infinite;
734
+ }
735
+
736
+ @keyframes flowPulse {
737
+ 0%, 100% { opacity: 0.4; }
738
+ 50% { opacity: 1; }
739
+ }
740
+
741
+ .bento-card h3 {
742
+ font-size: 1.05rem;
743
+ font-weight: 600;
744
+ margin-bottom: 0.4rem;
745
+ letter-spacing: -0.01em;
746
+ }
747
+
748
+ .bento-card p {
749
+ font-size: 0.85rem;
750
+ color: var(--text-dim);
751
+ line-height: 1.55;
752
+ }
753
+
754
+ /* ── How It Works ── */
755
+ .workflow {
756
+ max-width: 700px;
757
+ margin: 0 auto 6rem;
758
+ padding: 0 2rem;
759
+ }
760
+
761
+ .workflow-label {
762
+ font-size: 0.7rem;
763
+ font-weight: 600;
764
+ letter-spacing: 0.15em;
765
+ text-transform: uppercase;
766
+ color: var(--accent);
767
+ text-align: center;
768
+ margin-bottom: 1.5rem;
769
+ }
770
+
771
+ .workflow h2 {
772
+ font-size: clamp(1.6rem, 3.5vw, 2.2rem);
773
+ font-weight: 700;
774
+ text-align: center;
775
+ letter-spacing: -0.03em;
776
+ margin-bottom: 3rem;
777
+ }
778
+
779
+ .workflow-steps {
780
+ position: relative;
781
+ display: flex;
782
+ flex-direction: column;
783
+ gap: 0;
784
+ }
785
+
786
+ .workflow-steps::before {
787
+ content: '';
788
+ position: absolute;
789
+ left: 23px;
790
+ top: 48px;
791
+ bottom: 48px;
792
+ width: 1px;
793
+ background: linear-gradient(180deg, var(--accent), var(--cyan), var(--green));
794
+ opacity: 0.3;
795
+ }
796
+
797
+ .workflow-step {
798
+ display: flex;
799
+ align-items: flex-start;
800
+ gap: 1.5rem;
801
+ padding: 1.5rem 0;
802
+ position: relative;
803
+ }
804
+
805
+ .step-marker {
806
+ width: 48px; height: 48px;
807
+ border-radius: 14px;
808
+ display: flex;
809
+ align-items: center;
810
+ justify-content: center;
811
+ flex-shrink: 0;
812
+ font-size: 1.1rem;
813
+ background: var(--surface);
814
+ border: 1px solid var(--border);
815
+ position: relative;
816
+ z-index: 1;
817
+ }
818
+
819
+ .workflow-step:nth-child(1) .step-marker { border-color: rgba(59,130,246,0.3); }
820
+ .workflow-step:nth-child(2) .step-marker { border-color: rgba(34,211,238,0.3); }
821
+ .workflow-step:nth-child(3) .step-marker { border-color: rgba(52,211,153,0.3); }
822
+
823
+ .step-content h3 {
824
+ font-size: 1rem;
825
+ font-weight: 600;
826
+ margin-bottom: 0.35rem;
827
+ letter-spacing: -0.01em;
828
+ }
829
+
830
+ .step-content p {
831
+ font-size: 0.88rem;
832
+ color: var(--text-dim);
833
+ line-height: 1.6;
834
+ }
835
+
836
+ .step-content code {
837
+ font-family: 'JetBrains Mono', monospace;
838
+ font-size: 0.8rem;
839
+ color: var(--green);
840
+ background: rgba(52,211,153,0.08);
841
+ padding: 0.15rem 0.45rem;
842
+ border-radius: 5px;
843
+ border: 1px solid rgba(52,211,153,0.12);
844
+ }
845
+
846
+ /* ── Footer ── */
847
+ footer {
848
+ text-align: center;
849
+ padding: 3rem 2rem;
850
+ color: var(--text-dim);
851
+ font-size: 0.8rem;
852
+ position: relative;
853
+ }
854
+
855
+ footer::before {
856
+ content: '';
857
+ display: block;
858
+ max-width: 200px;
859
+ margin: 0 auto 2rem;
860
+ height: 1px;
861
+ background: linear-gradient(90deg, transparent, var(--border-hover), transparent);
862
+ }
863
+
864
+ footer a {
865
+ color: var(--text-mid);
866
+ text-decoration: none;
867
+ transition: color 0.3s;
868
+ }
869
+
870
+ footer a:hover { color: var(--text); }
871
+
872
+ .footer-links {
873
+ display: flex;
874
+ align-items: center;
875
+ justify-content: center;
876
+ gap: 1.5rem;
877
+ margin-bottom: 1rem;
878
+ }
879
+
880
+ .footer-brand {
881
+ font-weight: 600;
882
+ letter-spacing: -0.02em;
883
+ }
884
+
885
+ /* ── Responsive ── */
886
+ @media (max-width: 768px) {
887
+ .bento {
888
+ grid-template-columns: 1fr;
889
+ }
890
+ .bento-card.wide { grid-column: span 1; }
891
+ .bento-card.tall { grid-row: span 1; }
892
+ .hero { padding: 5rem 1.5rem 3rem; }
893
+ .cta-group { flex-direction: column; }
894
+ .nav-links { gap: 1rem; }
895
+ .nav-links a:not(.nav-gh):not(.nav-lang) { display: none; }
896
+ .encrypt-visual { flex-wrap: wrap; justify-content: center; gap: 0.5rem; }
897
+ .encrypt-visual .encrypt-arrow { display: none; }
898
+ .encrypt-block { font-size: 0.65rem; }
899
+ .device-flow { flex-wrap: wrap; justify-content: center; gap: 0.6rem; }
900
+ .device-flow .flow-line { display: none; }
901
+ .device-pill { font-size: 0.7rem; }
902
+ }
903
+
904
+ @media (max-width: 640px) {
905
+ nav { padding: 1rem 1.25rem; }
906
+ .showcase {
907
+ margin-top: 3rem;
908
+ display: flex;
909
+ justify-content: center;
910
+ align-items: flex-end;
911
+ gap: 0;
912
+ }
913
+ .showcase::after { display: none; }
914
+ .device-ipad {
915
+ width: 78%;
916
+ transform: rotate(0deg);
917
+ flex-shrink: 0;
918
+ }
919
+ .device-ipad:hover { transform: translateY(-8px); }
920
+ .device-iphone {
921
+ width: 28%;
922
+ transform: rotate(0deg) translateY(5%);
923
+ margin-left: -12%;
924
+ flex-shrink: 0;
925
+ justify-self: auto;
926
+ align-self: auto;
927
+ }
928
+ .device-iphone:hover { transform: translateY(-3%); }
929
+ .terminal { margin: 0 1rem; max-width: calc(100vw - 2rem); }
930
+ .terminal-body { padding: 1rem; font-size: 0.75rem; overflow-x: auto; }
931
+ .terminal-line { gap: 0.4rem; white-space: nowrap; }
932
+ .terminal-output { font-size: 0.7rem; padding-left: 0.9rem; }
933
+ .section-divider { margin: 4rem auto; }
934
+ .bento { padding: 0 1rem; margin: 4rem auto; }
935
+ .bento-card { padding: 1.5rem; border-radius: 16px; overflow: visible; }
936
+ .encrypt-visual { gap: 0.4rem; }
937
+ .encrypt-block { padding: 0.3rem 0.5rem; font-size: 0.6rem; }
938
+ .device-flow { gap: 0.5rem; }
939
+ .device-pill { padding: 0.4rem 0.6rem; font-size: 0.65rem; }
940
+ .workflow-step { gap: 1rem; }
941
+ .step-marker { width: 40px; height: 40px; border-radius: 12px; font-size: 1rem; }
942
+ .workflow-steps::before { left: 19px; }
943
+ }
944
+
945
+ /* ── Scroll animations ── */
946
+ .reveal {
947
+ opacity: 0;
948
+ transform: translateY(30px);
949
+ transition: opacity 0.8s ease, transform 0.8s ease;
950
+ }
951
+
952
+ .reveal.visible {
953
+ opacity: 1;
954
+ transform: translateY(0);
955
+ }
956
+
957
+ .sr-only {
958
+ position: absolute;
959
+ width: 1px; height: 1px;
960
+ padding: 0; margin: -1px;
961
+ overflow: hidden;
962
+ clip: rect(0,0,0,0);
963
+ white-space: nowrap;
964
+ border: 0;
965
+ }
966
+ </style>
967
+ </head>
968
+ <body>
969
+
970
+ <!-- Ambient background -->
971
+ <div class="ambient" aria-hidden="true">
972
+ <div class="ambient-orb"></div>
973
+ <div class="ambient-orb"></div>
974
+ <div class="ambient-orb"></div>
975
+ </div>
976
+ <div class="grain" aria-hidden="true"></div>
977
+
978
+ <div class="content">
979
+
980
+ <!-- Nav -->
981
+ <header>
982
+ <nav>
983
+ <div class="logo">
984
+ <div class="logo-mark">A</div>
985
+ <div class="logo-text">Agent<span>Link</span></div>
986
+ </div>
987
+ <div class="nav-links">
988
+ <a href="#features">Features</a>
989
+ <a href="#how-it-works">How It Works</a>
990
+ <a href="/zh" class="nav-lang">中文</a>
991
+ <a href="https://github.com/yilee/agentlink" target="_blank" rel="noopener" class="nav-gh">
992
+ <svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
993
+ GitHub
994
+ </a>
995
+ </div>
996
+ </nav>
997
+ </header>
998
+
999
+ <main>
1000
+
1001
+ <!-- Hero -->
1002
+ <section class="hero">
1003
+ <div class="hero-badge">
1004
+ <div class="hero-badge-dot"></div>
1005
+ Open Source &middot; End-to-End Encrypted
1006
+ </div>
1007
+ <h1>
1008
+ <span class="line">Control Claude Code.</span>
1009
+ <span class="line"><em>From anywhere.</em></span>
1010
+ </h1>
1011
+ <p class="hero-sub">
1012
+ Start Claude Code on your machine. Walk away.
1013
+ <strong>Pick it up from your phone, tablet, or any browser</strong> &mdash;
1014
+ end-to-end encrypted, zero configuration.
1015
+ </p>
1016
+ <div class="cta-group">
1017
+ <button class="cta-primary" onclick="copyInstall()">
1018
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" y1="19" x2="20" y2="19"></line></svg>
1019
+ Quick Install
1020
+ </button>
1021
+ <a href="https://github.com/yilee/agentlink" target="_blank" rel="noopener" class="cta-secondary">
1022
+ <svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
1023
+ View on GitHub
1024
+ </a>
1025
+ </div>
1026
+
1027
+ <!-- Terminal -->
1028
+ <div class="terminal">
1029
+ <div class="terminal-bar">
1030
+ <div class="terminal-dot"></div>
1031
+ <div class="terminal-dot"></div>
1032
+ <div class="terminal-dot"></div>
1033
+ <div class="terminal-title">Terminal</div>
1034
+ </div>
1035
+ <div class="terminal-body">
1036
+ <div class="terminal-line" onclick="copyCmd('npm install -g @agent-link/agent')">
1037
+ <span class="terminal-prompt">$</span>
1038
+ <span class="terminal-cmd">npm install -g @agent-link/agent</span>
1039
+ </div>
1040
+ <div class="terminal-line" onclick="copyCmd('agentlink-client start -D')">
1041
+ <span class="terminal-prompt">$</span>
1042
+ <span class="terminal-cmd">agentlink-client start -D</span>
1043
+ </div>
1044
+ <div class="terminal-output">
1045
+ Session ready &rarr; <a>https://msclaude.ai/s/abc123</a>
1046
+ </div>
1047
+ </div>
1048
+ </div>
1049
+ </section>
1050
+
1051
+ <!-- Device Showcase -->
1052
+ <section class="showcase reveal">
1053
+ <div class="device device-ipad">
1054
+ <picture>
1055
+ <source srcset="/iPad.webp" type="image/webp">
1056
+ <img src="/iPad.png" alt="AgentLink web interface running Claude Code on an iPad" loading="eager">
1057
+ </picture>
1058
+ </div>
1059
+ <div class="device device-iphone">
1060
+ <picture>
1061
+ <source srcset="/iPhone.webp" type="image/webp">
1062
+ <img src="/iPhone.png" alt="AgentLink mobile interface on iPhone" loading="eager">
1063
+ </picture>
1064
+ </div>
1065
+ </section>
1066
+
1067
+ <div class="section-divider"></div>
1068
+
1069
+ <!-- Philosophy -->
1070
+ <section class="philosophy reveal">
1071
+ <div class="philosophy-label">Philosophy</div>
1072
+ <h2>Code shouldn't be <em>chained to a desk.</em></h2>
1073
+ <p>
1074
+ AgentLink turns Claude Code into a truly portable experience.
1075
+ One command, one URL &mdash; your AI assistant is accessible from any device,
1076
+ with real encryption and zero accounts required.
1077
+ </p>
1078
+ </section>
1079
+
1080
+ <div class="section-divider"></div>
1081
+
1082
+ <!-- Bento Features -->
1083
+ <section class="bento reveal" id="features">
1084
+ <h2 class="sr-only">Features</h2>
1085
+
1086
+ <!-- E2E Encryption — wide -->
1087
+ <div class="bento-card wide">
1088
+ <div class="bento-visual">
1089
+ <div class="encrypt-visual">
1090
+ <div class="encrypt-block">hello world</div>
1091
+ <div class="encrypt-arrow">&rarr;</div>
1092
+ <div class="encrypt-block locked">x9f#k2$mQ...</div>
1093
+ <div class="encrypt-arrow">&rarr;</div>
1094
+ <div class="encrypt-block">hello world</div>
1095
+ </div>
1096
+ </div>
1097
+ <h3>End-to-End Encrypted</h3>
1098
+ <p>XSalsa20-Poly1305 encryption. The relay server is a blind forwarder &mdash; it never sees your code, your prompts, or your data.</p>
1099
+ </div>
1100
+
1101
+ <!-- Zero Config -->
1102
+ <div class="bento-card">
1103
+ <div class="bento-visual">
1104
+ <div class="bento-icon purple">
1105
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon></svg>
1106
+ </div>
1107
+ </div>
1108
+ <h3>Zero Config</h3>
1109
+ <p>No accounts. No registration. Install, start, open &mdash; done.</p>
1110
+ </div>
1111
+
1112
+ <!-- Any Device -->
1113
+ <div class="bento-card">
1114
+ <div class="bento-visual">
1115
+ <div class="bento-icon cyan">
1116
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="2" width="14" height="20" rx="2" ry="2"></rect><line x1="12" y1="18" x2="12.01" y2="18"></line></svg>
1117
+ </div>
1118
+ </div>
1119
+ <h3>Any Device</h3>
1120
+ <p>Phone, tablet, laptop &mdash; any browser becomes your Claude Code terminal.</p>
1121
+ </div>
1122
+
1123
+ <!-- Full Claude Code — wide -->
1124
+ <div class="bento-card wide">
1125
+ <div class="bento-visual">
1126
+ <div class="device-flow">
1127
+ <div class="device-pill">
1128
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" y1="19" x2="20" y2="19"></line></svg>
1129
+ Terminal
1130
+ </div>
1131
+ <div class="flow-line"></div>
1132
+ <div class="device-pill">
1133
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path><polyline points="14 2 14 8 20 8"></polyline></svg>
1134
+ Files
1135
+ </div>
1136
+ <div class="flow-line"></div>
1137
+ <div class="device-pill">
1138
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
1139
+ Search
1140
+ </div>
1141
+ <div class="flow-line"></div>
1142
+ <div class="device-pill">
1143
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>
1144
+ Chat
1145
+ </div>
1146
+ </div>
1147
+ </div>
1148
+ <h3>Full Claude Code Experience</h3>
1149
+ <p>File editing, shell commands, search, multi-turn conversations &mdash; every capability, now in your browser.</p>
1150
+ </div>
1151
+
1152
+ <!-- Self-hostable -->
1153
+ <div class="bento-card">
1154
+ <div class="bento-visual">
1155
+ <div class="bento-icon green">
1156
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="2" width="20" height="8" rx="2" ry="2"></rect><rect x="2" y="14" width="20" height="8" rx="2" ry="2"></rect><line x1="6" y1="6" x2="6.01" y2="6"></line><line x1="6" y1="18" x2="6.01" y2="18"></line></svg>
1157
+ </div>
1158
+ </div>
1159
+ <h3>Self-Hostable</h3>
1160
+ <p>Run your own relay server. Your infrastructure, your rules, your data.</p>
1161
+ </div>
1162
+
1163
+ <!-- Multi Session -->
1164
+ <div class="bento-card">
1165
+ <div class="bento-visual">
1166
+ <div class="bento-icon blue">
1167
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="8" height="8" rx="1.5"></rect><rect x="14" y="3" width="8" height="8" rx="1.5"></rect><rect x="2" y="13" width="8" height="8" rx="1.5"></rect><rect x="14" y="13" width="8" height="8" rx="1.5"></rect></svg>
1168
+ </div>
1169
+ </div>
1170
+ <h3>Multi Session</h3>
1171
+ <p>Run multiple conversations in parallel. Switch between tasks without losing context.</p>
1172
+ </div>
1173
+
1174
+ <!-- Password Protection -->
1175
+ <div class="bento-card">
1176
+ <div class="bento-visual">
1177
+ <div class="bento-icon amber">
1178
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>
1179
+ </div>
1180
+ </div>
1181
+ <h3>Optional Password</h3>
1182
+ <p>Add <code style="color:var(--green);font-family:'JetBrains Mono',monospace;font-size:0.8rem">--password</code> to lock your session. Brute-force protection built in.</p>
1183
+ </div>
1184
+ </section>
1185
+
1186
+ <div class="section-divider"></div>
1187
+
1188
+ <!-- How It Works -->
1189
+ <section class="workflow reveal" id="how-it-works">
1190
+ <div class="workflow-label">How It Works</div>
1191
+ <h2>Three steps. That's it.</h2>
1192
+ <div class="workflow-steps">
1193
+ <div class="workflow-step">
1194
+ <div class="step-marker">01</div>
1195
+ <div class="step-content">
1196
+ <h3>Start the agent</h3>
1197
+ <p>Run <code>agentlink-client start -D</code> in your project directory. It prints a unique session URL.</p>
1198
+ </div>
1199
+ </div>
1200
+ <div class="workflow-step">
1201
+ <div class="step-marker">02</div>
1202
+ <div class="step-content">
1203
+ <h3>Open the URL, anywhere</h3>
1204
+ <p>Phone, tablet, a friend's laptop &mdash; any browser works. Traffic is end-to-end encrypted automatically; the relay never sees your data.</p>
1205
+ </div>
1206
+ </div>
1207
+ <div class="workflow-step">
1208
+ <div class="step-marker">03</div>
1209
+ <div class="step-content">
1210
+ <h3>Run sessions in parallel, switch freely</h3>
1211
+ <p>Multiple conversations, multiple projects &mdash; all running at once. Jump between them from any device, with full history preserved.</p>
1212
+ </div>
1213
+ </div>
1214
+ </div>
1215
+ </section>
1216
+
1217
+ </main>
1218
+
1219
+ <footer>
1220
+ <div class="footer-links">
1221
+ <span class="footer-brand">AgentLink</span>
1222
+ <a href="https://github.com/yilee/agentlink" rel="noopener">GitHub</a>
1223
+ </div>
1224
+ <p>Open source. Free forever. Built for developers who ship from anywhere.</p>
1225
+ </footer>
1226
+
1227
+ </div>
1228
+
1229
+ <!-- Toast for copy -->
1230
+ <div class="terminal-copy-toast" id="copyToast">Copied to clipboard</div>
1231
+
1232
+ <script>
1233
+ function copyCmd(text) {
1234
+ navigator.clipboard.writeText(text);
1235
+ showToast();
1236
+ }
1237
+
1238
+ function copyInstall() {
1239
+ navigator.clipboard.writeText('npm install -g @agent-link/agent && agentlink-client start -D');
1240
+ showToast();
1241
+ }
1242
+
1243
+ function showToast() {
1244
+ const toast = document.getElementById('copyToast');
1245
+ toast.classList.add('show');
1246
+ setTimeout(() => toast.classList.remove('show'), 1800);
1247
+ }
1248
+
1249
+ // Scroll reveal
1250
+ const observer = new IntersectionObserver((entries) => {
1251
+ entries.forEach(entry => {
1252
+ if (entry.isIntersecting) {
1253
+ entry.target.classList.add('visible');
1254
+ }
1255
+ });
1256
+ }, { threshold: 0.1, rootMargin: '0px 0px -50px 0px' });
1257
+
1258
+ document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
1259
+ </script>
1260
+
1261
+ </body>
1262
+ </html>