npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@skillbolt/sync

v1.0.1

Published

Cross-device Skill synchronization with cloud backends for Skillbolt

Downloads

7

Readme

@skillbolt/sync

技能同步工具,支持将技能同步到云端存储,实现跨设备共享和备份。

功能特性

  • 多云后端: 支持 GitHub Gist、Supabase 等多种存储后端
  • 自动同步: 可配置自动同步策略
  • 冲突解决: 智能检测和解决同步冲突
  • 离线队列: 支持离线操作,网络恢复后自动同步
  • 增量同步: 仅同步变更的技能,提高效率
  • 版本历史: 保留技能的版本历史
  • 网络监控: 自动检测网络状态

基本使用

CLI 使用

# 推送技能到云端
skill sync push

# 从云端拉取技能
skill sync pull

# 查看同步状态
skill sync status

# 强制推送(覆盖远程)
skill sync push --force

# 强制拉取(覆盖本地)
skill sync pull --force

API 使用

import { SyncEngine, push, pull, syncStatus } from '@skillbolt/sync';

// 创建同步引擎
const syncEngine = new SyncEngine({
  backend: {
    type: 'github-gist',
    credentials: {
      token: 'your-github-token',
      gistId: 'your-gist-id'
    }
  }
});

// 推送技能
const pushResult = await syncEngine.push();
console.log(`Pushed ${pushResult.pushed} skills`);

// 拉取技能
const pullResult = await syncEngine.pull();
console.log(`Pulled ${pullResult.pulled} skills`);

// 查看状态
const status = await syncEngine.getStatus();
console.log(`Local: ${status.local.length}, Remote: ${status.remote.length}`);

后端配置

GitHub Gist

import { SyncEngine } from '@skillbolt/sync';

const syncEngine = new SyncEngine({
  backend: {
    type: 'github-gist',
    credentials: {
      token: process.env.GITHUB_TOKEN,
      gistId: process.env.GIST_ID
    }
  }
});

Supabase

import { SyncEngine } from '@skillbolt/sync';

const syncEngine = new SyncEngine({
  backend: {
    type: 'supabase',
    credentials: {
      url: 'https://your-project.supabase.co',
      anonKey: 'your-anon-key'
    }
  }
});

自定义后端

import { BaseBackend, SyncEngine } from '@skillbolt/sync';

class CustomBackend extends BaseBackend {
  async upload(skill: LocalSkill): Promise<UploadResult> {
    // 自定义上传逻辑
  }

  async download(skillId: string): Promise<RemoteSkill> {
    // 自定义下载逻辑
  }

  async delete(skillId: string): Promise<DeleteResult> {
    // 自定义删除逻辑
  }

  async list(): Promise<RemoteSkill[]> {
    // 自定义列出逻辑
  }
}

const syncEngine = new SyncEngine({
  backend: new CustomBackend()
});

同步操作

推送 (Push)

import { push } from '@skillbolt/sync';

const result = await push({
  backend: 'github-gist',
  credentials: { token: 'xxx', gistId: 'yyy' },
  skills: ['skill-1', 'skill-2'], // 特定技能,不指定则全部
  force: false
});

console.log(result.pushed); // 推送的数量
console.log(result.skipped); // 跳过的数量
console.log(result.failed); // 失败的数量

拉取 (Pull)

import { pull } from '@skillbolt/sync';

const result = await pull({
  backend: 'supabase',
  credentials: { url: 'xxx', anonKey: 'yyy' },
  force: false
});

console.log(result.pulled); // 拉取的数量
console.log(result.skipped); // 跳过的数量
console.log(result.failed); // 失败的数量

状态检查

import { syncStatus } from '@skillbolt/sync';

const status = await syncStatus();

status.skills.forEach(skill => {
  console.log(`${skill.name}: ${skill.status}`);
  // 'synced', 'local-only', 'remote-only', 'conflict'
});

console.log(`Overall: ${status.overallStatus}`);
// 'synced', 'needs-sync', 'has-conflicts'

冲突解决

检测冲突

import { detectConflicts } from '@skillbolt/sync';

const conflicts = await detectConflicts(localSkills, remoteSkills);

