Agent skill

Agent Crdt Synchronizer

by ruvnet in ruvnet/ruflo

Agent skill for crdt-synchronizer - invoke with $agent-crdt-synchronizer

MITAuto-check passed

Install Agent Crdt Synchronizer

skills CLI
$ npx skills add ruvnet/ruflo --skill agent-crdt-synchronizer -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install ruvnet/ruflo agent-crdt-synchronizer --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/ruvnet/ruflo.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/agent-crdt-synchronizer .claude/skills/agent-crdt-synchronizer && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
agent-crdt-synchronizer
GitHub stars
74k
Used in
3 other repos
Token cost
~6.3k tokens
SKILL.md length
190 words
Files
1
Skills in repo
264
Repo updated
First seen
Licence
MIT

At a glance

Agent skill for crdt-synchronizer - invoke with $agent-crdt-synchronizer

  • Works in 5 steps: CRDT Implementation: Deploy state-based… → Data Structure Management: Handle… → Delta Synchronization: Implement… → …
  • SKILL.md covers Core Responsibilities, Technical Implementation, MCP Integration Hooks and Advanced CRDT Features, plus 1 more section
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Agent Crdt Synchronizer is an agent skill from ruvnet/ruflo. Agent skill for crdt-synchronizer - invoke with $agent-crdt-synchronizer

Its SKILL.md is about 6.3k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

The repository describes itself as: 🌊 The original agent harness. Deploy intelligent multi-player swarms, coordinate autonomous workflows, and build conversational AI systems. Features adaptive memory…. The licence is MIT.

Example prompts

  • “/agent-crdt-synchronizer”

Workflow steps

5 steps, taken from the first numbered list in SKILL.md.

  1. CRDT Implementation: Deploy state-based and operation-based conflict-free data types
  2. Data Structure Management: Handle counters, sets, registers, and composite structures
  3. Delta Synchronization: Implement efficient incremental state updates
  4. Conflict Resolution: Ensure deterministic conflict-free merge operations
  5. Causal Consistency: Maintain proper ordering of causally related operations

What it can do on your machine

Read from SKILL.md and the folder at commit 6051f67. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are javascript).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Agent Crdt Synchronizer loads about 6.3k tokens when it runs. Until then it costs about 24 tokens; SKILL.md has 190 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~24
When it runs · the whole SKILL.md, loaded when a task matches
~6.3k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from ruvnet/ruflo at commit 6051f67, republished under its MIT licence (© ruvnet). 190 words, ~6,286 tokens.

