Back to list
FlexNetOS

holochain-development

by FlexNetOS

0🍴 0📅 Jan 21, 2026

SKILL.md


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

ConceptDescription
hAppHolochain Application - a collection of DNAs
DNADistributed Network Architecture - defines data types and validation rules
ZomeA module within a DNA written in Rust/WASM
EntryA piece of data stored on the DHT
LinkA directed connection between two entries
AgentA participant in the network with a unique key pair
ConductorRuntime that hosts hApps and manages connections
LairKey management service (lair-keystore)

Installation

# 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

CommandDescription
hc scaffold web-app <name>Create new hApp project
hc dna pack <workdir>Package DNA
hc app pack <workdir>Package hApp
hc sandbox generateGenerate sandbox environment
hc sandbox runRun sandbox conductor
holochain -c <config>Run conductor with config
lair-keystore serverStart keystore server

Score

Total Score

60/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon