Compare commits
6 Commits
5726d2d210
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a3fd57314 | ||
|
|
1de053a066 | ||
|
|
1205191348 | ||
|
|
477e7dfb4f | ||
|
|
bc21fa97ad | ||
|
|
0ee456ad58 |
5
.gitignore
vendored
@@ -5,4 +5,7 @@ out/
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
.vercel
|
||||
.env
|
||||
.env
|
||||
greywall-logo-negative.png
|
||||
greywall-logo-positive.png
|
||||
terminal.png
|
||||
@@ -49,8 +49,8 @@
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif;
|
||||
--font-serif: 'Source Serif 4', 'Source Serif Pro', Georgia, serif;
|
||||
--font-sans: var(--font-inter), 'Inter', ui-sans-serif, system-ui, sans-serif;
|
||||
--font-serif: var(--font-source-serif), 'Source Serif 4', 'Source Serif Pro', Georgia, serif;
|
||||
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||
|
||||
--color-background: rgb(var(--background));
|
||||
|
||||
@@ -3,8 +3,35 @@ import type { Metadata } from 'next'
|
||||
export const metadata: Metadata = {
|
||||
title: 'Greyscan | Greywall',
|
||||
description: 'Scan your repo and see what an unrestricted AI agent would attempt. Powered by Greywall.',
|
||||
alternates: {
|
||||
canonical: 'https://greywall.io/greyscan',
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Greyscan | Greywall',
|
||||
description: 'Scan your repo and see what an unrestricted AI agent would attempt. Powered by Greywall.',
|
||||
url: 'https://greywall.io/greyscan',
|
||||
siteName: 'Greywall',
|
||||
type: 'website',
|
||||
},
|
||||
}
|
||||
|
||||
const breadcrumbJsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'BreadcrumbList',
|
||||
itemListElement: [
|
||||
{ '@type': 'ListItem', position: 1, name: 'Greywall', item: 'https://greywall.io' },
|
||||
{ '@type': 'ListItem', position: 2, name: 'Greyscan', item: 'https://greywall.io/greyscan' },
|
||||
],
|
||||
}
|
||||
|
||||
export default function ExposureLayout({ children }: { children: React.ReactNode }) {
|
||||
return children
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbJsonLd) }}
|
||||
/>
|
||||
{children}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,26 @@
|
||||
import type { Metadata } from 'next'
|
||||
import { Inter, Source_Serif_4 } from 'next/font/google'
|
||||
import './globals.css'
|
||||
|
||||
const inter = Inter({
|
||||
subsets: ['latin'],
|
||||
display: 'swap',
|
||||
variable: '--font-inter',
|
||||
})
|
||||
|
||||
const sourceSerif = Source_Serif_4({
|
||||
subsets: ['latin'],
|
||||
display: 'swap',
|
||||
variable: '--font-source-serif',
|
||||
style: ['normal', 'italic'],
|
||||
axes: ['opsz'],
|
||||
})
|
||||
|
||||
export const metadata: Metadata = {
|
||||
metadataBase: new URL('https://greywall.io'),
|
||||
title: 'Greywall: Sandbox for AI Agents',
|
||||
description:
|
||||
'Container-free, default-deny sandboxing with observability for AI agents. Five layers of defense in one command.',
|
||||
'Container-free, default-deny sandboxing with real-time observability for AI agents on Linux and macOS. Five kernel-enforced security layers in one command. Open source.',
|
||||
icons: {
|
||||
icon: [
|
||||
{ url: '/icon.svg', type: 'image/svg+xml' },
|
||||
@@ -13,6 +29,76 @@ export const metadata: Metadata = {
|
||||
],
|
||||
apple: '/apple-icon.png',
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Greywall: Sandbox for AI Agents',
|
||||
description: 'Container-free, default-deny sandboxing with real-time observability for AI agents. Five kernel-enforced security layers in one command.',
|
||||
url: 'https://greywall.io',
|
||||
siteName: 'Greywall',
|
||||
type: 'website',
|
||||
images: [{ url: '/og-image.png', width: 1200, height: 630 }],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Greywall: Sandbox for AI Agents',
|
||||
description: 'Container-free, default-deny sandboxing with real-time observability for AI agents. Five kernel-enforced security layers in one command.',
|
||||
images: ['/og-image.png'],
|
||||
},
|
||||
alternates: {
|
||||
canonical: 'https://greywall.io',
|
||||
},
|
||||
}
|
||||
|
||||
const jsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@graph': [
|
||||
{
|
||||
'@type': 'Organization',
|
||||
'@id': 'https://greyhaven.co/#organization',
|
||||
name: 'Greyhaven',
|
||||
url: 'https://greyhaven.co',
|
||||
logo: { '@type': 'ImageObject', url: 'https://greywall.io/icon.svg' },
|
||||
sameAs: ['https://github.com/GreyhavenHQ'],
|
||||
},
|
||||
{
|
||||
'@type': 'WebSite',
|
||||
'@id': 'https://greywall.io/#website',
|
||||
name: 'Greywall',
|
||||
url: 'https://greywall.io',
|
||||
publisher: { '@id': 'https://greyhaven.co/#organization' },
|
||||
},
|
||||
{
|
||||
'@type': 'SoftwareApplication',
|
||||
'@id': 'https://greywall.io/#software',
|
||||
name: 'Greywall',
|
||||
description:
|
||||
'Container-free, default-deny sandboxing with real-time observability and dynamic controls for AI agents on Linux and macOS.',
|
||||
applicationCategory: 'SecurityApplication',
|
||||
operatingSystem: 'Linux, macOS',
|
||||
url: 'https://greywall.io',
|
||||
downloadUrl: 'https://github.com/GreyhavenHQ/greywall',
|
||||
license: 'https://opensource.org/licenses/Apache-2.0',
|
||||
offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' },
|
||||
author: { '@id': 'https://greyhaven.co/#organization' },
|
||||
featureList: [
|
||||
'Filesystem isolation',
|
||||
'Network isolation',
|
||||
'Command blocking',
|
||||
'Real-time violation monitoring',
|
||||
'Learning mode',
|
||||
'Syscall filtering',
|
||||
'Dynamic allow/deny controls',
|
||||
],
|
||||
isAccessibleForFree: true,
|
||||
},
|
||||
{
|
||||
'@type': 'SoftwareSourceCode',
|
||||
name: 'Greywall',
|
||||
codeRepository: 'https://github.com/GreyhavenHQ/greywall',
|
||||
programmingLanguage: 'Go',
|
||||
license: 'https://opensource.org/licenses/Apache-2.0',
|
||||
targetProduct: { '@id': 'https://greywall.io/#software' },
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export default function RootLayout({
|
||||
@@ -21,13 +107,11 @@ export default function RootLayout({
|
||||
children: React.ReactNode
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en" className="dark">
|
||||
<html lang="en" className={`dark ${inter.variable} ${sourceSerif.variable}`}>
|
||||
<head>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Source+Serif+4:ital,opsz,wght@0,8..60,400;0,8..60,500;0,8..60,600;0,8..60,700;1,8..60,400;1,8..60,600;1,8..60,700&display=swap"
|
||||
rel="stylesheet"
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
</head>
|
||||
<body className="font-sans antialiased bg-background text-foreground">
|
||||
|
||||
@@ -11,6 +11,7 @@ import { Observability } from '@/components/observability'
|
||||
import { Control } from '@/components/control'
|
||||
import { Comparison } from '@/components/comparison'
|
||||
import { About } from '@/components/about'
|
||||
import { FAQ } from '@/components/faq'
|
||||
import { Footer } from '@/components/footer'
|
||||
|
||||
export default function Home() {
|
||||
@@ -27,6 +28,7 @@ export default function Home() {
|
||||
<Comparison />
|
||||
<GettingStarted />
|
||||
<About />
|
||||
<FAQ />
|
||||
<Footer />
|
||||
</main>
|
||||
</PlatformProvider>
|
||||
|
||||
118
app/privacy/page.tsx
Normal file
@@ -0,0 +1,118 @@
|
||||
import type { Metadata } from 'next'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Privacy Policy | Greywall',
|
||||
description: 'How Greywall handles your data.',
|
||||
alternates: {
|
||||
canonical: 'https://greywall.io/privacy',
|
||||
},
|
||||
}
|
||||
|
||||
export default function PrivacyPage() {
|
||||
return (
|
||||
<main className="min-h-screen pt-24 pb-16 px-4 sm:px-6">
|
||||
<article className="mx-auto max-w-2xl">
|
||||
<h1 className="font-serif text-3xl sm:text-4xl font-semibold tracking-tight mb-2">
|
||||
Privacy Policy
|
||||
</h1>
|
||||
<p className="text-sm text-muted-foreground font-sans mb-12">
|
||||
Last updated: March 19, 2026
|
||||
</p>
|
||||
|
||||
<div className="space-y-10 text-muted-foreground font-serif text-base leading-relaxed">
|
||||
<section>
|
||||
<h2 className="font-serif text-xl font-semibold text-foreground mb-3">Greywall (the CLI tool)</h2>
|
||||
<p>
|
||||
Greywall runs entirely on your machine. It does not phone home, collect telemetry,
|
||||
or transmit any data. No analytics, no crash reports, no usage tracking. The source
|
||||
code is open and auditable
|
||||
at <a href="https://github.com/GreyhavenHQ/greywall" target="_blank" rel="noopener noreferrer" className="text-primary hover:text-primary/80 transition-colors">github.com/GreyhavenHQ/greywall</a>.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="font-serif text-xl font-semibold text-foreground mb-3">This website (greywall.io)</h2>
|
||||
<p className="mb-4">
|
||||
The Greywall landing page is a static site hosted on Vercel. We do not use cookies,
|
||||
analytics scripts, or tracking pixels. Vercel may collect minimal server logs
|
||||
(IP address, user agent, timestamp) as part of standard web hosting.
|
||||
See <a href="https://vercel.com/legal/privacy-policy" target="_blank" rel="noopener noreferrer" className="text-primary hover:text-primary/80 transition-colors">Vercel's privacy policy</a> for
|
||||
details.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="font-serif text-xl font-semibold text-foreground mb-3">Greyscan</h2>
|
||||
<p className="mb-4">
|
||||
When you use Greyscan at <a href="/greyscan" className="text-primary hover:text-primary/80 transition-colors">/greyscan</a>,
|
||||
the following happens:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2">
|
||||
<li>
|
||||
Your browser fetches the public file tree, dependency list, and README from GitHub's
|
||||
API directly. This data never passes through our servers during collection.
|
||||
</li>
|
||||
<li>
|
||||
To generate the threat report, a summary of the repo structure (file names,
|
||||
detected stack, dependency names, and up to 8,000 characters of the README) is
|
||||
sent to our server and forwarded to a third-party LLM provider for analysis.
|
||||
</li>
|
||||
<li>
|
||||
Results are cached in server memory for up to 24 hours to avoid redundant
|
||||
LLM calls for the same repository, then discarded. We do not persist scan
|
||||
results to disk or a database.
|
||||
</li>
|
||||
<li>
|
||||
No repository source code is read or transmitted. Only file paths, dependency
|
||||
names, and the public README are included.
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="font-serif text-xl font-semibold text-foreground mb-3">Third-party services</h2>
|
||||
<ul className="list-disc pl-6 space-y-2">
|
||||
<li>
|
||||
<span className="text-foreground font-medium">GitHub API</span> — Greyscan
|
||||
calls the GitHub REST API from your browser to fetch public repository metadata.
|
||||
Subject to <a href="https://docs.github.com/en/site-policy/privacy-policies/github-general-privacy-statement" target="_blank" rel="noopener noreferrer" className="text-primary hover:text-primary/80 transition-colors">GitHub's privacy statement</a>.
|
||||
</li>
|
||||
<li>
|
||||
<span className="text-foreground font-medium">LLM provider</span> — Repo
|
||||
summaries sent through Greyscan are processed by a third-party LLM to generate
|
||||
threat reports. The provider may retain data per their own policies.
|
||||
</li>
|
||||
<li>
|
||||
<span className="text-foreground font-medium">Vercel</span> — Hosting
|
||||
infrastructure. See <a href="https://vercel.com/legal/privacy-policy" target="_blank" rel="noopener noreferrer" className="text-primary hover:text-primary/80 transition-colors">Vercel's privacy policy</a>.
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="font-serif text-xl font-semibold text-foreground mb-3">Security</h2>
|
||||
<p>
|
||||
If you discover a security issue in Greywall or this website, please report it
|
||||
via <a href="https://github.com/GreyhavenHQ/greywall/security" target="_blank" rel="noopener noreferrer" className="text-primary hover:text-primary/80 transition-colors">GitHub Security Advisories</a>.
|
||||
We will respond promptly.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="font-serif text-xl font-semibold text-foreground mb-3">Contact</h2>
|
||||
<p>
|
||||
For questions about this policy,
|
||||
reach us at <a href="https://greyhaven.co/contact" target="_blank" rel="noopener noreferrer" className="text-primary hover:text-primary/80 transition-colors">greyhaven.co/contact</a>.
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div className="mt-16 pt-8 border-t border-border/30">
|
||||
<a href="/" className="text-sm text-muted-foreground hover:text-foreground transition-colors font-sans">
|
||||
← Back to Greywall
|
||||
</a>
|
||||
</div>
|
||||
</article>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
9
app/sitemap.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import type { MetadataRoute } from 'next'
|
||||
|
||||
export default function sitemap(): MetadataRoute.Sitemap {
|
||||
return [
|
||||
{ url: 'https://greywall.io', lastModified: new Date(), changeFrequency: 'weekly', priority: 1 },
|
||||
{ url: 'https://greywall.io/greyscan', lastModified: new Date(), changeFrequency: 'monthly', priority: 0.8 },
|
||||
{ url: 'https://greywall.io/privacy', lastModified: new Date(), changeFrequency: 'yearly', priority: 0.3 },
|
||||
]
|
||||
}
|
||||
@@ -31,7 +31,79 @@ export function About() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-16 border-t border-border/30 pt-16">
|
||||
{/* Team */}
|
||||
<div className="mt-16 border-t border-border/30 pt-16 mb-16">
|
||||
<h3 className="font-serif text-2xl sm:text-3xl font-semibold tracking-tight mb-8">
|
||||
The people behind it.
|
||||
</h3>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4 sm:gap-6">
|
||||
<a
|
||||
href="https://github.com/cowpig"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-start gap-3 p-4 rounded-lg border border-border/40 bg-card/30 hover:border-primary/20 transition-all"
|
||||
>
|
||||
<img
|
||||
src="https://github.com/cowpig.png?size=64"
|
||||
alt="Max McCrea"
|
||||
width={40}
|
||||
height={40}
|
||||
className="rounded-md shrink-0 bg-muted mt-0.5"
|
||||
/>
|
||||
<div>
|
||||
<div className="font-sans font-semibold text-sm text-foreground">Max McCrea</div>
|
||||
<div className="text-xs text-primary font-sans font-medium">CEO & Founder, Greyhaven</div>
|
||||
<p className="text-xs text-muted-foreground font-serif mt-1.5 leading-relaxed">
|
||||
AI researcher, Recurse Center alumnus. Built Monadical since 2016. Now building sovereign AI infrastructure.
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
href="https://github.com/nikitalokhmachev-ai"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-start gap-3 p-4 rounded-lg border border-border/40 bg-card/30 hover:border-primary/20 transition-all"
|
||||
>
|
||||
<img
|
||||
src="https://github.com/nikitalokhmachev-ai.png?size=64"
|
||||
alt="Nikita Lokhmachev"
|
||||
width={40}
|
||||
height={40}
|
||||
className="rounded-md shrink-0 bg-muted mt-0.5"
|
||||
/>
|
||||
<div>
|
||||
<div className="font-sans font-semibold text-sm text-foreground">Nikita Lokhmachev</div>
|
||||
<div className="text-xs text-primary font-sans font-medium">Technical Product Lead</div>
|
||||
<p className="text-xs text-muted-foreground font-serif mt-1.5 leading-relaxed">
|
||||
Former startup CTO, Fulbright scholar. Leads AI tooling and process engineering.
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
href="https://github.com/tito"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-start gap-3 p-4 rounded-lg border border-border/40 bg-card/30 hover:border-primary/20 transition-all"
|
||||
>
|
||||
<img
|
||||
src="https://github.com/tito.png?size=64"
|
||||
alt="Mathieu Virbel"
|
||||
width={40}
|
||||
height={40}
|
||||
className="rounded-md shrink-0 bg-muted mt-0.5"
|
||||
/>
|
||||
<div>
|
||||
<div className="font-sans font-semibold text-sm text-foreground">Mathieu Virbel</div>
|
||||
<div className="text-xs text-primary font-sans font-medium">Senior Team Lead</div>
|
||||
<p className="text-xs text-muted-foreground font-serif mt-1.5 leading-relaxed">
|
||||
Creator of <a href="https://github.com/kivy/kivy" target="_blank" rel="noopener noreferrer" className="text-foreground hover:text-primary transition-colors">Kivy</a> (19k+ stars). Full stack engineer, GSoC mentor.
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-t border-border/30 pt-16">
|
||||
<h3 className="font-serif text-2xl sm:text-3xl font-semibold tracking-tight mb-4">
|
||||
Need more than sandboxing?
|
||||
</h3>
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import Image from 'next/image'
|
||||
import { CheckCircle2 } from 'lucide-react'
|
||||
|
||||
const agents = [
|
||||
{ name: 'Claude Code', org: 'anthropics', url: 'https://docs.anthropic.com/en/docs/claude-code' },
|
||||
{ name: 'Codex', org: 'openai', url: 'https://github.com/openai/codex' },
|
||||
{ name: 'Cursor', org: 'getcursor', url: 'https://cursor.com' },
|
||||
{ name: 'Aider', org: 'Aider-AI', url: 'https://aider.chat' },
|
||||
{ name: 'Goose', org: 'block', url: 'https://github.com/block/goose' },
|
||||
{ name: 'Amp', org: 'sourcegraph', url: 'https://ampcode.com' },
|
||||
{ name: 'Gemini CLI', org: 'google-gemini', url: 'https://github.com/google-gemini/gemini-cli' },
|
||||
{ name: 'Cline', org: 'cline', url: 'https://cline.bot' },
|
||||
{ name: 'OpenCode', org: 'nicepkg', url: 'https://opencode.ai/' },
|
||||
{ name: 'Copilot', org: 'github', url: 'https://github.com/features/copilot' },
|
||||
{ name: 'Claude Code', icon: '/agents/anthropics.png', url: 'https://docs.anthropic.com/en/docs/claude-code' },
|
||||
{ name: 'Codex', icon: '/agents/openai.png', url: 'https://github.com/openai/codex' },
|
||||
{ name: 'Cursor', icon: '/agents/getcursor.png', url: 'https://cursor.com' },
|
||||
{ name: 'Aider', icon: '/agents/aider-ai.png', url: 'https://aider.chat' },
|
||||
{ name: 'Goose', icon: '/agents/block.png', url: 'https://github.com/block/goose' },
|
||||
{ name: 'Amp', icon: '/agents/sourcegraph.png', url: 'https://ampcode.com' },
|
||||
{ name: 'Gemini CLI', icon: '/agents/google-gemini.png', url: 'https://github.com/google-gemini/gemini-cli' },
|
||||
{ name: 'Cline', icon: '/agents/cline.png', url: 'https://cline.bot' },
|
||||
{ name: 'OpenCode', icon: '/agents/nicepkg.png', url: 'https://opencode.ai/' },
|
||||
{ name: 'Copilot', icon: '/agents/github.png', url: 'https://github.com/features/copilot' },
|
||||
]
|
||||
|
||||
export function Agents() {
|
||||
@@ -42,8 +43,8 @@ export function Agents() {
|
||||
rel="noopener noreferrer"
|
||||
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`}
|
||||
<Image
|
||||
src={agent.icon}
|
||||
alt={agent.name}
|
||||
width={28}
|
||||
height={28}
|
||||
|
||||
@@ -109,22 +109,22 @@ const rows: Row[] = [
|
||||
function CellIcon({ value }: { value: CellValue }) {
|
||||
if (value === 'yes') {
|
||||
return (
|
||||
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-green-400/10">
|
||||
<Check className="h-3 w-3 text-green-400" />
|
||||
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-green-400/10" aria-label="Supported">
|
||||
<Check className="h-3 w-3 text-green-400" aria-hidden="true" />
|
||||
</span>
|
||||
)
|
||||
}
|
||||
if (value === 'no') {
|
||||
return (
|
||||
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-red-400/10">
|
||||
<X className="h-3 w-3 text-red-400/70" />
|
||||
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-red-400/10" aria-label="Not supported">
|
||||
<X className="h-3 w-3 text-red-400/70" aria-hidden="true" />
|
||||
</span>
|
||||
)
|
||||
}
|
||||
if (value === 'partial') {
|
||||
return (
|
||||
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-yellow-400/10">
|
||||
<Minus className="h-3 w-3 text-yellow-400/70" />
|
||||
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-yellow-400/10" aria-label="Partial support">
|
||||
<Minus className="h-3 w-3 text-yellow-400/70" aria-hidden="true" />
|
||||
</span>
|
||||
)
|
||||
}
|
||||
@@ -214,19 +214,19 @@ export function Comparison() {
|
||||
<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">
|
||||
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-green-400/10">
|
||||
<Check className="h-3 w-3 text-green-400" />
|
||||
<Check className="h-3 w-3 text-green-400" aria-hidden="true" />
|
||||
</span>
|
||||
Supported
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-yellow-400/10">
|
||||
<Minus className="h-3 w-3 text-yellow-400/70" />
|
||||
<Minus className="h-3 w-3 text-yellow-400/70" aria-hidden="true" />
|
||||
</span>
|
||||
Partial
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-red-400/10">
|
||||
<X className="h-3 w-3 text-red-400/70" />
|
||||
<X className="h-3 w-3 text-red-400/70" aria-hidden="true" />
|
||||
</span>
|
||||
Not supported
|
||||
</div>
|
||||
|
||||
120
components/faq.tsx
Normal file
@@ -0,0 +1,120 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { HelpCircle, ChevronDown } from 'lucide-react'
|
||||
|
||||
const faqs = [
|
||||
{
|
||||
question: 'What is Greywall?',
|
||||
answer:
|
||||
'Greywall is a command-line tool that sandboxes AI coding agents. You wrap your agent in it — <code>greywall -- claude</code> — and it enforces a default-deny security policy at the kernel level. The agent can read and write your project files, but it cannot touch your SSH keys, read your .env, or make network calls you haven\'t approved. It works on Linux and macOS, requires no containers, and is open source under the Apache 2.0 license. The basic promise is modest: your AI assistant should not have more access to your computer than you would give a stranger at a coffee shop.',
|
||||
},
|
||||
{
|
||||
question: 'How do I sandbox my AI coding agent?',
|
||||
answer:
|
||||
'Install Greywall, then prefix your command: <code>greywall -- claude</code>, <code>greywall -- opencode</code>, or any other CLI agent. That is the whole process. Greywall operates at the OS level, so it does not need plugins, extensions, or agent-specific configuration. The agent launches inside a kernel-enforced sandbox and runs normally — it just cannot reach things you have not explicitly allowed. If you want to see what the agent is trying to access, open the GreyProxy dashboard.',
|
||||
},
|
||||
{
|
||||
question: 'How is Greywall different from running agents in Docker?',
|
||||
answer:
|
||||
'Containers were designed to ship software, not to babysit it. When you run an AI agent inside Docker, you get isolation, but you lose access to your local tools, editor integrations, and filesystem. Every dependency change means rebuilding an image. Greywall takes a different approach: the agent runs natively on your machine with full access to your toolchain, but the kernel enforces boundaries around what it can reach. Think of it as the difference between locking someone in a room versus letting them walk around the house with certain doors locked. You also get real-time visibility into what the agent is doing, which Docker does not offer.',
|
||||
},
|
||||
{
|
||||
question: 'Does Greywall work on macOS?',
|
||||
answer:
|
||||
'Yes. On macOS, Greywall uses Seatbelt — Apple\'s built-in kernel sandbox, the same one that constrains App Store applications. It generates a deny-by-default sandbox profile for each session, covering filesystem access, network connections, and IPC. Network traffic is routed through GreyProxy via environment variables. On Linux, there are more layers available (Bubblewrap, Landlock, Seccomp BPF, eBPF, and a TUN device for network capture), but the macOS implementation provides strong isolation using only built-in OS capabilities. No additional packages required.',
|
||||
},
|
||||
{
|
||||
question: 'Is Greywall open source?',
|
||||
answer:
|
||||
'Yes. Apache 2.0 license, source code on <a href="https://github.com/GreyhavenHQ/greywall" target="_blank" rel="noopener noreferrer">GitHub</a>. For a security tool, this is not a philosophical position so much as a practical necessity. You should be able to read the code that stands between an AI agent and your production credentials. Greywall is built by <a href="https://greyhaven.co" target="_blank" rel="noopener noreferrer">Greyhaven</a>, who use it in their own production deployments. As the saying goes — never trust a lock you cannot pick apart.',
|
||||
},
|
||||
{
|
||||
question: 'What kernel version does Linux require?',
|
||||
answer:
|
||||
'The minimum is Linux 3.8 for namespace isolation via Bubblewrap. Landlock filesystem controls need 5.13. Seccomp BPF needs 3.5. eBPF monitoring needs 4.15. The network proxy works on any kernel. Greywall detects what your system supports at runtime and activates every available layer. If you are on a reasonably modern distribution — anything from the last few years — you will get all five layers. Run <code>greywall --linux-features</code> to see what is available. The tool degrades gracefully rather than refusing to start, which is a courtesy more software should extend.',
|
||||
},
|
||||
{
|
||||
question: 'Which AI agents does Greywall support?',
|
||||
answer:
|
||||
'All of them. Claude Code, Codex, Cursor, Aider, Goose, Amp, Gemini CLI, Cline, OpenCode, Copilot — anything that runs as a process on your machine. Greywall does not need agent-specific configuration because it operates at the OS level, below the agent. The agent does not know it is sandboxed, which is, in a way, the whole point. It simply discovers that certain operations fail, adapts, and carries on with its work. Most of the time, this is exactly what you wanted it to do in the first place.',
|
||||
},
|
||||
]
|
||||
|
||||
const faqJsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'FAQPage',
|
||||
mainEntity: faqs.map((faq) => ({
|
||||
'@type': 'Question',
|
||||
name: faq.question,
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: faq.answer.replace(/<[^>]*>/g, ''),
|
||||
},
|
||||
})),
|
||||
}
|
||||
|
||||
function FAQItem({ question, answer }: { question: string; answer: string }) {
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
return (
|
||||
<div className="border-b border-border/30">
|
||||
<button
|
||||
onClick={() => setOpen(!open)}
|
||||
className="w-full flex items-center justify-between gap-4 py-5 text-left cursor-pointer"
|
||||
>
|
||||
<h3 className="font-serif text-base sm:text-lg font-semibold text-foreground">
|
||||
{question}
|
||||
</h3>
|
||||
<ChevronDown
|
||||
className={`h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200 ${
|
||||
open ? 'rotate-180' : ''
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
<div
|
||||
className={`grid transition-[grid-template-rows] duration-200 ${
|
||||
open ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]'
|
||||
}`}
|
||||
>
|
||||
<div className="overflow-hidden">
|
||||
<p
|
||||
className="pb-5 text-muted-foreground font-serif text-base leading-relaxed [&_code]:font-mono [&_code]:text-xs [&_code]:text-foreground [&_code]:bg-card/50 [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:rounded [&_a]:text-primary [&_a]:hover:text-primary/80 [&_a]:transition-colors"
|
||||
dangerouslySetInnerHTML={{ __html: answer }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function FAQ() {
|
||||
return (
|
||||
<section className="py-24 px-4 sm:px-6 border-t border-border/30">
|
||||
<div className="mx-auto max-w-5xl">
|
||||
<div className="max-w-2xl mb-12">
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<HelpCircle className="h-4 w-4 text-primary" />
|
||||
<span className="text-xs font-sans uppercase tracking-wider text-primary font-medium">
|
||||
Questions
|
||||
</span>
|
||||
</div>
|
||||
<h2 className="font-serif text-3xl sm:text-4xl font-semibold tracking-tight mb-4">
|
||||
Frequently asked.
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="max-w-3xl">
|
||||
{faqs.map((faq) => (
|
||||
<FAQItem key={faq.question} question={faq.question} answer={faq.answer} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(faqJsonLd) }}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -32,6 +32,12 @@ export function Footer() {
|
||||
>
|
||||
greyhaven.co
|
||||
</a>
|
||||
<a
|
||||
href="/privacy"
|
||||
className="hover:text-foreground transition-colors"
|
||||
>
|
||||
Privacy
|
||||
</a>
|
||||
<span>Apache 2.0</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,9 +17,23 @@ export function Hero() {
|
||||
<h1 className="font-serif text-4xl sm:text-5xl md:text-6xl font-semibold tracking-tight leading-[1.1] mb-6">
|
||||
<em className="italic text-primary">Greywall</em> your agent & let it cook.
|
||||
</h1>
|
||||
<p className="text-lg text-muted-foreground leading-relaxed max-w-2xl mx-auto font-serif">
|
||||
<p className="text-lg text-muted-foreground leading-relaxed max-w-2xl mx-auto font-serif mb-6">
|
||||
Container-free sandboxing with real-time observability & dynamic controls, for Linux & MacOS.
|
||||
</p>
|
||||
<div className="inline-flex items-center gap-2 flex-wrap justify-center">
|
||||
<a href="https://github.com/GreyhavenHQ/greywall" target="_blank" rel="noopener noreferrer">
|
||||
<img src="https://img.shields.io/github/stars/GreyhavenHQ/greywall?style=flat&color=D95E2A&labelColor=161614&logo=github&logoColor=white" alt="GitHub stars" className="h-5" />
|
||||
</a>
|
||||
<a href="https://github.com/GreyhavenHQ/greywall/blob/main/LICENSE" target="_blank" rel="noopener noreferrer">
|
||||
<img src="https://img.shields.io/github/license/GreyhavenHQ/greywall?style=flat&color=D95E2A&labelColor=161614" alt="License" className="h-5" />
|
||||
</a>
|
||||
<a href="https://github.com/GreyhavenHQ/greywall/releases" target="_blank" rel="noopener noreferrer">
|
||||
<img src="https://img.shields.io/github/v/release/GreyhavenHQ/greywall?style=flat&color=D95E2A&labelColor=161614" alt="Latest release" className="h-5" />
|
||||
</a>
|
||||
<a href="https://github.com/GreyhavenHQ/greywall" target="_blank" rel="noopener noreferrer">
|
||||
<img src="https://img.shields.io/github/go-mod/go-version/GreyhavenHQ/greywall?style=flat&color=D95E2A&labelColor=161614" alt="Go version" className="h-5" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { useState, useEffect, useRef } from 'react'
|
||||
import Image from 'next/image'
|
||||
import { Eye } from 'lucide-react'
|
||||
|
||||
const slides = [
|
||||
@@ -97,20 +98,26 @@ export function Observability() {
|
||||
{/* Screenshot with crossfade */}
|
||||
<div className="relative rounded-lg border border-border/40 overflow-hidden bg-white">
|
||||
{/* Hidden reference image to lock container height */}
|
||||
<img
|
||||
<Image
|
||||
src={slides[0].src}
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
width={1977}
|
||||
height={1444}
|
||||
className="w-full h-auto invisible"
|
||||
priority
|
||||
/>
|
||||
{slides.map((slide, i) => (
|
||||
<img
|
||||
<Image
|
||||
key={slide.label}
|
||||
src={slide.src}
|
||||
alt={slide.alt}
|
||||
width={slide.src === '/pending_requests.png' ? 1752 : 1977}
|
||||
height={slide.src === '/pending_requests.png' ? 1216 : 1444}
|
||||
className={`absolute inset-0 w-full h-full object-contain object-top transition-opacity duration-700 ${
|
||||
i === active ? 'opacity-100' : 'opacity-0'
|
||||
}`}
|
||||
priority={i === 0}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -122,11 +122,22 @@ export function Problem() {
|
||||
<blockquote className="font-serif text-xl sm:text-2xl md:text-3xl font-semibold tracking-tight leading-snug mb-6">
|
||||
<span className="text-primary">“</span>The act of verification creates trust.<span className="text-primary">”</span>
|
||||
</blockquote>
|
||||
<p className="text-muted-foreground font-serif text-base sm:text-lg leading-relaxed max-w-2xl mx-auto">
|
||||
<p className="text-muted-foreground font-serif text-base sm:text-lg leading-relaxed max-w-2xl mx-auto mb-10">
|
||||
Greywall gives you two pillars: <span className="text-foreground font-medium">control</span> over
|
||||
what agents can reach, and <span className="text-foreground font-medium">clarity</span> into
|
||||
every operation they perform.
|
||||
</p>
|
||||
<div className="mx-auto max-w-3xl rounded-lg border border-border/40 overflow-hidden">
|
||||
<div className="relative w-full" style={{ paddingBottom: '56.25%' }}>
|
||||
<iframe
|
||||
src="https://www.youtube.com/embed/u7YFVGGpPRI"
|
||||
title="Greywall Demo"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
className="absolute inset-0 w-full h-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
typescript: {
|
||||
ignoreBuildErrors: true,
|
||||
},
|
||||
images: {
|
||||
unoptimized: true,
|
||||
remotePatterns: [
|
||||
{
|
||||
protocol: 'https',
|
||||
@@ -12,6 +8,19 @@ const nextConfig = {
|
||||
},
|
||||
],
|
||||
},
|
||||
async headers() {
|
||||
return [
|
||||
{
|
||||
source: '/(.*)',
|
||||
headers: [
|
||||
{ key: 'X-Frame-Options', value: 'DENY' },
|
||||
{ key: 'X-Content-Type-Options', value: 'nosniff' },
|
||||
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
|
||||
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
|
||||
],
|
||||
},
|
||||
]
|
||||
},
|
||||
}
|
||||
|
||||
export default nextConfig
|
||||
|
||||
BIN
public/agents/aider-ai.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
public/agents/anthropics.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
public/agents/block.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
public/agents/cline.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
public/agents/getcursor.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
public/agents/github.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
public/agents/google-gemini.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
public/agents/nicepkg.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
public/agents/openai.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
public/agents/sourcegraph.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 0 B After Width: | Height: | Size: 850 B |
|
Before Width: | Height: | Size: 585 B After Width: | Height: | Size: 850 B |
|
Before Width: | Height: | Size: 566 B After Width: | Height: | Size: 850 B |
30
public/llms.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
# Greywall
|
||||
|
||||
> Container-free, default-deny sandboxing with real-time observability for AI agents on Linux and macOS.
|
||||
|
||||
Greywall is an open-source CLI tool that wraps any AI agent (Claude Code, Codex, Cursor, Aider, and others) in a kernel-enforced sandbox. It uses five security layers on Linux (Bubblewrap namespaces, Landlock filesystem, Seccomp BPF syscall filtering, eBPF monitoring, and TUN+SOCKS5 network proxy) and four on macOS (Seatbelt sandbox, filesystem policy, log stream monitor, and proxy-based network control). Default-deny policy means nothing is accessible unless explicitly granted. Built by Greyhaven, licensed Apache 2.0.
|
||||
|
||||
## Key Features
|
||||
- Filesystem isolation (kernel-enforced read/write/deny per path)
|
||||
- Network isolation (all traffic routed through GreyProxy)
|
||||
- Command blocking (detects blocked commands in pipes, chains, nested shells)
|
||||
- Real-time violation monitoring (every denial captured with full context)
|
||||
- Learning mode (auto-generates least-privilege templates from observed access)
|
||||
- Syscall filtering (blocks 27+ dangerous system calls via Seccomp BPF)
|
||||
- Dynamic allow/deny controls (adjust policies live without restarting)
|
||||
|
||||
## Links
|
||||
- [Homepage](https://greywall.io)
|
||||
- [Documentation](https://docs.greywall.io/)
|
||||
- [GitHub](https://github.com/GreyhavenHQ/greywall)
|
||||
- [Greyhaven (parent company)](https://greyhaven.co)
|
||||
|
||||
## Install
|
||||
- Homebrew: `brew tap greyhavenhq/tap && brew install greywall`
|
||||
- Curl: `curl -fsSL https://raw.githubusercontent.com/GreyhavenHQ/greywall/main/install.sh | sh`
|
||||
- Go: `go install github.com/GreyhavenHQ/greywall/cmd/greywall@latest`
|
||||
|
||||
## Compatibility
|
||||
Works with: Claude Code, Codex, Cursor, Aider, Goose, Amp, Gemini CLI, Cline, OpenCode, Copilot.
|
||||
Platforms: Linux (3.8+), macOS.
|
||||
License: Apache 2.0.
|
||||
BIN
public/og-image.png
Normal file
|
After Width: | Height: | Size: 104 KiB |
26
public/robots.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
User-agent: *
|
||||
Allow: /
|
||||
Disallow: /api/
|
||||
|
||||
User-agent: GPTBot
|
||||
Allow: /
|
||||
|
||||
User-agent: OAI-SearchBot
|
||||
Allow: /
|
||||
|
||||
User-agent: ClaudeBot
|
||||
Allow: /
|
||||
|
||||
User-agent: PerplexityBot
|
||||
Allow: /
|
||||
|
||||
User-agent: CCBot
|
||||
Disallow: /
|
||||
|
||||
User-agent: anthropic-ai
|
||||
Disallow: /
|
||||
|
||||
User-agent: cohere-ai
|
||||
Disallow: /
|
||||
|
||||
Sitemap: https://greywall.io/sitemap.xml
|
||||