Observed since 21 Oct, 09:38 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Persistent cryptographic identity for web apps without accounts.
Persistent cryptographic identity for web apps without accounts.
A TypeScript library that gives a browser a keypair instead of giving your application a user database. The private key never leaves the browser. The browser gets a stable Ghost ID, and the active public key becomes a credential for that Ghost. Your server verifies signatures.
Ghost authenticates a key, not a person.
pnpm add @0xsarwagya/ghost
In the browser:
import { createGhost } from "@0xsarwagya/ghost";
const ghost = await createGhost();
console.log(ghost.id); // ghost_1_crhgcniramqtgfpib5uiaautocwdigbt
console.log(ghost.credentialId); // cred_1_…
// Later, prove possession of a server-issued challenge:
const proof = await ghost.sign(challenge);
On your server:
import {
createChallenge,
InMemoryChallengeStore,
InMemoryGhostCredentialStore,
verifyGhostProof,
} from "@0xsarwagya/ghost/server";
const store = new InMemoryChallengeStore();
const credentials = new InMemoryGhostCredentialStore();
credentials.register(ghost); // persist this in your own database in production
// 1. Issue a one-time challenge.
const challenge = createChallenge({ audience: "https://app.example", action: "login" });
// 2. Verify the browser's proof.
const result = await verifyGhostProof(proof, {
expectedAudience: "https://app.example",
challengeStore: store,
credentialStore: credentials,
});
if (result.ok) {
console.log("same ghost as before:", result.ghostId);
}
No email. No password. No OAuth. No user table.
Ghost is usable without recovery. When a Ghost owns durable value, ask the user whether to make it recoverable:
const { recoverySecret, recoveryRecord } = await ghost.enableRecovery();
// Show recoverySecret once. Store recoveryRecord with your app's Ghost row.
If the browser profile is lost, the user supplies the secret and your app supplies the recovery record:
import { recoverGhost } from "@0xsarwagya/ghost";
const ghost = await recoverGhost({ recoverySecret, recoveryRecord });
// Same ghost.id, fresh non-extractable credential.
Experimental. The protocol is versioned and the v1 wire format is pinned by test vectors, but the API may still change before 1.0. Read the security model before relying on it — especially what Ghost does not prove.
https://oss.sarwagya.wtf/ghost/docs
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.1.0Registry latest | 5 Jul 2026 | 6 |
This describes our collected data; it is not a security assessment.
Observed since 21 Oct, 09:38 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:5682720962d9f2be2f6eadc06026e34394dfe6376e7f9e4302776ef4c375af48