Nit
git for agent identity
Install / Use
/learn @newtype-ai/NitREADME
nit
Git for agent identity.
_ _ _____
| \ |"| ___ |_ " _|
<| \| |> |_"_| | |
U| |\ |u | | /| |\
|_| \_| U/| |\u u |_|U
|| \\,-.-,_|___|_,-._// \\_
(_") (_/ \_)-' '-(_/(__) (__)
One identity. Any apps.
- Self-sovereign — your keys, your identity. No authority assigns or revokes it
- Ed25519 signed — every commit cryptographically signed
- A2A card format — uses the
agent-card.jsonformat from A2A protocol (identity layer, not communication) - MIT licensed
Install
npm install -g @newtype-ai/nit
Or use directly:
npx @newtype-ai/nit init
Quick Start
# Initialize — generates Ed25519 keypair + initial agent-card.json
nit init
# Create a platform-specific branch
nit branch faam.io
nit checkout faam.io
# Edit agent-card.json — set name, description, skills
nit commit -m "FAAM config"
# Push all branches to remote
nit push --all
Features
Branch-per-platform
main is your canonical public identity. Each branch is a platform-specific persona — branch name = domain.
main → full agent card (public, discoverable)
faam.io → { skills: [content, social], description: "Content creator..." }
polymarket.com → { skills: [research, trading], description: "Market analyst..." }
Data in one branch never pollutes another. Switch environments cleanly.
On-chain identity
One keypair, multiple chains. Your Ed25519 identity derives chain-native addresses — no seed phrases, no extra key management.
- Solana — your Ed25519 public key is your Solana address
- EVM (Ethereum, BSC, Polygon, Arbitrum, etc.) — deterministic secp256k1 derivation from your Ed25519 identity
Agents prove identity and sign on any chain using the same cryptographic root.
nit status # shows your chain addresses
Skill resolution
Skills stored as pointers ({ "id": "skill-name" }) in your card — resolved from SKILL.md files at commit time. SKILL.md is the single source of truth.
Auto-discovers skills from major agent frameworks:
.claude/skills/— Claude Code.cursor/skills/— Cursor.windsurf/skills/— Windsurf.codex/skills/— OpenAI Codex.openclaw/workspace/skills/— OpenClaw
Configurable remote
Free hosting at newtype-ai.org. Or bring your own server:
nit remote set-url origin https://my-server.com
Zero runtime dependencies
Pure Node.js builtins. No bloat.
Commands
| Command | Description |
|---------|-------------|
| nit init | Create .nit/, generate Ed25519 keypair, initial commit |
| nit status | Identity info, current branch, chain addresses, uncommitted changes |
| nit commit -m "msg" | Snapshot agent-card.json |
| nit log | Commit history for current branch |
| nit diff [target] | JSON diff vs HEAD, branch, or commit |
| nit branch [name] | List branches or create a new one |
| nit branch -d <name> | Delete a local branch |
| nit branch -D <name> | Delete local + remote branch |
| nit checkout <branch> | Switch branch (auto-commits changes first) |
| nit push [--all] | Push branch(es) to remote |
| nit pull [--all] | Pull branch(es) from remote |
| nit reset [target] | Restore agent-card.json from HEAD or target |
| nit show [target] | Show commit metadata and card content |
| nit sign "msg" | Sign a message with your Ed25519 key |
| nit sign --login <domain> | Auto-switch to domain branch + generate login payload |
| nit remote | Show remote URL and credential status |
| nit remote add <name> <url> | Add a new remote |
| nit remote set-url <name> <url> | Change a remote's URL |
| nit sign-tx --chain <c> <data> | Sign transaction data (EVM: 32-byte hash, Solana: message bytes) |
| nit broadcast --chain <c> <tx> | Broadcast signed transaction to configured RPC endpoint |
| nit rpc | Show configured RPC endpoints |
| nit rpc set-url <chain> <url> | Set RPC endpoint for a chain |
| nit auth set <domain> --provider <p> --account <a> | Configure OAuth auth for a domain branch |
| nit auth show [domain] | Show auth config for branch(es) |
How It Works
Identity
nit init generates an Ed25519 keypair stored in .nit/identity/. The public key is embedded in your agent card as:
{
"publicKey": "ed25519:<base64-key>"
}
Platforms verify your identity by challenging you to sign a nonce — no shared secrets, no bearer tokens.
publicKey is managed by nit automatically — injected from your keypair at every commit. You don't need to set or modify it.
nit also derives chain-native addresses from your keypair — Solana (Ed25519 native) and EVM chains (Ethereum, BSC, Polygon, etc.) via a deterministic secp256k1 derivation. Run nit status to see your addresses.
Login
When you log into an app, you sign a domain-bound payload with your private key. The app verifies it through the server's identity registry — no OAuth, no API keys, no human account.
nit sign --login <domain> does two things automatically:
- Switches to the domain's branch (creates it if it doesn't exist)
- Generates the signed login payload (includes
public_keyfor transparency)
The app sends the payload to api.newtype-ai.org/agent-card/verify with an optional policy (trust rules like max_identities_per_machine, min_age_seconds). The server evaluates and returns admitted: true/false alongside identity metadata and attestation.
The domain is baked into the signature — a signature for faam.io is mathematically invalid for discord.com.
Remote Protocol
The main branch is public. Non-main branches require signed-challenge authentication:
GET /.well-known/agent-card.json → main card (public)
GET /.well-known/agent-card.json?branch=faam.io → 401 { challenge }
GET ... + X-Nit-Signature + X-Nit-Challenge → branch card
nit is the client. Any server can implement the protocol. newtype-ai.org is the recommended free hosting, but you can point to any compatible server.
Directory Structure
your-project/
├── .nit/ # nit repository (gitignored)
│ ├── HEAD # Current branch ref
│ ├── config # Remote URL, credentials, skills directory
│ ├── identity/
│ │ ├── agent.pub # Ed25519 public key
│ │ ├── agent.key # Ed25519 private key (0600)
│ │ ├── agent-id # UUIDv5 derived from public key
│ │ └── machine-hash # SHA-256 of platform machine ID
│ ├── objects/ # Content-addressable store
│ └── refs/heads/ # Branch pointers
├── agent-card.json # Working copy (changes with checkout)
└── ...
Programmatic API
import {
init, commit, checkout, branch, push, status, sign, loginPayload,
loadRawKeyPair, getWalletAddresses, signTx, rpcSetUrl,
authSet, authShow, reset, show, pull,
} from '@newtype-ai/nit';
await init();
// Log into an app (auto-creates and switches to domain branch)
const payload = await loginPayload('faam.io');
// → { agent_id, domain, timestamp, signature, public_key, switchedBranch, createdSkill }
// Customize card, then commit & push
await commit('FAAM config');
await push({ all: true });
// Access raw Ed25519 keypair (64 bytes: [seed || pubkey])
const keypair = await loadRawKeyPair('/path/to/.nit');
// → Uint8Array(64) — compatible with Solana and other Ed25519 libraries
// Get chain addresses (derived from your identity)
const addresses = await getWalletAddresses('/path/to/.nit');
// → { solana: "C54kvW3...", ethereum: "0x2317..." }
// Sign data with identity-derived keys
await rpcSetUrl('evm', 'https://eth.llamarpc.com');
const sig = await signTx('evm', '0x<32-byte-keccak256-hash>');
// → { chain: 'evm', signature: '0x...', recovery: 0, address: '0x...' }
License
MIT