conflicts.forEach(conflict => {
  console.log(`Conflict in ${conflict.skillName}`);
  console.log(`Local version: ${conflict.localVersion}`);
  console.log(`Remote version: ${conflict.remoteVersion}`);
});

解决冲突

import { resolveConflict, resolveConflictWithBackup } from '@skillbolt/sync';

// 策略: 使用本地版本
await resolveConflict(conflict, 'local');

// 策略: 使用远程版本
await resolveConflict(conflict, 'remote');

// 策略: 创建备份后使用本地
await resolveConflictWithBackup(conflict, 'local');

// 策略: 手动解决
const resolved = {
  name: conflict.skillName,
  content: 'merged content',
  version: '1.0.0'
};
await resolveConflict(conflict, 'manual', resolved);

离线队列

使用离线队列

import { OfflineQueue } from '@skillbolt/sync';

const queue = new OfflineQueue({
  storagePath: './.skillbolt/queue.json'
});

// 网络可用时,自动同步队列中的操作
queue.on('network:available', async () => {
  await queue.flush();
});

// 添加操作到队列
await queue.add({
  type: 'push',
  skillId: 'my-skill',
  timestamp: Date.now()
});

// 手动刷新队列
await queue.flush();

队列状态

const status = await queue.getStatus();
console.log(`Pending: ${status.pending}`);
console.log(`Failed: ${status.failed}`);
console.log(`Total: ${status.total}`);

自动同步

配置自动同步

import { SyncEngine } from '@skillbolt/sync';

const syncEngine = new SyncEngine({
  backend: {
    type: 'github-gist',
    credentials: { token: 'xxx', gistId: 'yyy' }
  },
  autoSync: {
    enabled: true,
    interval: 60000, // 每 60 秒
    onConflict: 'local', // 冲突时使用本地版本
    syncOnStartup: true // 启动时同步
  }
});

// 手动触发自动同步
await syncEngine.autoSync();

事件监听

syncEngine.on('sync:start', () => {
  console.log('Sync started');
});

syncEngine.on('sync:complete', (result) => {
  console.log('Sync completed', result);
});

syncEngine.on('sync:error', (error) => {
  console.error('Sync error', error);
});

syncEngine.on('conflict', (conflict) => {
  console.log('Conflict detected', conflict);
});

使用示例

示例 1: 基本同步

import { SyncEngine } from '@skillbolt/sync';

async function basicSync() {
  const syncEngine = new SyncEngine({
    backend: {
      type: 'github-gist',
      credentials: {
        token: process.env.GITHUB_TOKEN,
        gistId: process.env.GIST_ID
      }
    }
  });

  // 检查状态
  const status = await syncEngine.getStatus();
  console.log(`Local skills: ${status.local.length}`);
  console.log(`Remote skills: ${status.remote.length}`);

  // 如果需要同步
  if (status.overallStatus !== 'synced') {
    await syncEngine.push();
    await syncEngine.pull();
  }
}

示例 2: 处理冲突

import { SyncEngine, resolveConflict } from '@skillbolt/sync';

async function syncWithConflictHandling() {
  const syncEngine = new SyncEngine({
    backend: {
      type: 'github-gist',
      credentials: { token: 'xxx', gistId: 'yyy' }
    }
  });

  // 检测冲突
  const conflicts = await syncEngine.detectConflicts();

  // 解决冲突
  for (const conflict of conflicts) {
    console.log(`Resolving conflict for ${conflict.skillName}`);

    // 简单策略: 使用最新修改的版本
    if (conflict.localModifiedAt > conflict.remoteModifiedAt) {
      await resolveConflict(conflict, 'local');
    } else {
      await resolveConflict(conflict, 'remote');
    }
  }

  // 继续同步
  await syncEngine.push();
}

示例 3: 网络监控

import { SyncEngine, createNetworkMonitor } from '@skillbolt/sync';

async function syncWithNetworkMonitoring() {
  const syncEngine = new SyncEngine({
    backend: {
      type: 'supabase',
      credentials: { url: 'xxx', anonKey: 'yyy' }
    }
  });

  // 创建网络监控器
  const monitor = createNetworkMonitor({
    checkInterval: 5000, // 每 5 秒检查一次
    pingUrl: 'https://www.google.com'
  });

  // 网络可用时同步
  monitor.on('online', async () => {
    console.log('Network available, syncing...');
    await syncEngine.pull();
    await syncEngine.push();
  });

  // 网络不可用时记录
  monitor.on('offline', () => {
    console.log('Network unavailable');
  });

  // 启动监控
  monitor.start();
}

