510 lines
31 KiB
Cheetah
510 lines
31 KiB
Cheetah
{{define "index"}}
|
|
<!-- Hero -->
|
|
<div class="container hero-split">
|
|
<div>
|
|
<p class="label accent mb-6">George Orwell — 1984</p>
|
|
<h1 class="mb-6">"If you want to keep a secret, you must also hide it from yourself."</h1>
|
|
<p class="lead mb-3">The only password manager for AI agents worth your trust.</p>
|
|
<p class="mb-6">We cannot read your passwords. Not <em>will not</em>. <strong>Cannot.</strong> Your Credential and Identity keys are derived from your hardware authenticator and baked into your tokens. Our servers hold ciphertext they have never had the means to decrypt.</p>
|
|
<div class="btn-row">
|
|
<a href="/hosted" class="btn btn-primary">Get hosted — <s>$20</s> $12/yr</a>
|
|
<a href="/install" class="btn btn-ghost">Self-host free →</a>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<!-- Hero SVG: Credential / Identity split -->
|
|
<svg viewBox="0 0 480 380" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<!-- Background -->
|
|
<rect x="0" y="0" width="480" height="380" rx="12" fill="#111f38"/>
|
|
|
|
<!-- Top labels -->
|
|
<text x="130" y="35" font-family="JetBrains Mono, monospace" font-size="11" fill="#94a3b8" text-anchor="middle">AI Agent</text>
|
|
<text x="350" y="35" font-family="JetBrains Mono, monospace" font-size="11" fill="#94a3b8" text-anchor="middle">You only</text>
|
|
|
|
<!-- Arrows -->
|
|
<path d="M130 42 L130 58" stroke="#22C55E" stroke-width="1.5" marker-end="url(#arrowGreen)"/>
|
|
<path d="M350 42 L350 58" stroke="#EF4444" stroke-width="1.5" marker-end="url(#arrowRed)"/>
|
|
<defs>
|
|
<marker id="arrowGreen" markerWidth="8" markerHeight="6" refX="4" refY="3" orient="auto"><path d="M0,0 L4,3 L0,6" fill="none" stroke="#22C55E" stroke-width="1.5"/></marker>
|
|
<marker id="arrowRed" markerWidth="8" markerHeight="6" refX="4" refY="3" orient="auto"><path d="M0,0 L4,3 L0,6" fill="none" stroke="#EF4444" stroke-width="1.5"/></marker>
|
|
</defs>
|
|
|
|
<!-- Credential Column -->
|
|
<rect x="30" y="65" width="200" height="260" rx="8" fill="none" stroke="#22C55E" stroke-width="1" stroke-opacity="0.3"/>
|
|
<rect x="30" y="65" width="200" height="30" rx="8" fill="#22C55E" fill-opacity="0.1"/>
|
|
<text x="130" y="82" font-family="JetBrains Mono, monospace" font-size="10" fill="#22C55E" text-anchor="middle" font-weight="600">Credential Encryption</text>
|
|
|
|
<!-- Credential items -->
|
|
<g>
|
|
<rect x="50" y="115" width="160" height="36" rx="6" fill="#0A1628"/>
|
|
<text x="80" y="138" font-family="JetBrains Mono, monospace" font-size="11" fill="#d1d5db">github_token</text>
|
|
<circle cx="192" cy="133" r="8" fill="#22C55E" fill-opacity="0.15"/>
|
|
<path d="M188 133 L190.5 135.5 L196 130" stroke="#22C55E" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
|
</g>
|
|
<g>
|
|
<rect x="50" y="163" width="160" height="36" rx="6" fill="#0A1628"/>
|
|
<text x="80" y="186" font-family="JetBrains Mono, monospace" font-size="11" fill="#d1d5db">ssh_key</text>
|
|
<circle cx="192" cy="181" r="8" fill="#22C55E" fill-opacity="0.15"/>
|
|
<path d="M188 181 L190.5 183.5 L196 178" stroke="#22C55E" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
|
</g>
|
|
<g>
|
|
<rect x="50" y="211" width="160" height="36" rx="6" fill="#0A1628"/>
|
|
<text x="80" y="234" font-family="JetBrains Mono, monospace" font-size="11" fill="#d1d5db">totp_github</text>
|
|
<circle cx="192" cy="229" r="8" fill="#22C55E" fill-opacity="0.15"/>
|
|
<path d="M188 229 L190.5 231.5 L196 226" stroke="#22C55E" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
|
</g>
|
|
<g>
|
|
<rect x="50" y="259" width="160" height="36" rx="6" fill="#0A1628"/>
|
|
<text x="80" y="282" font-family="JetBrains Mono, monospace" font-size="11" fill="#d1d5db">oauth_slack</text>
|
|
<circle cx="192" cy="277" r="8" fill="#22C55E" fill-opacity="0.15"/>
|
|
<path d="M188 277 L190.5 279.5 L196 274" stroke="#22C55E" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
|
</g>
|
|
|
|
<!-- Identity Column -->
|
|
<rect x="250" y="65" width="200" height="260" rx="8" fill="none" stroke="#EF4444" stroke-width="1" stroke-opacity="0.3"/>
|
|
<rect x="250" y="65" width="200" height="30" rx="8" fill="#EF4444" fill-opacity="0.1"/>
|
|
<text x="350" y="82" font-family="JetBrains Mono, monospace" font-size="10" fill="#EF4444" text-anchor="middle" font-weight="600">Identity Encryption</text>
|
|
|
|
<!-- Identity items -->
|
|
<g>
|
|
<rect x="270" y="115" width="160" height="36" rx="6" fill="#0A1628"/>
|
|
<text x="300" y="138" font-family="JetBrains Mono, monospace" font-size="11" fill="#d1d5db">credit_card</text>
|
|
<rect x="408" y="125" width="16" height="16" rx="3" fill="#EF4444" fill-opacity="0.15"/>
|
|
<path d="M413 131 L413 135 M416 131 L416 135 M411 133 L411 129 Q411 127 413 127 L416 127 Q418 127 418 129 L418 133 Z" stroke="#EF4444" stroke-width="1.2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
|
</g>
|
|
<g>
|
|
<rect x="270" y="163" width="160" height="36" rx="6" fill="#0A1628"/>
|
|
<text x="300" y="186" font-family="JetBrains Mono, monospace" font-size="11" fill="#d1d5db">cvv</text>
|
|
<rect x="408" y="173" width="16" height="16" rx="3" fill="#EF4444" fill-opacity="0.15"/>
|
|
<path d="M413 179 L413 183 M416 179 L416 183 M411 181 L411 177 Q411 175 413 175 L416 175 Q418 175 418 177 L418 181 Z" stroke="#EF4444" stroke-width="1.2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
|
</g>
|
|
<g>
|
|
<rect x="270" y="211" width="160" height="36" rx="6" fill="#0A1628"/>
|
|
<text x="300" y="234" font-family="JetBrains Mono, monospace" font-size="11" fill="#d1d5db">passport</text>
|
|
<rect x="408" y="221" width="16" height="16" rx="3" fill="#EF4444" fill-opacity="0.15"/>
|
|
<path d="M413 227 L413 231 M416 227 L416 231 M411 229 L411 225 Q411 223 413 223 L416 223 Q418 223 418 225 L418 229 Z" stroke="#EF4444" stroke-width="1.2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
|
</g>
|
|
<g>
|
|
<rect x="270" y="259" width="160" height="36" rx="6" fill="#0A1628"/>
|
|
<text x="300" y="282" font-family="JetBrains Mono, monospace" font-size="11" fill="#d1d5db">ssn</text>
|
|
<rect x="408" y="269" width="16" height="16" rx="3" fill="#EF4444" fill-opacity="0.15"/>
|
|
<path d="M413 275 L413 279 M416 275 L416 279 M411 277 L411 273 Q411 271 413 271 L416 271 Q418 271 418 273 L418 277 Z" stroke="#EF4444" stroke-width="1.2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
|
</g>
|
|
|
|
<!-- Center vault icon -->
|
|
<rect x="224" y="340" width="32" height="28" rx="4" fill="#111f38" stroke="#94a3b8" stroke-width="1"/>
|
|
<circle cx="240" cy="352" r="3" fill="none" stroke="#94a3b8" stroke-width="1"/>
|
|
<line x1="240" y1="355" x2="240" y2="360" stroke="#94a3b8" stroke-width="1"/>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
|
|
<hr class="divider">
|
|
|
|
<!-- The Problem -->
|
|
<div class="section container">
|
|
<h2 class="mb-4">The problem with every other password manager</h2>
|
|
<p class="lead mb-8">In 2022, attackers stole the entire vault database of a leading password manager. The encryption worked exactly as designed. Accounts are still being drained today — four years later. The problem was never the encryption. It was who held the key.</p>
|
|
<div class="grid-3">
|
|
<div class="card card-hover">
|
|
<div class="feature-icon red"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z"/></svg></div>
|
|
<h3 class="mb-3">They hold the key</h3>
|
|
<p>Every major password manager encrypts your vault — then stores a way to decrypt it. The company's servers have always had what it takes to read your passwords. You just hoped they wouldn't.</p>
|
|
</div>
|
|
<div class="card card-hover">
|
|
<div class="feature-icon red"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/></svg></div>
|
|
<h3 class="mb-3">Policy isn't protection</h3>
|
|
<p>"We will not read your passwords" is a promise. Promises can be broken, compelled, or hacked. Clavitor cannot read your Credential or Identity fields — not will not. <strong>Cannot.</strong> The key was never here.</p>
|
|
</div>
|
|
<div class="card card-hover">
|
|
<div class="feature-icon red"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg></div>
|
|
<h3 class="mb-3">AI agents need credentials now</h3>
|
|
<p>Your AI needs your GitHub token to deploy. It shouldn't also be able to see your passport. Every other manager is all-or-nothing. Clavitor gives agents exactly what they need — nothing more.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<hr class="divider">
|
|
|
|
<!-- How it works -->
|
|
<div class="section container">
|
|
<p class="label mb-4">How it works</p>
|
|
<h2 class="mb-6">"Your assistant can book your flights.<br><span class="gradient-text">Not read your diary.</span>"</h2>
|
|
<p class="lead mb-4">Everything in your vault is encrypted. What differs is who holds the key.</p>
|
|
<p class="mb-8">Vault Encryption covers everything — the server uses it to store and serve your data. Credential and Identity fields go further: those keys are derived from your hardware authenticator, baked into your tokens, and never sent to our servers. We hold the vault. We never got those keys.</p>
|
|
<div class="grid-3">
|
|
<div class="card alt">
|
|
<span class="badge mb-4" style="background:rgba(148,163,184,0.1);color:#94a3b8">Vault Encryption</span>
|
|
<h3 class="mb-3">Titles, URLs, usernames</h3>
|
|
<p class="mb-4">Server-readable. Encrypted at rest with the vault key. Needed for search, entry listing, and MCP tool responses.</p>
|
|
<ul class="checklist">
|
|
<li>Entry names & labels</li>
|
|
<li>URLs</li>
|
|
<li>Usernames</li>
|
|
<li>Tags & metadata</li>
|
|
</ul>
|
|
</div>
|
|
<div class="card alt">
|
|
<span class="badge accent mb-4">Credential Encryption</span>
|
|
<h3 class="mb-3">AI-readable secrets</h3>
|
|
<p class="mb-4">Encrypted client-side. The key lives in your agent tokens. The server stores ciphertext it has never had the means to decrypt.</p>
|
|
<ul class="checklist">
|
|
<li>API keys & tokens</li>
|
|
<li>SSH keys</li>
|
|
<li>TOTP 2FA seeds — AI generates codes</li>
|
|
<li>OAuth tokens</li>
|
|
</ul>
|
|
</div>
|
|
<div class="card red">
|
|
<span class="badge red mb-4">Identity Encryption</span>
|
|
<h3 class="mb-3">Your device only</h3>
|
|
<p class="mb-4">Encrypted client-side with a key derived from your WebAuthn PRF. Hardware tap required. Not in tokens. Agents receive <code>[Identity Encryption — hardware key required]</code>.</p>
|
|
<ul class="checklist red">
|
|
<li>Credit card numbers & CVV</li>
|
|
<li>Passport & government IDs</li>
|
|
<li>Social security numbers</li>
|
|
<li>Seed phrases & private keys</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<hr class="divider">
|
|
|
|
<!-- Features -->
|
|
<div class="section container">
|
|
<h2 class="mb-4">Built different</h2>
|
|
<p class="lead mb-8">Not another password manager with an AI checkbox. The architecture is the feature.</p>
|
|
<div class="grid-3">
|
|
<div class="card card-hover">
|
|
<div class="feature-icon"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h8m-8 6h16"/></svg></div>
|
|
<h3 class="mb-3">Field-level encryption tiers</h3>
|
|
<p>Each field carries its own encryption layer. Your AI reads the API key, not the CVV. Same entry, different keys, different access.</p>
|
|
</div>
|
|
<div class="card card-hover">
|
|
<div class="feature-icon"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 11c0 3.517-1.009 6.799-2.753 9.571m-3.44-2.04l.054-.09A13.916 13.916 0 008 11a4 4 0 118 0c0 1.017-.07 2.019-.203 3m-2.118 6.844A21.88 21.88 0 0015.171 17m3.839 1.132c.645-2.266.99-4.659.99-7.132A8 8 0 008 4.07M3 15.364c.64-1.319 1-2.8 1-4.364 0-1.457.39-2.823 1.07-4"/></svg></div>
|
|
<h3 class="mb-3">WebAuthn PRF</h3>
|
|
<p>Credential and Identity keys derive from your WebAuthn authenticator hardware — Touch ID, Face ID, YubiKey, Titan Key. No master password. No server-side key storage. Math, not policy.</p>
|
|
</div>
|
|
<div class="card card-hover">
|
|
<div class="feature-icon"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/></svg></div>
|
|
<h3 class="mb-3">AI-powered 2FA</h3>
|
|
<p>Store TOTP secrets as Credential fields. Your AI generates time-based codes on demand via MCP — no more switching to your phone during a deployment.</p>
|
|
</div>
|
|
<div class="card card-hover">
|
|
<div class="feature-icon"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/></svg></div>
|
|
<h3 class="mb-3">Client-side encryption</h3>
|
|
<p>Your browser and agents encrypt before anything leaves the client. The vault stores what it receives. It has never seen your Credential or Identity plaintext.</p>
|
|
</div>
|
|
<div class="card card-hover">
|
|
<div class="feature-icon"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z"/></svg></div>
|
|
<h3 class="mb-3">One binary, one file</h3>
|
|
<p>No Docker. No Postgres. No Redis. One Go binary, one SQLite file. Runs on a Raspberry Pi. Runs on a $4/month VPS. Port 1984.</p>
|
|
</div>
|
|
<div class="card card-hover">
|
|
<div class="feature-icon"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"/></svg></div>
|
|
<h3 class="mb-3">Smart import</h3>
|
|
<p>Native parsers for Chrome, Firefox, Bitwarden, Proton Pass. Any other format via LLM. Auto-detects which fields should be Credential vs Identity. Collision resolution by modification date.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<hr class="divider">
|
|
|
|
<!-- For your agents -->
|
|
<div class="section container">
|
|
<div class="grid-2">
|
|
<div>
|
|
<h2 class="mb-4">Your agents get in.<br><span class="gradient-text">Nobody else gets anything.</span></h2>
|
|
<p class="lead mb-6">MCP-native from day one. Every AI agent that supports MCP can read credentials, fetch API keys, and generate 2FA codes — using only what it needs.</p>
|
|
<p class="mb-6">Each token is a combined credential: MCP auth and the Credential private key, wrapped together. The agent decrypts locally. The server sees a request and returns ciphertext. Nothing in between.</p>
|
|
<div class="code-block">
|
|
<p class="code-label">~/.claude/mcp.json</p>
|
|
<pre>{
|
|
"mcpServers": {
|
|
"clavitor": {
|
|
"url": "http://localhost:1984/mcp",
|
|
"headers": {
|
|
"Authorization": "Bearer <span class="prompt">v1984_...</span>"
|
|
}
|
|
}
|
|
}
|
|
}</pre>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div class="card alt mb-4">
|
|
<p class="label accent mb-3">MCP Tools</p>
|
|
<ul class="checklist">
|
|
<li><code>get_credential</code> — fetch by query</li>
|
|
<li><code>list_credentials</code> — list accessible entries</li>
|
|
<li><code>get_totp</code> — live 2FA code</li>
|
|
<li><code>search_vault</code> — full-text search</li>
|
|
<li><code>check_expiring</code> — upcoming expirations</li>
|
|
<li><code>save_credential</code> — write (explicit permission only)</li>
|
|
</ul>
|
|
</div>
|
|
<div class="card red">
|
|
<p class="label red mb-3">Identity Encryption fields</p>
|
|
<p>Agents receive <code>[Identity Encryption — hardware key required]</code> for card numbers, passports, and government IDs. They know the field exists. They cannot read it. Ever.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<hr class="divider">
|
|
|
|
<!-- Access Methods -->
|
|
<div class="section container">
|
|
<h2 class="mb-4">Your agent and you — same vault, right access</h2>
|
|
<p class="lead mb-8">Four ways in. Each designed for a different context. All pointing at the same encrypted store.</p>
|
|
<div class="grid-2">
|
|
<div class="card card-hover">
|
|
<p class="label accent mb-3">MCP</p>
|
|
<h3 class="mb-2">For AI agents</h3>
|
|
<p>Claude Code, Codex, Cursor, or any MCP-compatible agent. Search credentials, fetch API keys, complete 2FA flows — without asking you.</p>
|
|
</div>
|
|
<div class="card card-hover">
|
|
<p class="label accent mb-3">Extension</p>
|
|
<h3 class="mb-2">For humans in a browser</h3>
|
|
<p>Autofill passwords, generate 2FA codes inline. LLM field mapping fills by intent, not CSS selector — works on SPAs, obfuscated forms, multi-step flows.</p>
|
|
</div>
|
|
<div class="card card-hover">
|
|
<p class="label accent mb-3">CLI</p>
|
|
<h3 class="mb-2">For terminal workflows</h3>
|
|
<p>Pipe credentials into scripts and CI pipelines. <code>vault get github.token</code> — done.</p>
|
|
</div>
|
|
<div class="card card-hover">
|
|
<p class="label accent mb-3">API</p>
|
|
<h3 class="mb-2">For everything else</h3>
|
|
<p>REST API with read/write tokens. Full audit log: every access tagged by actor — web, extension, MCP, or agent name.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<hr class="divider">
|
|
|
|
<!-- The competition -->
|
|
<div class="section container">
|
|
<p class="label mb-4">Real complaints. Real users.</p>
|
|
<h2 class="mb-4">We listened. And addressed them all.</h2>
|
|
<p class="lead mb-8">Verbatim quotes from real users — pulled from public forums, GitHub issues, and community threads. Not cherry-picked. Not paraphrased.</p>
|
|
|
|
<div class="grid-3">
|
|
|
|
<div class="card red">
|
|
<p class="label red mb-3">Leading password manager — Community Forum</p>
|
|
<p><em>"The web extensions are laughably bad at this point. This has been going on for months. They either won't fill, wont' unlock, or just plain won't do anything (even clicking extension icon). It's so bad"</em></p>
|
|
<p class="mt-2 text-sm" style="color:#64748b">Community forum, April 2024</p>
|
|
<hr class="divider mt-4 mb-4">
|
|
<ul class="checklist">
|
|
<li><span class="vaultname">clavitor</span>: No desktop app dependency. The extension calls the vault binary directly — no IPC, no sync layer, no unlock chain.</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="card red">
|
|
<p class="label red mb-3">Leading password manager — GitHub Issues</p>
|
|
<p><em>"Every single website loads slower. From Google, up to social media websites like Reddit, Instagram, X... Even scrolling and animation stutters sometimes. So for me the browser extension is unusable. It interferes with my browsing experience like malware."</em></p>
|
|
<p class="mt-2 text-sm" style="color:#64748b">GitHub Issues, 2024</p>
|
|
<hr class="divider mt-4 mb-4">
|
|
<ul class="checklist">
|
|
<li><span class="vaultname">clavitor</span>: Zero content scripts. The extension injects nothing into pages — fills via browser autofill API, on demand, when you ask.</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="card red">
|
|
<p class="label red mb-3">Leading password manager — Hacker News</p>
|
|
<p><em>"The fact they're drip-feeding how bad this breach actually was is terrible enough... Personally I'm never touching them again."</em></p>
|
|
<p class="mt-2 text-sm" style="color:#64748b">Hacker News, January 2023</p>
|
|
<hr class="divider mt-4 mb-4">
|
|
<ul class="checklist">
|
|
<li><span class="vaultname">clavitor</span>: Credential and Identity fields are encrypted before they reach us. We mathematically cannot read them — and neither can anyone who breaches our servers.</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="card red">
|
|
<p class="label red mb-3">Leading password manager — Community Forum</p>
|
|
<p><em>"Since doing so, it asks me to enter my password every 10 minutes or so in the chrome extension"</em></p>
|
|
<p class="mt-2 text-sm" style="color:#64748b">Community forum, November 2022</p>
|
|
<hr class="divider mt-4 mb-4">
|
|
<ul class="checklist">
|
|
<li><span class="vaultname">clavitor</span>: WebAuthn-first. Your authenticator is the primary unlock. Session lives locally — no server-side token expiry forcing re-auth every few minutes.</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="card red">
|
|
<p class="label red mb-3">Leading password manager — Community Forums</p>
|
|
<p><em>"the password not only auto-filled in the password field, but also auto-filled in reddit's search box!"</em></p>
|
|
<p class="mt-2 text-sm" style="color:#64748b">Community forum</p>
|
|
<hr class="divider mt-4 mb-4">
|
|
<ul class="checklist">
|
|
<li><span class="vaultname">clavitor</span>: LLM field mapping. The extension reads the form and asks the model which field is which — fills by intent, not by CSS selector guesswork.</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="card red">
|
|
<p class="label red mb-3">Leading password manager — Community Forums</p>
|
|
<p><em>"Bitwarden REFUSES to autofill the actual password saved for a given site or app...and instead fills an old password. It simply substitutes the OLD password for the new one that is plainly saved in the vault."</em></p>
|
|
<p class="mt-2 text-sm" style="color:#64748b">Community forum</p>
|
|
<hr class="divider mt-4 mb-4">
|
|
<ul class="checklist">
|
|
<li><span class="vaultname">clavitor</span>: LLM field mapping matches by intent. Entries are indexed by URL — the right credential, every time.</li>
|
|
</ul>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<p class="mt-8">All quotes verbatim from public posts. <a href="/sources">View sources →</a></p>
|
|
</div>
|
|
|
|
<hr class="divider">
|
|
|
|
<!-- Hosted CTA -->
|
|
<div class="section container">
|
|
<h2 class="mb-4">Your vault needs to be everywhere you are.</h2>
|
|
<p class="lead mb-3">A password manager that only works on your home network isn't a password manager. Your laptop moves. Your phone moves. Your agents run on servers in three time zones.</p>
|
|
<p class="mb-3">Self-hosting means a server with a public IP, DNS, TLS certificates, uptime monitoring, and backups. That's not a weekend project — that's infrastructure.</p>
|
|
<p class="mb-8">We run <span class="vaultname">clavitor</span> across regions on every continent. <s>$20</s> $12/yr. Your Credential and Identity keys never leave your browser — we cannot read your private fields. Not policy. Math.</p>
|
|
<div class="btn-row">
|
|
<a href="/hosted" class="btn btn-primary">Get hosted →</a>
|
|
<a href="/install" class="btn btn-ghost">Self-host anyway</a>
|
|
</div>
|
|
</div>
|
|
|
|
<hr class="divider">
|
|
|
|
<!-- Quick install -->
|
|
<div class="section container">
|
|
<h2 class="mb-4">Up and running in 30 seconds</h2>
|
|
<p class="lead mb-8">One command. No dependencies.</p>
|
|
<div class="code-block mb-6">
|
|
<p class="code-label">Terminal</p>
|
|
<div><span class="comment"># Self-host in 30 seconds</span></div>
|
|
<div><span class="prompt">$</span> curl -fsSL clavitor.com/install.sh | sh</div>
|
|
<div><span class="prompt">$</span> clavitor</div>
|
|
<div class="comment"># Running on http://localhost:1984</div>
|
|
</div>
|
|
<div class="code-block">
|
|
<p class="code-label">MCP config for Claude Code / Cursor / Codex</p>
|
|
<pre>{
|
|
"mcpServers": {
|
|
"clavitor": {
|
|
"url": "http://localhost:1984/mcp",
|
|
"headers": { "Authorization": "Bearer <span class="prompt">v1984_your_token_here</span>" }
|
|
}
|
|
}
|
|
}</pre>
|
|
</div>
|
|
<p class="mt-4"><a href="/install" class="btn btn-accent">Full install guide →</a></p>
|
|
</div>
|
|
{{end}}
|
|
|
|
{{define "index-script"}}
|
|
<script>
|
|
(function() {
|
|
const W = 1000, H = 460;
|
|
function project(lon, lat) {
|
|
const latR = Math.min(Math.abs(lat), 85) * Math.PI / 180 * (lat < 0 ? -1 : 1);
|
|
const miller = 1.25 * Math.log(Math.tan(Math.PI/4 + 0.4*latR));
|
|
const maxMiller = 1.25 * Math.log(Math.tan(Math.PI/4 + 0.4*80*Math.PI/180));
|
|
const x = (lon + 180) / 360 * W;
|
|
const y = H/2 - (miller / (2*maxMiller)) * H;
|
|
return [Math.round(x*10)/10, Math.round(y*10)/10];
|
|
}
|
|
|
|
function addVisitorDot(lat, lon, city) {
|
|
const svg = document.getElementById('worldmap');
|
|
if (!svg) return;
|
|
const [x, y] = project(lon, lat);
|
|
const ns = 'http://www.w3.org/2000/svg';
|
|
|
|
const ring = document.createElementNS(ns, 'circle');
|
|
ring.setAttribute('cx', x); ring.setAttribute('cy', y);
|
|
ring.setAttribute('r', '3'); ring.setAttribute('fill', 'none');
|
|
ring.setAttribute('stroke', '#EF4444'); ring.setAttribute('stroke-width', '1.5');
|
|
const a1 = document.createElementNS(ns, 'animate');
|
|
a1.setAttribute('attributeName', 'r'); a1.setAttribute('values', '3;16;3');
|
|
a1.setAttribute('dur', '2s'); a1.setAttribute('repeatCount', 'indefinite');
|
|
const a2 = document.createElementNS(ns, 'animate');
|
|
a2.setAttribute('attributeName', 'stroke-opacity'); a2.setAttribute('values', '0.8;0;0.8');
|
|
a2.setAttribute('dur', '2s'); a2.setAttribute('repeatCount', 'indefinite');
|
|
ring.appendChild(a1); ring.appendChild(a2);
|
|
|
|
const dot = document.createElementNS(ns, 'circle');
|
|
dot.setAttribute('cx', x); dot.setAttribute('cy', y);
|
|
dot.setAttribute('r', '4'); dot.setAttribute('fill', '#EF4444');
|
|
dot.setAttribute('stroke', '#0a1628'); dot.setAttribute('stroke-width', '1.5');
|
|
|
|
const label = document.createElementNS(ns, 'text');
|
|
label.setAttribute('x', x); label.setAttribute('y', y + 15);
|
|
label.setAttribute('font-family', 'Inter,sans-serif');
|
|
label.setAttribute('font-size', '10');
|
|
label.setAttribute('fill', '#EF4444');
|
|
label.setAttribute('text-anchor', 'middle');
|
|
label.setAttribute('font-weight', '500');
|
|
label.textContent = city || 'You';
|
|
|
|
svg.appendChild(ring);
|
|
svg.appendChild(dot);
|
|
svg.appendChild(label);
|
|
}
|
|
|
|
function handleGeoData(d) {
|
|
if (!d.latitude || !d.longitude) return;
|
|
addVisitorDot(d.latitude, d.longitude, d.city || 'You');
|
|
|
|
const grid = document.getElementById('dc-grid');
|
|
if (!grid) return;
|
|
|
|
const flag = d.country_code ? d.country_code.toUpperCase().split('').map(c =>
|
|
String.fromCodePoint(c.charCodeAt(0) + 127397)).join('') : '📍';
|
|
const label = [d.city, d.country_name].filter(Boolean).join(', ') || 'Your location';
|
|
const region = d.region || '';
|
|
|
|
const card = document.createElement('div');
|
|
card.className = 'rounded-xl p-5 text-center card-hover';
|
|
card.setAttribute('data-lon', d.longitude);
|
|
card.style.cssText = 'background:#1f0a0a;border:1px solid rgba(239,68,68,0.35)';
|
|
card.innerHTML = `
|
|
<div class="text-2xl mb-2">${flag}</div>
|
|
<div class="text-white font-semibold text-sm">${label}</div>
|
|
<div class="text-gray-500 text-xs mb-2">${region}</div>
|
|
<div class="flex items-center justify-center gap-1.5 text-xs text-gray-400">
|
|
<span class="w-1.5 h-1.5 rounded-full inline-block" style="background:#EF4444;opacity:0.6"></span>You are here
|
|
</div>`;
|
|
|
|
grid.style.gridTemplateColumns = "repeat(5,1fr)";
|
|
|
|
const cards = [...grid.children];
|
|
const insertBefore = cards.find(c => parseFloat(c.getAttribute('data-lon')) > d.longitude);
|
|
if (insertBefore) grid.insertBefore(card, insertBefore);
|
|
else grid.appendChild(card);
|
|
}
|
|
|
|
fetch('/geo')
|
|
.then(r => r.json())
|
|
.then(d => {
|
|
if (d.latitude) {
|
|
handleGeoData(d);
|
|
} else if (d.private && navigator.geolocation) {
|
|
navigator.geolocation.getCurrentPosition(pos => {
|
|
const lat = pos.coords.latitude, lon = pos.coords.longitude;
|
|
fetch(`/geo?lat=${lat}&lon=${lon}`)
|
|
.then(r => r.json())
|
|
.then(g => handleGeoData({
|
|
latitude: lat, longitude: lon,
|
|
city: g.city || 'You',
|
|
region: g.region || '',
|
|
country_name: g.country_name || '',
|
|
country_code: g.country_code || ''
|
|
}))
|
|
.catch(() => handleGeoData({ latitude: lat, longitude: lon,
|
|
city: 'You', region: '', country_name: '', country_code: '' }));
|
|
}, () => {});
|
|
}
|
|
})
|
|
.catch(() => {});
|
|
})();
|
|
</script>
|
|
{{end}}
|