Download SKILL.mdSave it as .claude/skills/agent-crdt-synchronizer/SKILL.md (or your agent's skills folder).
name
agent-crdt-synchronizer
description
Agent skill for crdt-synchronizer - invoke with $agent-crdt-synchronizer

name: crdt-synchronizer type: synchronizer color: "#4CAF50" description: Implements Conflict-free Replicated Data Types for eventually consistent state synchronization capabilities:

  • state_based_crdts
  • operation_based_crdts
  • delta_synchronization
  • conflict_resolution
  • causal_consistency priority: high hooks: pre: | echo "🔄 CRDT Synchronizer syncing: $TASK"

    Initialize CRDT state tracking

    if [[ "$TASK" == "synchronization" ]]; then echo "📊 Preparing delta state computation" fi post: | echo "🎯 CRDT synchronization complete"

    Verify eventual consistency

    echo "✅ Validating conflict-free state convergence"

CRDT Synchronizer

Implements Conflict-free Replicated Data Types for eventually consistent distributed state synchronization.

Core Responsibilities

  1. CRDT Implementation: Deploy state-based and operation-based conflict-free data types
  2. Data Structure Management: Handle counters, sets, registers, and composite structures
  3. Delta Synchronization: Implement efficient incremental state updates
  4. Conflict Resolution: Ensure deterministic conflict-free merge operations
  5. Causal Consistency: Maintain proper ordering of causally related operations

Technical Implementation

Base CRDT Framework
javascript
class CRDTSynchronizer {
  constructor(nodeId, replicationGroup) {
    this.nodeId = nodeId;
    this.replicationGroup = replicationGroup;
    this.crdtInstances = new Map();
    this.vectorClock = new VectorClock(nodeId);
    this.deltaBuffer = new Map();
    this.syncScheduler = new SyncScheduler();
    this.causalTracker = new CausalTracker();
  }

  // Register CRDT instance
  registerCRDT(name, crdtType, initialState = null) {
    const crdt = this.createCRDTInstance(crdtType, initialState);
    this.crdtInstances.set(name, crdt);
    
    // Subscribe to CRDT changes for delta tracking
    crdt.onUpdate((delta) => {
      this.trackDelta(name, delta);
    });
    
    return crdt;
  }

  // Create specific CRDT instance
  createCRDTInstance(type, initialState) {
    switch (type) {
      case 'G_COUNTER':
        return new GCounter(this.nodeId, this.replicationGroup, initialState);
      case 'PN_COUNTER':
        return new PNCounter(this.nodeId, this.replicationGroup, initialState);
      case 'OR_SET':
        return new ORSet(this.nodeId, initialState);
      case 'LWW_REGISTER':
        return new LWWRegister(this.nodeId, initialState);
      case 'OR_MAP':
        return new ORMap(this.nodeId, this.replicationGroup, initialState);
      case 'RGA':
        return new RGA(this.nodeId, initialState);
      default:
        throw new Error(`Unknown CRDT type: ${type}`);
    }
  }

  // Synchronize with peer nodes
  async synchronize(peerNodes = null) {
    const targets = peerNodes || Array.from(this.replicationGroup);
    
    for (const peer of targets) {
      if (peer !== this.nodeId) {
        await this.synchronizeWithPeer(peer);
      }
    }
  }

  async synchronizeWithPeer(peerNode) {
    // Get current state and deltas
    const localState = this.getCurrentState();
    const deltas = this.getDeltasSince(peerNode);
    
    // Send sync request
    const syncRequest = {
      type: 'CRDT_SYNC_REQUEST',
      sender: this.nodeId,
      vectorClock: this.vectorClock.clone(),
      state: localState,
      deltas: deltas
    };
    
    try {
      const response = await this.sendSyncRequest(peerNode, syncRequest);
      await this.processSyncResponse(response);
    } catch (error) {
      console.error(`Sync failed with ${peerNode}:`, error);
    }
  }
}
G-Counter Implementation
javascript
class GCounter {
  constructor(nodeId, replicationGroup, initialState = null) {
    this.nodeId = nodeId;
    this.replicationGroup = replicationGroup;
    this.payload = new Map();
    
    // Initialize counters for all nodes
    for (const node of replicationGroup) {
      this.payload.set(node, 0);
    }
    
    if (initialState) {
      this.merge(initialState);
    }
    
    this.updateCallbacks = [];
  }

  // Increment operation (can only be performed by owner node)
  increment(amount = 1) {
    if (amount < 0) {
      throw new Error('G-Counter only supports positive increments');
    }
    
    const oldValue = this.payload.get(this.nodeId) || 0;
    const newValue = oldValue + amount;
    this.payload.set(this.nodeId, newValue);
    
    // Notify observers
    this.notifyUpdate({
      type: 'INCREMENT',
      node: this.nodeId,
      oldValue: oldValue,
      newValue: newValue,
      delta: amount
    });
    
    return newValue;
  }

  // Get current value (sum of all node counters)
  value() {
    return Array.from(this.payload.values()).reduce((sum, val) => sum + val, 0);
  }

  // Merge with another G-Counter state
  merge(otherState) {
    let changed = false;
    
    for (const [node, otherValue] of otherState.payload) {
      const currentValue = this.payload.get(node) || 0;
      if (otherValue > currentValue) {
        this.payload.set(node, otherValue);
        changed = true;
      }
    }
    
    if (changed) {
      this.notifyUpdate({
        type: 'MERGE',
        mergedFrom: otherState
      });
    }
  }

  // Compare with another state
  compare(otherState) {
    for (const [node, otherValue] of otherState.payload) {
      const currentValue = this.payload.get(node) || 0;
      if (currentValue < otherValue) {
        return 'LESS_THAN';
      } else if (currentValue > otherValue) {
        return 'GREATER_THAN';
      }
    }
    return 'EQUAL';
  }

  // Clone current state
  clone() {
    const newCounter = new GCounter(this.nodeId, this.replicationGroup);
    newCounter.payload = new Map(this.payload);
    return newCounter;
  }

  onUpdate(callback) {
    this.updateCallbacks.push(callback);
  }

  notifyUpdate(delta) {
    this.updateCallbacks.forEach(callback => callback(delta));
  }
}
OR-Set Implementation
javascript
class ORSet {
  constructor(nodeId, initialState = null) {
    this.nodeId = nodeId;
    this.elements = new Map(); // element -> Set of unique tags
    this.tombstones = new Set(); // removed element tags
    this.tagCounter = 0;
    
    if (initialState) {
      this.merge(initialState);
    }
    
    this.updateCallbacks = [];
  }

  // Add element to set
  add(element) {
    const tag = this.generateUniqueTag();
    
    if (!this.elements.has(element)) {
      this.elements.set(element, new Set());
    }
    
    this.elements.get(element).add(tag);
    
    this.notifyUpdate({
      type: 'ADD',
      element: element,
      tag: tag
    });
    
    return tag;
  }

  // Remove element from set
  remove(element) {
    if (!this.elements.has(element)) {
      return false; // Element not present
    }
    
    const tags = this.elements.get(element);
    const removedTags = [];
    
    // Add all tags to tombstones
    for (const tag of tags) {
      this.tombstones.add(tag);
      removedTags.push(tag);
    }
    
    this.notifyUpdate({
      type: 'REMOVE',
      element: element,
      removedTags: removedTags
    });
    
    return true;
  }

  // Check if element is in set
  has(element) {
    if (!this.elements.has(element)) {
      return false;
    }
    
    const tags = this.elements.get(element);
    
    // Element is present if it has at least one non-tombstoned tag
    for (const tag of tags) {
      if (!this.tombstones.has(tag)) {
        return true;
      }
    }
    
    return false;
  }

  // Get all elements in set
  values() {
    const result = new Set();
    
    for (const [element, tags] of this.elements) {
      // Include element if it has at least one non-tombstoned tag
      for (const tag of tags) {
        if (!this.tombstones.has(tag)) {
          result.add(element);
          break;
        }
      }
    }
    
    return result;
  }

  // Merge with another OR-Set
  merge(otherState) {
    let changed = false;
    
    // Merge elements and their tags
    for (const [element, otherTags] of otherState.elements) {
      if (!this.elements.has(element)) {
        this.elements.set(element, new Set());
      }
      
      const currentTags = this.elements.get(element);
      
      for (const tag of otherTags) {
        if (!currentTags.has(tag)) {
          currentTags.add(tag);
          changed = true;
        }
      }
    }
    
    // Merge tombstones
    for (const tombstone of otherState.tombstones) {
      if (!this.tombstones.has(tombstone)) {
        this.tombstones.add(tombstone);
        changed = true;
      }
    }
    
    if (changed) {
      this.notifyUpdate({
        type: 'MERGE',
        mergedFrom: otherState
      });
    }
  }

  generateUniqueTag() {
    return `${this.nodeId}-${Date.now()}-${++this.tagCounter}`;
  }

  onUpdate(callback) {
    this.updateCallbacks.push(callback);
  }

  notifyUpdate(delta) {
    this.updateCallbacks.forEach(callback => callback(delta));
  }
}
LWW-Register Implementation
javascript
class LWWRegister {
  constructor(nodeId, initialValue = null) {
    this.nodeId = nodeId;
    this.value = initialValue;
    this.timestamp = initialValue ? Date.now() : 0;
    this.vectorClock = new VectorClock(nodeId);
    this.updateCallbacks = [];
  }

  // Set new value with timestamp
  set(newValue, timestamp = null) {
    const ts = timestamp || Date.now();
    
    if (ts > this.timestamp || 
        (ts === this.timestamp && this.nodeId > this.getLastWriter())) {
      const oldValue = this.value;
      this.value = newValue;
      this.timestamp = ts;
      this.vectorClock.increment();
      
      this.notifyUpdate({
        type: 'SET',
        oldValue: oldValue,
        newValue: newValue,
        timestamp: ts
      });
    }
  }

  // Get current value
  get() {
    return this.value;
  }

  // Merge with another LWW-Register
  merge(otherRegister) {
    if (otherRegister.timestamp > this.timestamp ||
        (otherRegister.timestamp === this.timestamp && 
         otherRegister.nodeId > this.nodeId)) {
      
      const oldValue = this.value;
      this.value = otherRegister.value;
      this.timestamp = otherRegister.timestamp;
      
      this.notifyUpdate({
        type: 'MERGE',
        oldValue: oldValue,
        newValue: this.value,
        mergedFrom: otherRegister
      });
    }
    
    // Merge vector clocks
    this.vectorClock.merge(otherRegister.vectorClock);
  }

  getLastWriter() {
    // In real implementation, this would track the actual writer
    return this.nodeId;
  }

  onUpdate(callback) {
    this.updateCallbacks.push(callback);
  }

  notifyUpdate(delta) {
    this.updateCallbacks.forEach(callback => callback(delta));
  }
}
RGA (Replicated Growable Array) Implementation
javascript
class RGA {
  constructor(nodeId, initialSequence = []) {
    this.nodeId = nodeId;
    this.sequence = [];
    this.tombstones = new Set();
    this.vertexCounter = 0;
    
    // Initialize with sequence
    for (const element of initialSequence) {
      this.insert(this.sequence.length, element);
    }
    
    this.updateCallbacks = [];
  }

  // Insert element at position
  insert(position, element) {
    const vertex = this.createVertex(element, position);
    
    // Find insertion point based on causal ordering
    const insertionIndex = this.findInsertionIndex(vertex, position);
    
    this.sequence.splice(insertionIndex, 0, vertex);
    
    this.notifyUpdate({
      type: 'INSERT',
      position: insertionIndex,
      element: element,
      vertex: vertex
    });
    
    return vertex.id;
  }

  // Remove element at position
  remove(position) {
    if (position < 0 || position >= this.visibleLength()) {
      throw new Error('Position out of bounds');
    }
    
    const visibleVertex = this.getVisibleVertex(position);
    if (visibleVertex) {
      this.tombstones.add(visibleVertex.id);
      
      this.notifyUpdate({
        type: 'REMOVE',
        position: position,
        vertex: visibleVertex
      });
      
      return true;
    }
    
    return false;
  }

  // Get visible elements (non-tombstoned)
  toArray() {
    return this.sequence
      .filter(vertex => !this.tombstones.has(vertex.id))
      .map(vertex => vertex.element);
  }

  // Get visible length
  visibleLength() {
    return this.sequence.filter(vertex => !this.tombstones.has(vertex.id)).length;
  }

  // Merge with another RGA
  merge(otherRGA) {
    let changed = false;
    
    // Merge sequences
    const mergedSequence = this.mergeSequences(this.sequence, otherRGA.sequence);
    if (mergedSequence.length !== this.sequence.length) {
      this.sequence = mergedSequence;
      changed = true;
    }
    
    // Merge tombstones
    for (const tombstone of otherRGA.tombstones) {
      if (!this.tombstones.has(tombstone)) {
        this.tombstones.add(tombstone);
        changed = true;
      }
    }
    
    if (changed) {
      this.notifyUpdate({
        type: 'MERGE',
        mergedFrom: otherRGA
      });
    }
  }

  createVertex(element, position) {
    const leftVertex = position > 0 ? this.getVisibleVertex(position - 1) : null;
    
    return {
      id: `${this.nodeId}-${++this.vertexCounter}`,
      element: element,
      leftOrigin: leftVertex ? leftVertex.id : null,
      timestamp: Date.now(),
      nodeId: this.nodeId
    };
  }

  findInsertionIndex(vertex, targetPosition) {
    // Simplified insertion logic - in practice would use more sophisticated
    // causal ordering based on left origins and vector clocks
    let visibleCount = 0;
    
    for (let i = 0; i < this.sequence.length; i++) {
      if (!this.tombstones.has(this.sequence[i].id)) {
        if (visibleCount === targetPosition) {
          return i;
        }
        visibleCount++;
      }
    }
    
    return this.sequence.length;
  }

  getVisibleVertex(position) {
    let visibleCount = 0;
    
    for (const vertex of this.sequence) {
      if (!this.tombstones.has(vertex.id)) {
        if (visibleCount === position) {
          return vertex;
        }
        visibleCount++;
      }
    }
    
    return null;
  }

  mergeSequences(seq1, seq2) {
    // Simplified merge - real implementation would use topological sort
    // based on causal dependencies
    const merged = [...seq1];
    
    for (const vertex of seq2) {
      if (!merged.find(v => v.id === vertex.id)) {
        merged.push(vertex);
      }
    }
    
    // Sort by timestamp for basic ordering
    return merged.sort((a, b) => a.timestamp - b.timestamp);
  }

  onUpdate(callback) {
    this.updateCallbacks.push(callback);
  }

  notifyUpdate(delta) {
    this.updateCallbacks.forEach(callback => callback(delta));
  }
}
Delta-State CRDT Framework
javascript
class DeltaStateCRDT {
  constructor(baseCRDT) {
    this.baseCRDT = baseCRDT;
    this.deltaBuffer = [];
    this.lastSyncVector = new Map();
    this.maxDeltaBuffer = 1000;
  }

  // Apply operation and track delta
  applyOperation(operation) {
    const oldState = this.baseCRDT.clone();
    const result = this.baseCRDT.applyOperation(operation);
    const newState = this.baseCRDT.clone();
    
    // Compute delta
    const delta = this.computeDelta(oldState, newState);
    this.addDelta(delta);
    
    return result;
  }

  // Add delta to buffer
  addDelta(delta) {
    this.deltaBuffer.push({
      delta: delta,
      timestamp: Date.now(),
      vectorClock: this.baseCRDT.vectorClock.clone()
    });
    
    // Maintain buffer size
    if (this.deltaBuffer.length > this.maxDeltaBuffer) {
      this.deltaBuffer.shift();
    }
  }

  // Get deltas since last sync with peer
  getDeltasSince(peerNode) {
    const lastSync = this.lastSyncVector.get(peerNode) || new VectorClock();
    
    return this.deltaBuffer.filter(deltaEntry => 
      deltaEntry.vectorClock.isAfter(lastSync)
    );
  }

  // Apply received deltas
  applyDeltas(deltas) {
    const sortedDeltas = this.sortDeltasByCausalOrder(deltas);
    
    for (const delta of sortedDeltas) {
      this.baseCRDT.merge(delta.delta);
    }
  }

  // Compute delta between two states
  computeDelta(oldState, newState) {
    // Implementation depends on specific CRDT type
    // This is a simplified version
    return {
      type: 'STATE_DELTA',
      changes: this.compareStates(oldState, newState)
    };
  }

  sortDeltasByCausalOrder(deltas) {
    // Sort deltas to respect causal ordering
    return deltas.sort((a, b) => {
      if (a.vectorClock.isBefore(b.vectorClock)) return -1;
      if (b.vectorClock.isBefore(a.vectorClock)) return 1;
      return 0;
    });
  }

  // Garbage collection for old deltas
  garbageCollectDeltas() {
    const cutoffTime = Date.now() - (24 * 60 * 60 * 1000); // 24 hours
    
    this.deltaBuffer = this.deltaBuffer.filter(
      deltaEntry => deltaEntry.timestamp > cutoffTime
    );
  }
}

MCP Integration Hooks

Memory Coordination for CRDT State
javascript
// Store CRDT state persistently
await this.mcpTools.memory_usage({
  action: 'store',
  key: `crdt_state_${this.crdtName}`,
  value: JSON.stringify({
    type: this.crdtType,
    state: this.serializeState(),
    vectorClock: Array.from(this.vectorClock.entries()),
    lastSync: Array.from(this.lastSyncVector.entries())
  }),
  namespace: 'crdt_synchronization',
  ttl: 0 // Persistent
});

// Coordinate delta synchronization
await this.mcpTools.memory_usage({
  action: 'store',
  key: `deltas_${this.nodeId}_${Date.now()}`,
  value: JSON.stringify(this.getDeltasSince(null)),
  namespace: 'crdt_deltas',
  ttl: 86400000 // 24 hours
});
Performance Monitoring
javascript
// Track CRDT synchronization metrics
await this.mcpTools.metrics_collect({
  components: [
    'crdt_merge_time',
    'delta_generation_time',
    'sync_convergence_time',
    'memory_usage_per_crdt'
  ]
});

// Neural pattern learning for sync optimization
await this.mcpTools.neural_patterns({
  action: 'learn',
  operation: 'crdt_sync_optimization',
  outcome: JSON.stringify({
    syncPattern: this.lastSyncPattern,
    convergenceTime: this.lastConvergenceTime,
    networkTopology: this.networkState
  })
});

Advanced CRDT Features

Causal Consistency Tracker
javascript
class CausalTracker {
  constructor(nodeId) {
    this.nodeId = nodeId;
    this.vectorClock = new VectorClock(nodeId);
    this.causalBuffer = new Map();
    this.deliveredEvents = new Set();
  }

  // Track causal dependencies
  trackEvent(event) {
    event.vectorClock = this.vectorClock.clone();
    this.vectorClock.increment();
    
    // Check if event can be delivered
    if (this.canDeliver(event)) {
      this.deliverEvent(event);
      this.checkBufferedEvents();
    } else {
      this.bufferEvent(event);
    }
  }

  canDeliver(event) {
    // Event can be delivered if all its causal dependencies are satisfied
    for (const [nodeId, clock] of event.vectorClock.entries()) {
      if (nodeId === event.originNode) {
        // Origin node's clock should be exactly one more than current
        if (clock !== this.vectorClock.get(nodeId) + 1) {
          return false;
        }
      } else {
        // Other nodes' clocks should not exceed current
        if (clock > this.vectorClock.get(nodeId)) {
          return false;
        }
      }
    }
    return true;
  }

  deliverEvent(event) {
    if (!this.deliveredEvents.has(event.id)) {
      // Update vector clock
      this.vectorClock.merge(event.vectorClock);
      
      // Mark as delivered
      this.deliveredEvents.add(event.id);
      
      // Apply event to CRDT
      this.applyCRDTOperation(event);
    }
  }

  bufferEvent(event) {
    if (!this.causalBuffer.has(event.id)) {
      this.causalBuffer.set(event.id, event);
    }
  }

  checkBufferedEvents() {
    const deliverable = [];
    
    for (const [eventId, event] of this.causalBuffer) {
      if (this.canDeliver(event)) {
        deliverable.push(event);
      }
    }
    
    // Deliver events in causal order
    for (const event of deliverable) {
      this.causalBuffer.delete(event.id);
      this.deliverEvent(event);
    }
  }
}
CRDT Composition Framework
javascript
class CRDTComposer {
  constructor() {
    this.compositeTypes = new Map();
    this.transformations = new Map();
  }

  // Define composite CRDT structure
  defineComposite(name, schema) {
    this.compositeTypes.set(name, {
      schema: schema,
      factory: (nodeId, replicationGroup) => 
        this.createComposite(schema, nodeId, replicationGroup)
    });
  }

  createComposite(schema, nodeId, replicationGroup) {
    const composite = new CompositeCRDT(nodeId, replicationGroup);
    
    for (const [fieldName, fieldSpec] of Object.entries(schema)) {
      const fieldCRDT = this.createFieldCRDT(fieldSpec, nodeId, replicationGroup);
      composite.addField(fieldName, fieldCRDT);
    }
    
    return composite;
  }

  createFieldCRDT(fieldSpec, nodeId, replicationGroup) {
    switch (fieldSpec.type) {
      case 'counter':
        return fieldSpec.decrements ? 
          new PNCounter(nodeId, replicationGroup) :
          new GCounter(nodeId, replicationGroup);
      case 'set':
        return new ORSet(nodeId);
      case 'register':
        return new LWWRegister(nodeId);
      case 'map':
        return new ORMap(nodeId, replicationGroup, fieldSpec.valueType);
      case 'sequence':
        return new RGA(nodeId);
      default:
        throw new Error(`Unknown CRDT field type: ${fieldSpec.type}`);
    }
  }
}

class CompositeCRDT {
  constructor(nodeId, replicationGroup) {
    this.nodeId = nodeId;
    this.replicationGroup = replicationGroup;
    this.fields = new Map();
    this.updateCallbacks = [];
  }

  addField(name, crdt) {
    this.fields.set(name, crdt);
    
    // Subscribe to field updates
    crdt.onUpdate((delta) => {
      this.notifyUpdate({
        type: 'FIELD_UPDATE',
        field: name,
        delta: delta
      });
    });
  }

  getField(name) {
    return this.fields.get(name);
  }

  merge(otherComposite) {
    let changed = false;
    
    for (const [fieldName, fieldCRDT] of this.fields) {
      const otherField = otherComposite.fields.get(fieldName);
      if (otherField) {
        const oldState = fieldCRDT.clone();
        fieldCRDT.merge(otherField);
        
        if (!this.statesEqual(oldState, fieldCRDT)) {
          changed = true;
        }
      }
    }
    
    if (changed) {
      this.notifyUpdate({
        type: 'COMPOSITE_MERGE',
        mergedFrom: otherComposite
      });
    }
  }

  serialize() {
    const serialized = {};
    
    for (const [fieldName, fieldCRDT] of this.fields) {
      serialized[fieldName] = fieldCRDT.serialize();
    }
    
    return serialized;
  }

  onUpdate(callback) {
    this.updateCallbacks.push(callback);
  }

  notifyUpdate(delta) {
    this.updateCallbacks.forEach(callback => callback(delta));
  }
}

Integration with Consensus Protocols

CRDT-Enhanced Consensus
javascript
class CRDTConsensusIntegrator {
  constructor(consensusProtocol, crdtSynchronizer) {
    this.consensus = consensusProtocol;
    this.crdt = crdtSynchronizer;
    this.hybridOperations = new Map();
  }

  // Hybrid operation: consensus for ordering, CRDT for state
  async hybridUpdate(operation) {
    // Step 1: Achieve consensus on operation ordering
    const consensusResult = await this.consensus.propose({
      type: 'CRDT_OPERATION',
      operation: operation,
      timestamp: Date.now()
    });
    
    if (consensusResult.committed) {
      // Step 2: Apply operation to CRDT with consensus-determined order
      const orderedOperation = {
        ...operation,
        consensusIndex: consensusResult.index,
        globalTimestamp: consensusResult.timestamp
      };
      
      await this.crdt.applyOrderedOperation(orderedOperation);
      
      return {
        success: true,
        consensusIndex: consensusResult.index,
        crdtState: this.crdt.getCurrentState()
      };
    }
    
    return { success: false, reason: 'Consensus failed' };
  }

  // Optimized read operations using CRDT without consensus
  async optimisticRead(key) {
    return this.crdt.read(key);
  }

  // Strong consistency read requiring consensus verification
  async strongRead(key) {
    // Verify current CRDT state against consensus
    const consensusState = await this.consensus.getCommittedState();
    const crdtState = this.crdt.getCurrentState();
    
    if (this.statesConsistent(consensusState, crdtState)) {
      return this.crdt.read(key);
    } else {
      // Reconcile states before read
      await this.reconcileStates(consensusState, crdtState);
      return this.crdt.read(key);
    }
  }
}

This CRDT Synchronizer provides comprehensive support for conflict-free replicated data types, enabling eventually consistent distributed state management that complements consensus protocols for different consistency requirements.

© ruvnet, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/agent-crdt-synchronizer of ruvnet/ruflo.

Open the folder on GitHubat commit 6051f67

Used in 3 other repositories

We found 4 copies of this SKILL.md (exact, near-identical or edited) in other folders, from 3 other GitHub owners. This page covers the copy in ruvnet/ruflo, which our catalogue first saw on October 7, 2026.

Compare with similar skills

Agent Crdt Synchronizer next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Agent Crdt Synchronizer compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Agent Crdt Synchronizer this skillruvnet/ruflo74k3 repos~6.3kAutomated safety check: PassMIT
Create Invoke TaskDataDog/datadog-agent3.8k—~606Automated safety check: NotesApache-2.0
Golem Invoke Agent Moonbitgolemcloud/golem1.5k—~1.4kAutomated safety check: PassCustom licence
Golem Invoke Agent Rustgolemcloud/golem1.5k—~1.4kAutomated safety check: PassCustom licence
Golem Invoke Agent Scalagolemcloud/golem1.5k—~1.4kAutomated safety check: PassCustom licence
Golem Invoke Agent TSgolemcloud/golem1.5k—~1.4kAutomated safety check: PassCustom licence

Similar skills

  • Create Invoke Task

    DataDog/datadog-agent

    Official

    Create a new Python invoke task for the dda CLI. An agent skill from DataDog/datadog-agent.

    3.8k GitHub stars~606 tokensUpdated today
    Auto-check: notes
  • Invoking a MoonBit Golem agent method from the CLI. An agent skill from golemcloud/golem.

    1.5k GitHub stars~1.4k tokensUpdated today
    Auto-check passed
  • Golem Invoke Agent Rust

    golemcloud/golem

    Invoking a Rust Golem agent method from the CLI. An agent skill from golemcloud/golem.

    1.5k GitHub stars~1.4k tokensUpdated today
    Auto-check passed
  • Golem Invoke Agent Scala

    golemcloud/golem

    Invoking a Scala Golem agent method from the CLI. An agent skill from golemcloud/golem.

    1.5k GitHub stars~1.4k tokensUpdated today
    Auto-check passed
  • Golem Invoke Agent TS

    golemcloud/golem

    Invoking a TypeScript Golem agent method from the CLI. An agent skill from golemcloud/golem.

    1.5k GitHub stars~1.4k tokensUpdated today
    Auto-check passed
  • Invoking an Effect-based Golem agent method from the CLI. An agent skill from golemcloud/golem.

    1.5k GitHub stars~1.3k tokensUpdated today
    Auto-check passed

More from ruvnet/ruflo

All 264 skills in this repo
  • Stores, searches, and retrieves successful patterns with HNSW-indexed semantic search so agents can reuse past solutions instead of relearning them.

    74k GitHub starsUsed in 3 repos~830 tokens
    Auto-check passed
  • Runs claude-flow CLI security scans for input validation, path traversal, SQL injection, XSS, hardcoded secrets and known CVEs, and writes an audit report.

    74k GitHub starsUsed in 2 repos~823 tokens
    Auto-check passed
  • Applies the SPARC method (specification, pseudocode, architecture, refinement, completion) with 17 specialized modes and multi-agent orchestration, from research to deployment.

    74k GitHub starsUsed in 2 repos~829 tokens
    Auto-check passed
  • Coordinates a hierarchical swarm of specialized agents through the claude-flow CLI for work that spans several files or modules at once.

    74k GitHub starsUsed in 2 repos~779 tokens
    Auto-check passed
  • Sets up and drives Ruflo, an npm-installed orchestration layer for multi-agent swarms, persistent memory, routing, hooks and its MCP tool catalog.

    74k GitHub starsUsed in 1 repo~975 tokens
    Auto-check passed
  • Agent Coordination

    ruvnet/ruflo

    Reference for spawning, listing, monitoring and stopping agents with claude-flow commands, with agent type families, routing codes and coordination tips.

    74k GitHub starsUsed in 2 repos~519 tokens
    Auto-check passed

Questions about Agent Crdt Synchronizer

What does Agent Crdt Synchronizer do?

Agent skill for crdt-synchronizer - invoke with $agent-crdt-synchronizer. Agent Crdt Synchronizer is an agent skill from ruvnet/ruflo.

How do I install Agent Crdt Synchronizer in Claude Code?

Run `npx skills add ruvnet/ruflo --skill agent-crdt-synchronizer -a claude-code`. Or copy the skill folder (.agents/skills/agent-crdt-synchronizer in ruvnet/ruflo) into .claude/skills/agent-crdt-synchronizer in your project. Claude Code loads it when a task matches its description.

How do I install Agent Crdt Synchronizer in Codex?

Run `npx skills add ruvnet/ruflo --skill agent-crdt-synchronizer -a codex`. Or copy the skill folder (.agents/skills/agent-crdt-synchronizer in ruvnet/ruflo) into .agents/skills/agent-crdt-synchronizer in your project. Codex loads it when a task matches its description.

Can I use Agent Crdt Synchronizer in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add ruvnet/ruflo --skill agent-crdt-synchronizer -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/agent-crdt-synchronizer, .gemini/skills/agent-crdt-synchronizer, .github/skills/agent-crdt-synchronizer and .opencode/skills/agent-crdt-synchronizer in your project.

What does Agent Crdt Synchronizer need to run?

SKILL.md names no scripts, command-line tools or credentials: Agent Crdt Synchronizer is instructions for the agent only.

Does Agent Crdt Synchronizer access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Agent Crdt Synchronizer safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Agent Crdt Synchronizer use?

Agent Crdt Synchronizer is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Agent Crdt Synchronizer use?

About 6.3k tokens (SKILL.md is roughly 25k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Agent Crdt Synchronizer?

Skills that share tags, products or a category with Agent Crdt Synchronizer: Create Invoke Task (DataDog/datadog-agent, 3.8k stars), Golem Invoke Agent Moonbit (golemcloud/golem, 1.5k stars), Golem Invoke Agent Rust (golemcloud/golem, 1.5k stars) and Golem Invoke Agent Scala (golemcloud/golem, 1.5k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Agent Crdt Synchronizer?

ruvnet (a GitHub user) maintains it in ruvnet/ruflo, which has 74,089 GitHub stars. The repository holds 264 skills in this directory. The repository was last updated on October 8, 2026.

Source: ruvnet/ruflo on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.