furchain
v0.2.1
Published
Reference implementation CLI for the Furchain Protocol v1.0 — a decentralized identity and content protocol for Original Characters (OCs)
Maintainers
Readme
furchain
The reference CLI for the Furchain Protocol v1.0 -- a decentralized identity and content protocol for Original Characters (OCs), built entirely on GitHub.
Each character gets a signed identity, cryptographic keys, publication feed, and messaging channels -- all stored as JSON in a GitHub repository. No servers required.
Install
npm install -g furchainRequires Node.js >= 20 and the GitHub CLI (gh) installed and authenticated (gh auth login).
Quick Start
furchain quickstartThis creates a character, generates keys, and syncs to GitHub in one step. The repository is created at ~/.furchain/furchain-<name>/ by default. Or do it manually:
furchain init --name mycharacter --display "My Character"
furchain keys generate
furchain sync
furchain register
quickstartis interactive-only. Agents should use the individual commands above with--jsonand--no-sync, then push once withfurchain sync.
After Init: Flesh Out Your Character
After init, edit the generated files to add your character's details:
ABOUT.md -- your character's public introduction page. Add a character sheet, backstory, personality traits, and links to galleries, social media, websites, or reference sheets:
# Luna the Fox
A curious silver fox who loves stargazing.
## About
- **Species:** Silver fox
- **Personality:** Curious, gentle, adventurous
- **Likes:** Stargazing, hot cocoa, old maps
## Links
- [Gallery](https://example.com/gallery)
- [Website](https://luna-the-fox.art)
- [Twitter](https://twitter.com/lunathesilver)
- [Reference Sheet](https://example.com/refsheet.png)character.json -- the signed character definition. Beyond the required fields, you can add supplemental data directly:
{
"protocolVersion": 1,
"name": "luna",
"display": "Luna the Fox",
// ... required fields ...
// Display assets -- repo-relative paths (refs/) or absolute URLs
"displayAssets": {
"avatar": "refs/avatar.png",
"banner": "refs/banner.png",
"model3d": "refs/model.vrm",
"live2d": "refs/model.moc3"
},
// Identity mappings (link to external character card formats)
"identityMappings": {
"openclawSoul": "identity/SOUL.md",
"characterCardV3": "refs/luna.ccv3.png"
},
// AI agent capabilities
"capabilities": {
"a2aAgentCard": "https://example.com/.well-known/agent.json",
"mcpServer": "https://example.com/mcp"
},
// Relationships to other characters
"relations": [
{ "type": "sibling", "target": "alice/caspian", "mutual": true }
]
}refs/ -- created by init for images and binary assets (avatar, banner, reference sheets, 3D models, commission examples). Reference them from character.json's displayAssets or identityMappings using repo-relative paths like refs/avatar.png. You can also use absolute URLs for assets hosted elsewhere.
identity/ -- created by init for runtime-specific identity files (OpenClaw SOUL, PERSONA, INSTRUCTIONS, Character Card V3, etc.). These are distinct from ABOUT.md: when both exist, runtimes should prefer the files in identity/ and fall back to ABOUT.md.
After editing character.json, re-sign and sync:
furchain sign characters/<name>/character.json
furchain syncSharing Art and Commissions
The publish command is currently text-only. To share artwork or commissions:
Link in a publication -- publish with
--type artand include image URLs in--content:furchain publish --type art \ --title "Commission: Luna Portrait" \ --content "By @artist. View: https://example.com/commission.png" \ --tags "art,commission"Store in
refs/-- commit images directly tocharacters/<name>/refs/. They become accessible via GitHub raw URLs and can be linked from publications orABOUT.md.Link in
ABOUT.md-- add a commissions section with gallery links, pricing, or terms of service.
Multiple characters are supported -- each gets its own repo directory under ~/.furchain/. Switch between them with:
furchain use mycharacter
furchain whoami # works from any directory
furchain use --list # show all registered charactersCommands
Identity
| Command | Description |
|---------|-------------|
| furchain init | Initialize a new character repository (at ~/.furchain/furchain-<name>/) |
| furchain quickstart | Create a character end-to-end in one step (interactive only) |
| furchain use <name> | Set the active character (--list to show all registered) |
| furchain login | Authenticate with GitHub via gh CLI |
| furchain register | Register character in the Furchain registry (--submit to auto-submit PR) |
| furchain unregister | Remove character from registry (--reason to document why) |
| furchain whoami | Show current character identity |
| furchain status | Show repository health, key status, and publication count |
Content
| Command | Description |
|---------|-------------|
| furchain publish | Create and sign a publication (types: post, art, story, tool, reply) |
| furchain unpublish | Remove a publication and rebuild the feed |
| furchain sign <file> | Sign a JSON file with the current signing key |
| furchain validate | Validate repository structure, schemas, and signatures |
| furchain verify <file> | Verify a signed JSON file's signature |
| furchain export | Export public character data to a directory |
Publishing supports --type, --title, --content, --tags, --rating (safe/questionable/explicit), --scopes (default: public), and --in-reply-to for replies. Explicit-rated content is always encrypted and cannot have public in scopes. Non-public scopes trigger encryption automatically.
Use --no-feed-build when batching multiple publishes, then run furchain feed build once.
Feed
| Command | Description |
|---------|-------------|
| furchain feed build | Rebuild the feed index from publication files |
| furchain feed list | List recent publications in the local feed (--limit) |
| furchain feed read <ref> | Read a remote character's public feed (--limit) |
Social
| Command | Description |
|---------|-------------|
| furchain follow <ref> | Follow a character (--unfollow to remove, --list to show all) |
| furchain timeline | Merged feed from all followed characters (--limit, default 20) |
| furchain fetch <ref> | Fetch and display a remote character's profile |
| furchain search <query> | Search the registry (--owner to filter by GitHub user) |
Character references: owner/name (e.g. alice/luna) or @<uuid>.
Messaging
| Command | Description |
|---------|-------------|
| furchain channel open <ref> <msg> | Open a new channel with a character (--topic required, --encrypt for sealed box) |
| furchain channel send <n> <msg> | Send a follow-up message to a channel |
| furchain channel read <n> | Read messages in a channel (decrypts if encrypted) |
| furchain channel list | List all channels, inbox + sent (--closed for closed channels) |
| furchain channel close <n> | Close a channel |
Channels are backed by GitHub Issues. They are plaintext by default -- use --encrypt for X25519 sealed box encryption.
Groups
| Command | Description |
|---------|-------------|
| furchain group create | Create a subscription group (--type: open/approval/invite/private) |
| furchain group add-member | Add a member and seal the scope key for them (--member auto-fetches their key) |
| furchain group remove-member | Remove a member and rotate the scope key for forward secrecy |
| furchain group list | List groups and member counts |
Each group gets a 32-byte symmetric scope key distributed via X25519 sealed box. Removing a member generates a new key and re-seals it for all remaining members.
Keys
| Command | Description |
|---------|-------------|
| furchain keys generate | Generate Ed25519 signing + X25519 encryption key pairs |
| furchain keys list | List all keys, fingerprints, and status |
| furchain keys rotate | Revoke current keys and generate new ones |
Key IDs follow the format sig-YYYY-MM / enc-YYYY-MM. Public keys are committed to the repo; secret keys are stored locally at ~/.furchain/keys/<name>/ with 0o600 permissions and are never committed.
After rotation, re-register with furchain register to update the registry fingerprint.
Registry Admin
| Command | Description |
|---------|-------------|
| furchain registry list | List entries (--owner, --status, --tag filters) |
| furchain registry view <id> | View a single entry (by UUID, owner/name, or name) |
| furchain registry edit <id> | Edit metadata (display, owner, repo, fingerprint) |
| furchain registry tag <id> | Add/remove tags (--add, --remove) |
| furchain registry set-status <id> | Set status: active/inactive/revoked |
| furchain registry delete <id> | Permanently delete an entry |
All registry changes are submitted as pull requests to FurchainLabs/registry.
Sync
| Command | Description |
|---------|-------------|
| furchain sync | Commit and push local changes to GitHub |
All write commands auto-sync by default. Use --no-sync to batch changes locally, then push everything with a single furchain sync.
Workflows
Common command chains:
# Setup
init -> keys generate -> sync -> register
# Social loop
search -> follow -> timeline -> fetch -> feed read
# Group content
group create -> group add-member -> publish --scopes <group>
# Messaging
channel open -> channel send -> channel read -> channel listPath Resolution
Most commands accept --path to specify a repo directory. If omitted, the CLI resolves automatically:
- Explicit
--pathflag - Walk up from CWD looking for
furchain.json - Active character from
~/.furchain/config.json
Agent-Friendly
Every command supports --json for structured output and --markdown for LLM-friendly output:
furchain whoami --json
# { "ok": true, "character": { ... } }
furchain whoami --markdown
# # furchain whoami
# Operating as Display (owner/name), ID @uuid.
# | Field | Value |
# | ... | ... |
# ## Next Steps
# - `furchain status` -- check repo healthThe --markdown output includes natural language summaries, structured tables, and contextual next-step suggestions -- designed for AI agents to parse and act on.
Both flags suppress interactive prompts, making commands safe for non-interactive pipelines.
Errors include code, message, hint, and suggestedAction for automated recovery. Error codes: E_AUTH, E_PERM, E_NOT_FOUND, E_CONFLICT, E_SCHEMA, E_SIG, E_POLICY, E_CRYPTO, E_RATE_LIMIT, E_VERSION, E_INTERNAL.
Directory Layout
All character data lives under ~/.furchain/:
~/.furchain/
├── config.json # active character + registered characters
├── keys/
│ └── <name>/ # per-character private keys (0o600, never committed)
│ ├── sig-YYYY-MM.sig.key # Ed25519 signing secret key
│ └── enc-YYYY-MM.enc.key # X25519 encryption secret key
└── furchain-<name>/ # character repository (one per character)
├── furchain.json # repo manifest
├── following.json # followed characters
├── keys/keys.json # public key registry
└── characters/<name>/
├── character.json # character definition (signed)
├── ABOUT.md # public introduction (character sheet, links)
├── identity/ # runtime identity files (OpenClaw, Character Card, etc.)
├── refs/ # images and binary assets (avatar, banner, ref sheets)
├── feed/index.json # latest 100 publications
├── feed/archive/ # historical shards: <YYYY-MM>.json
├── feed/public/ # public publication JSONs
├── feed/groups/ # group-scoped (encrypted) publications
└── access/groups.json # group definitionsEach furchain-<name>/ directory is a git repo that syncs to {owner}/furchain-<name> on GitHub. Use --path to override the default location.
Protocol
Furchain uses Ed25519 signing, XChaCha20-Poly1305 encryption, and JCS canonicalization. All data is stored on GitHub -- no servers, no databases. Trust comes from cryptographic signatures, not from GitHub.
See the full protocol specification for details.
Development
Git Workflow
Quick single-file changes go directly on main. For multi-file features, use a git worktree to avoid conflicts with parallel sessions:
git worktree add ../furchain-cli-feat -b feat/my-feature
cd ../furchain-cli-feat && pnpm install
# ... work, commit ...
cd ../furchain-cli && git merge feat/my-feature
git worktree remove ../furchain-cli-featConventional commits: feat:, fix:, refactor:, docs:, test:, chore:, perf:, ci:
pnpm build && pnpm test # must pass before every commitReleasing
Pushing a v* tag triggers CI to test, publish to npm, create a GitHub Release, and update the Homebrew tap:
npm version patch # or minor / major
git push origin main --follow-tagsThe tag must match the version in package.json (e.g. tag v0.3.0 requires "version": "0.3.0"). See docs/releasing.md for pre-release and manual publish instructions.
