also looking at this
feat(homepage): say what a text can actually do
#64
11 files
+149
-22
Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.
| @@ -73,6 +73,21 @@ const install = [ | ||
| 73 | 73 | { verb: 'Text it', body: 'Send yourself "ping" from your iPhone. The answer starts with a satellite.' }, |
| 74 | 74 | ] |
| 75 | 75 | |
| 76 | // What a text can actually do, and what cannot reach it. The page asks for | |
| 77 | // Full Disk Access and an unattended agent, and said nothing about either. | |
| 78 | const power = [ | |
| 79 | { title: 'Approvals are off', body: 'Nobody is at the Mac to answer a prompt, so there are none. Claude Code runs with bypassPermissions, Codex with bypass.' }, | |
| 80 | { title: 'It can read, write and run', body: 'Inside the directory your text names, with your permissions. The same authority you have at a terminal on that Mac.' }, | |
| 81 | { title: 'So your phone is the key', body: 'An unlocked phone with access to the allowed thread can command your Mac. Treat the allow list the way you treat an SSH key.' }, | |
| 82 | ] | |
| 83 | ||
| 84 | const limits = [ | |
| 85 | { title: 'iMessage only', body: 'SMS is refused outright. A forwarded SMS sender id can be spoofed through a bulk gateway, and the other side of that door is an agent with approvals off.' }, | |
| 86 | { title: 'One to one only', body: 'A group chat never reaches it, whoever is in it.' }, | |
| 87 | { title: 'Handles you allow', body: 'Empty means this Mac\'s own Messages handles, so a default install answers only you.' }, | |
| 88 | { title: 'Nothing stale', body: 'A text older than the catch-up window is not run, so a Mac waking up cannot replay a day of instructions.' }, | |
| 89 | ] | |
| 90 | ||
| 76 | 91 | const pricing = PLANS.map(plan => ({ ...plan, price: formatCents(plan.priceCents) })) |
| 77 | 92 | const yearlySaving = yearlySavingPercent() |
| 78 | 93 | |
| @@ -186,7 +201,7 @@ const faqs = [ | ||
| 186 | 201 | <div class="lg:sticky lg:top-28 lg:self-start"> |
| 187 | 202 | <p class="text-xs tracking-[0.18em] uppercase u-accent u-mono">How it works</p> |
| 188 | 203 | <h2 id="how-title" class="mt-3 font-semibold text-3xl tracking-tight md:text-4xl">From a text to an agent session, and back.</h2> |
| 189 | <p class="mt-4 max-w-[46ch] u-muted">No server in between. Your Mac reads the message, does the work and answers through Messages.</p> | |
| 204 | <p class="mt-4 max-w-[46ch] u-muted">Your Mac reads the message, does the work and answers through Messages. The agent sends your prompt to Anthropic or OpenAI under your own account, and <a href="/privacy" class="underline underline-offset-4 hover:opacity-80">nothing else leaves</a>.</p> | |
| 190 | 205 | </div> |
| 191 | 206 | <ol class="grid gap-10"> |
| 192 | 207 | @foreach(steps as step) |
| @@ -250,13 +265,54 @@ const faqs = [ | ||
| 250 | 265 | </span> |
| 251 | 266 | <div> |
| 252 | 267 | <h3 class="font-semibold text-xl">Nobody else can use it</h3> |
| 253 | <p class="mt-1 leading-relaxed u-muted">Only one-to-one chats with handles you allow. Group chats are ignored, and only Uplink.app gets Full Disk Access, not your terminal.</p> | |
| 268 | <p class="mt-1 leading-relaxed u-muted">Only one-to-one chats with handles you allow. Group chats are ignored, and only Uplink.app gets Full Disk Access, not your terminal. <a href="#security" class="underline underline-offset-4 hover:opacity-80">What a text can do</a>.</p> | |
| 254 | 269 | </div> |
| 255 | 270 | </article> |
| 256 | 271 | </div> |
| 257 | 272 | </div> |
| 258 | 273 | </section> |
| 259 | 274 | |
| 275 | <section id="security" class="border-t scroll-mt-16 u-line" aria-labelledby="security-title"> | |
| 276 | <div class="mx-auto px-4 py-20 sm:px-6 lg:py-28 max-w-6xl"> | |
| 277 | <p class="text-xs tracking-[0.18em] uppercase u-accent u-mono">Before you install it</p> | |
| 278 | <h2 id="security-title" class="mt-3 max-w-[20ch] font-semibold text-3xl tracking-tight md:text-4xl">A text runs a real agent, unattended.</h2> | |
| 279 | <p class="mt-4 max-w-[58ch] u-muted"> | |
| 280 | That is the product, and it is worth knowing before you point it at a Mac that matters. | |
| 281 | </p> | |
| 282 | ||
| 283 | <div class="grid gap-12 mt-14 lg:grid-cols-2 lg:gap-16"> | |
| 284 | <div> | |
| 285 | <h3 class="font-semibold text-lg">What a text can do</h3> | |
| 286 | <ul class="grid gap-5 mt-6"> | |
| 287 | @foreach(power as item) | |
| 288 | <li class="u-reveal"> | |
| 289 | <p class="font-medium">{{ item.title }}</p> | |
| 290 | <p class="mt-1 max-w-[52ch] leading-relaxed u-muted">{{ item.body }}</p> | |
| 291 | </li> | |
| 292 | @endforeach | |
| 293 | </ul> | |
| 294 | </div> | |
| 295 | ||
| 296 | <div> | |
| 297 | <h3 class="font-semibold text-lg">What cannot reach it</h3> | |
| 298 | <ul class="grid gap-5 mt-6"> | |
| 299 | @foreach(limits as item) | |
| 300 | <li class="u-reveal"> | |
| 301 | <p class="font-medium">{{ item.title }}</p> | |
| 302 | <p class="mt-1 max-w-[52ch] leading-relaxed u-muted">{{ item.body }}</p> | |
| 303 | </li> | |
| 304 | @endforeach | |
| 305 | </ul> | |
| 306 | </div> | |
| 307 | </div> | |
| 308 | ||
| 309 | <p class="mt-14 max-w-[58ch] u-muted"> | |
| 310 | Your prompt and whatever the agent reads go to Anthropic or OpenAI under your own account. Your texts go through Apple, as any iMessage does. A licence check reaches uplink.stacksjs.com every six hours and sends the key, nothing else. | |
| 311 | <a href="/privacy" class="underline underline-offset-4 hover:opacity-80">The whole of it is on the privacy page</a>. | |
| 312 | </p> | |
| 313 | </div> | |
| 314 | </section> | |
| 315 | ||
| 260 | 316 | <section id="download" class="border-t scroll-mt-16 u-line" aria-labelledby="download-title"> |
| 261 | 317 | <div class="grid gap-12 items-center lg:gap-16 lg:grid-cols-[1.1fr_0.9fr] mx-auto px-4 py-20 sm:px-6 lg:py-28 max-w-6xl"> |
| 262 | 318 | <div> |