示例 4: 备份和恢复

import { SyncEngine } from '@skillbolt/sync';

async function backupSkills() {
  const syncEngine = new SyncEngine({
    backend: {
      type: 'github-gist',
      credentials: { token: 'xxx', gistId: 'yyy' }
    }
  });

  // 推送所有技能作为备份
  const result = await syncEngine.push({
    all: true,
    force: true // 覆盖远程
  });

  console.log(`Backed up ${result.pushed} skills`);
}

类型定义

interface SyncEngineOptions {
  backend: BackendConfig;
  autoSync?: AutoSyncConfig;
  queue?: QueueConfig;
  backup?: BackupSettings;
}

interface BackendConfig {
  type: BackendType;
  credentials: Credentials;
}

interface PushOptions {
  skills?: string[];
  force?: boolean;
  dryRun?: boolean;
}

interface PullOptions {
  skills?: string[];
  force?: boolean;
  dryRun?: boolean;
}

interface PushResult {
  pushed: number;
  skipped: number;
  failed: number;
  errors: Error[];
}

interface PullResult {
  pulled: number;
  skipped: number;
  failed: number;
  errors: Error[];
}

interface StatusResult {
  local: SkillStatus[];
  remote: SkillStatus[];
  overallStatus: OverallStatus;
}

interface SkillStatus {
  name: string;
  status: 'synced' | 'local-only' | 'remote-only' | 'conflict';
  localVersion?: string;
  remoteVersion?: string;
  localModifiedAt?: Date;
  remoteModifiedAt?: Date;
}

interface Conflict {
  skillName: string;
  local: LocalSkill;
  remote: RemoteSkill;
}

type BackendType = 'github-gist' | 'supabase' | 'custom';
type ConflictStrategy = 'local' | 'remote' | 'manual';
type OverallStatus = 'synced' | 'needs-sync' | 'has-conflicts';

CLI 命令

push

skill sync push

# 选项
skill sync push --force
skill sync push --skills skill-1,skill-2
skill sync push --dry-run

pull

skill sync pull

# 选项
skill sync pull --force
skill sync pull --skills skill-1,skill-2
skill sync pull --dry-run

status

skill sync status

# 选项
skill sync status --detailed
skill sync status --json

最佳实践

  1. 定期同步: 设置自动同步确保数据安全
  2. 冲突处理: 建立明确的冲突解决策略
  3. 网络监控: 在网络不稳定时使用离线队列
  4. 备份策略: 定期备份重要技能
  5. 版本控制: 保留技能的版本历史

故障排除

同步失败

如果同步失败:

  1. 检查网络连接
  2. 验证后端凭证
  3. 查看详细的错误日志
  4. 检查磁盘空间

冲突频繁

如果频繁出现冲突:

  1. 检查自动同步配置
  2. 调整同步间隔
  3. 审查多设备使用情况
  4. 建立明确的使用规范

性能问题

如果同步速度慢:

  1. 检查技能数量和大小
  2. 考虑增量同步
  3. 优化网络连接
  4. 使用更快的后端

API 参考

主要导出

// 核心
export { SyncEngine, computeSyncDiff, getSyncSummary };

// 冲突处理
export {
  detectConflicts,
  resolveConflict,
  resolveConflictWithBackup,
  createConflictBackup
};

// 后端
export {
  BaseBackend,
  SupabaseBackend,
  GitHubGistBackend,
  createBackend,
  getSupportedBackends
};

// 队列
export { OfflineQueue, QueueStorage };

// 命令
export { push, pull, syncStatus, formatStatus };

// 工具
export {
  computeHashFromString,
  computeHashFromFile,
  hashesMatch,
  checkNetworkConnectivity,
  createNetworkMonitor,
  scanLocalSkills,
  filterSkills
};

贡献

欢迎贡献!请查看 CONTRIBUTING.md 了解详细信息。

许可证

MIT