ReviewOS

also looking at this

stacks/uplink

feat(homepage): say what a text can actually do

#64
Merged glennmichael123 wants to merge feat/say-what-a-text-can-do into main
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.

resources/partials/site-nav.stxmodified+1-0
Changes to resources/partials/site-nav.stx
@@ -14,6 +14,7 @@ const navDownloadUrl = release.url
1414 </a>
1515 <div class="flex gap-5 items-center text-sm sm:gap-6">
1616 <a href="/#how" class="hidden sm:inline hover:opacity-80 u-muted">How it works</a>
17 <a href="/#security" class="hidden lg:inline hover:opacity-80 u-muted">Security</a>
1718 @if(path === '/pricing')
1819 <a href="/pricing" class="hover:opacity-80 u-muted" aria-current="page">Pricing</a>
1920 @else
resources/views/index.stxmodified+58-2
Changes to resources/views/index.stx
@@ -73,6 +73,21 @@ const install = [
7373 { verb: 'Text it', body: 'Send yourself "ping" from your iPhone. The answer starts with a satellite.' },
7474]
7575
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.
78const 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
84const 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
7691const pricing = PLANS.map(plan => ({ ...plan, price: formatCents(plan.priceCents) }))
7792const yearlySaving = yearlySavingPercent()
7893
@@ -186,7 +201,7 @@ const faqs = [
186201 <div class="lg:sticky lg:top-28 lg:self-start">
187202 <p class="text-xs tracking-[0.18em] uppercase u-accent u-mono">How it works</p>
188203 <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>
190205 </div>
191206 <ol class="grid gap-10">
192207 @foreach(steps as step)
@@ -250,13 +265,54 @@ const faqs = [
250265 </span>
251266 <div>
252267 <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>
254269 </div>
255270 </article>
256271 </div>
257272 </div>
258273 </section>
259274
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
260316 <section id="download" class="border-t scroll-mt-16 u-line" aria-labelledby="download-title">
261317 <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">
262318 <div>