Claude-skill-registry Holochain Development
Holochain DHT development for distributed coordination. Activate when: (1) Building Holochain applications (hApps), (2) Writing Zome code in Rust, (3) Configuring conductor and lair-keystore, (4) Working with DHT entries and links, or (5) Setting up Holochain development environment.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/holochain" ~/.claude/skills/majiayu000-claude-skill-registry-holochain-development-4a394c && rm -rf "$T"
manifest:
skills/data/holochain/SKILL.mdsource content
Holochain Development
Overview
Holochain is a framework for building fully distributed, peer-to-peer applications. It uses a distributed hash table (DHT) for data storage and validation without global consensus.
Key Concepts
| Concept | Description |
|---|---|
| hApp | Holochain Application - a collection of DNAs |
| DNA | Distributed Network Architecture - defines data types and validation rules |
| Zome | A module within a DNA written in Rust/WASM |
| Entry | A piece of data stored on the DHT |
| Link | A directed connection between two entries |
| Agent | A participant in the network with a unique key pair |
| Conductor | Runtime that hosts hApps and manages connections |
| Lair | Key management service (lair-keystore) |
Installation
Via Nix (Recommended)
# flake.nix { inputs.holochain.url = "github:holochain/holochain"; devShells.default = pkgs.mkShell { packages = [ holochain lair-keystore hc # Holochain CLI ]; }; }
Via Cargo
cargo install holochain cargo install lair_keystore
Quick Start
Create a New hApp
# Scaffold new project hc scaffold web-app my-happ # Structure created: # my-happ/ # ├── dnas/ # │ └── my_dna/ # │ ├── workdir/ # │ └── zomes/ # │ └── coordinator/ # │ └── src/lib.rs # ├── ui/ # └── workdir/ # Build the hApp hc dna pack dnas/my_dna/workdir hc app pack workdir
Zome Development
// zomes/coordinator/src/lib.rs use hdk::prelude::*; #[hdk_entry_helper] pub struct Post { pub title: String, pub content: String, } #[hdk_extern] pub fn create_post(post: Post) -> ExternResult<ActionHash> { create_entry(&EntryTypes::Post(post.clone())) } #[hdk_extern] pub fn get_post(action_hash: ActionHash) -> ExternResult<Option<Record>> { get(action_hash, GetOptions::default()) } #[hdk_extern] pub fn get_all_posts() -> ExternResult<Vec<Record>> { let path = Path::from("all_posts"); let links = get_links(path.path_entry_hash()?, LinkTypes::AllPosts, None)?; let posts: Vec<Record> = links .into_iter() .filter_map(|link| get(link.target, GetOptions::default()).ok().flatten()) .collect(); Ok(posts) }
Entry Definitions
#[hdk_entry_defs] #[unit_enum(UnitEntryTypes)] pub enum EntryTypes { Post(Post), Comment(Comment), } #[hdk_link_types] pub enum LinkTypes { AllPosts, PostToComments, }
Conductor Configuration
# conductor-config.yaml environment_path: /tmp/holochain keystore: type: lair_server connection_url: unix:///tmp/lair/socket?k=... admin_interfaces: - driver: type: websocket port: 4444 network: transport_pool: - type: webrtc signal_url: wss://signal.holochain.org
Testing
Unit Tests (Rust)
#[cfg(test)] mod tests { use super::*; use holochain::sweettest::*; #[tokio::test(flavor = "multi_thread")] async fn test_create_post() { let (conductors, _) = SweetConductorBatch::from_standard_config(1).await; let apps = conductors.setup_app("test", &[]).await.unwrap(); let post = Post { title: "Test".to_string(), content: "Content".to_string(), }; let hash: ActionHash = conductors[0] .call(&apps[0].cells()[0].zome("posts"), "create_post", post) .await; assert!(!hash.is_empty()); } }
Integration Tests (Tryorama)
// tests/src/post.test.ts import { runScenario } from '@holochain/tryorama'; test('create and get post', async () => { await runScenario(async scenario => { const appBundleSource = { path: './workdir/my-happ.happ' }; const [alice] = await scenario.addPlayers([{ appBundleSource }]); const post = { title: 'Hello', content: 'World' }; const hash = await alice.cells[0].callZome({ zome_name: 'posts', fn_name: 'create_post', payload: post, }); expect(hash).toBeTruthy(); }); });
Common Patterns
Validation Rules
#[hdk_extern] pub fn validate(op: Op) -> ExternResult<ValidateCallbackResult> { match op.flattened::<EntryTypes, LinkTypes>()? { FlatOp::StoreEntry(OpEntry::CreateEntry { entry, .. }) => { match entry { EntryTypes::Post(post) => { if post.title.is_empty() { return Ok(ValidateCallbackResult::Invalid( "Title cannot be empty".into() )); } Ok(ValidateCallbackResult::Valid) } _ => Ok(ValidateCallbackResult::Valid) } } _ => Ok(ValidateCallbackResult::Valid) } }
Signal Emission
#[hdk_extern] pub fn create_post(post: Post) -> ExternResult<ActionHash> { let hash = create_entry(&EntryTypes::Post(post.clone()))?; // Emit signal to UI emit_signal(&Signal::PostCreated { hash: hash.clone(), post })?; Ok(hash) }
Commands Reference
| Command | Description |
|---|---|
| Create new hApp project |
| Package DNA |
| Package hApp |
| Generate sandbox environment |
| Run sandbox conductor |
| Run conductor with config |
| Start keystore server |