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

mihomo-config

v0.2.0

Published

Type-safe TypeScript library for generating mihomo (Clash Meta) proxy configuration

Readme

mihomo-config

Type-safe TypeScript library for generating mihomo (Clash Meta) proxy configuration dynamically. Runtime validation via Zod, YAML serialization via js-yaml.

Example

mihomo-worker

Install

npm install mihomo-config

Quick Start

import {
  vless, select, urlTest, loadBalance,
  dns, sniffer, experimental,
  ruleProvider, proxyProvider,
  ruleSet, domainSuffix, ipCidr, match,
  createConfig, toYaml,
} from 'mihomo-config'

const config = createConfig({
  'log-level': 'warning',
  'find-process-mode': 'off',
  dns: dns({
    enable: true,
    listen: '0.0.0.0:53',
    'enhanced-mode': 'redir-host',
    nameserver: ['https://1.1.1.1/dns-query'],
  }),
  sniffer: sniffer({ enable: true }),
  proxies: [
    vless({
      name: 'JP',
      server: '1.2.3.4',
      port: 443,
      uuid: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
      tls: true,
      flow: 'xtls-rprx-vision',
      network: 'tcp',
      'reality-opts': { 'public-key': 'xxxxx', 'short-id': 'abc' },
    }),
  ],
  'proxy-groups': [
    select({ name: '节点选择', type: 'select', proxies: ['JP', 'DIRECT'] }),
  ],
  rules: [ruleSet('geosite_cn', 'DIRECT'), match('节点选择')],
  'rule-providers': {
    geosite_cn: ruleProvider({
      type: 'http', behavior: 'domain', format: 'mrs',
      interval: 3600, url: 'https://example.com/cn.mrs',
    }),
  },
  experimental: experimental({ 'dialer-ip4p-convert': true }),
})

console.log(toYaml(config))

API

Proxies

All proxy factories return validated objects with a type field. Each accepts an options object matching the mihomo config schema — keys use kebab-case (same as YAML).

import { vless, vmess, trojan, shadowsocks, hysteria2, tuic, wireguard } from 'mihomo-config'

vless({ name: '...', server: '...', port: 443, uuid: '...', /* ... */ })
vmess({ name: '...', server: '...', port: 443, uuid: '...', alterId: 0, cipher: 'auto', /* ... */ })
trojan({ name: '...', server: '...', port: 443, password: '...', /* ... */ })
shadowsocks({ name: '...', server: '...', port: 8388, password: '...', cipher: 'aes-256-gcm', /* ... */ })
hysteria2({ name: '...', server: '...', port: 443, password: '...', /* ... */ })
tuic({ name: '...', server: '...', port: 443, uuid: '...', password: '...', /* ... */ })
wireguard({ name: '...', server: '...', port: 51820, 'private-key': '...', ip: '...', /* ... */ })

Additional proxy types: socks5, http, snell, ssh, anytls, shadowsocksr, heybox, direct.

Common options available on most proxies: udp, tfo, mptcp, interface-name, routing-mark, dialer-proxy, ip-version, client-fingerprint, plus transport sub-options (ws-opts, grpc-opts, http-opts, h2-opts, xhttp-opts).

heybox (小黑盒加速器)

heybox is the 小黑盒 accelerator outbound: sessions (session id / handshake key / node port) are issued atomically by the accelerator API and fetched lazily on first traffic, so there is no server/port. It is normally generated by a type: 'heybox' proxy provider rather than hand-written:

import { heybox, proxyProvider } from 'mihomo-config'

proxyProvider({
  type: 'heybox',
  'heybox-id': 16651571,              // 小黑盒账号 ID (required)
  pkey: 'MTc4...',                    // 登录凭据,每次登录轮换 (required)
  games: [356],                       // 游戏 acc_id 列表,356 = Switch (required)
  // isp: 'liantong',                 // 'all' | 'dianxin' | 'liantong' | 'yidong' | 'bgp'
  // api: 'https://accapi.xiaoheihe.cn',
  interval: 600,                      // 枚举刷新,默认 600s,无会话副作用
})

// 手写单条时(通常不必):除标注可选外均必填,上游严格解码器要求显式出现
heybox({
  name: 'Switch-通用-日本3',
  'heybox-id': 16651571,
  pkey: 'MTc4...',
  'acc-id': 356,
  'game-id': 0,
  'server-region': 1,
  'node-name': '日本3',               // 会话按此分配
  'acc-mode': 1,
  'transport-proto': 'udp',
  // isp: 'liantong',                 // 可选
  // 'node-ip': '1.2.3.4', 'echo-addr': '1.2.3.4:443', 'rtt-avg': 30,
})

Health-check / group URL tests use the node-entry UDP echo (zero sessions, zero TCP) and health-check is ignored on heybox providers. Node names from the provider are {游戏名}-{节点名} (e.g. Switch-通用-日本3), filterable via filter/exclude-filter.

Proxy Groups

import { select, urlTest, fallback, loadBalance, relay } from 'mihomo-config'

select({ name: '节点选择', type: 'select', proxies: ['JP', 'DIRECT'] })
urlTest({ name: '日本自动', type: 'url-test', url: 'https://cp.cloudflare.com', interval: 300, tolerance: 100 })
fallback({ name: '回退', type: 'fallback', url: 'https://cp.cloudflare.com', interval: 300, proxies: ['JP', 'DIRECT'] })
loadBalance({ name: '负载均衡', type: 'load-balance', strategy: 'sticky-sessions', interval: 300, proxies: ['JP1', 'JP2'] })
relay({ name: '链路', type: 'relay', proxies: ['JP', 'US'] })

DNS

import { dns } from 'mihomo-config'

dns({
  enable: true,
  listen: '0.0.0.0:53',
  'enhanced-mode': 'redir-host',       // 'normal' | 'fake-ip' | 'redir-host'
  'cache-algorithm': 'arc',             // 'lru' | 'arc'
  nameserver: ['https://1.1.1.1/dns-query'],
  'proxy-server-nameserver': ['https://223.5.5.5/dns-query'],
  'direct-nameserver': ['https://120.53.53.53/dns-query'],

  // IP 优选: DNS 答案命中 cidr 段时,替换为内嵌测速器筛出的优选池前 N 条
  'preferred-ip': [
    {
      name: 'cloudflare',              // 持久化键,不能重复
      cidr: ['173.245.48.0/20', '103.21.244.0/22'],
      ipv6: 'block',                   // 'replace' (默认) | 'block'
      'answer-count': 5,               // 改写后返回前 N 条,默认 5
      'ttl-cap': 60,                   // 改写记录 TTL 上限(秒),默认 60
      persist: true,                   // 持久化到 cache.db,默认 true
      speedtest: {
        url: '',                       // 留空用 speed.cloudflare.com
        interval: '24h',               // 定时重测,支持 '24h' 或秒数,默认 24h
        'disable-download': false,     // true 则仅按延迟排序
        threads: 200,                  // tcping 并发,默认 200
        'tcp-port': 443,               // tcping 端口,默认 443
        'ping-times': 4,               // tcping 次数,默认 4
        'download-count': 10,          // 参与下载测速数量,默认 10
        'download-time': '10s',        // 单 IP 下载时长,默认 10s
        'max-delay': '9999ms',         // 平均延迟上限
        // 'min-delay': '0ms', 'max-loss-rate': 1.0, 'min-speed': 0,
      },
    },
  ],
})

Sniffer

import { sniffer } from 'mihomo-config'

sniffer({
  enable: true,
  'parse-pure-ip': true,
  'force-domain': ['+.google.com'],
  sniff: {
    HTTP: { ports: ['80', '8080-8880'], 'override-destination': true },
    TLS: { ports: ['443'] },
    QUIC: { ports: ['443'] },
  },
})

TUN

import { tun } from 'mihomo-config'

tun({
  enable: true,
  stack: 'mixed',                       // 'gvisor' | 'system' | 'mixed'
  'auto-route': true,
  'auto-detect-interface': true,
  'dns-hijack': ['any:53'],
})

Rules

All rule functions return a RULE-TYPE,payload,target[,params...] string.

import {
  domain, domainSuffix, domainKeyword, domainRegex,
  geoSite, geoIp, ipCidr, srcIpCidr,
  ruleSet, match, network, processName,
  dstPort, srcPort, inPort, inType,
  and, or, not, subRule,
} from 'mihomo-config'

domainSuffix('google.com', '节点选择')            // DOMAIN-SUFFIX,google.com,节点选择
ipCidr('192.168.0.0/16', 'DIRECT', 'no-resolve') // IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
ruleSet('geosite_cn', 'DIRECT')                   // RULE-SET,geosite_cn,DIRECT
match('节点选择')                                  // MATCH,节点选择

Providers

import { ruleProvider, proxyProvider } from 'mihomo-config'

ruleProvider({
  type: 'http',
  behavior: 'domain',                  // 'domain' | 'ipcidr' | 'classical'
  format: 'mrs',                       // 'mrs' | 'yaml' | 'text'
  interval: 3600,
  url: 'https://example.com/rule.mrs',
})

proxyProvider({
  type: 'http',
  interval: 86400,
  url: 'https://example.com/sub',
})

Listeners

import { listener } from 'mihomo-config'

listener({
  type: 'mixed',
  listen: '0.0.0.0:7893',
})

Experimental

import { experimental } from 'mihomo-config'

experimental({
  'dialer-ip4p-convert': true,
  'quic-go-disable-gso': false,
  'quic-go-disable-ecn': false,
})

Top-level Config

createConfig() assembles all sections into a validated config object. Accepts all mihomo top-level keys.

import { createConfig } from 'mihomo-config'

const config = createConfig({
  'mixed-port': 7890,
  'allow-lan': true,
  mode: 'rule',
  'log-level': 'info',
  dns: dns({ /* ... */ }),
  sniffer: sniffer({ /* ... */ }),
  tun: tun({ /* ... */ }),
  proxies: [/* ... */],
  'proxy-groups': [/* ... */],
  'proxy-providers': { /* ... */ },
  rules: [/* ... */],
  'rule-providers': { /* ... */ },
  experimental: experimental({ /* ... */ }),
})

YAML Serialization

import { toYaml } from 'mihomo-config'

const yaml = toYaml(config)  // string

Development

npm install
npm run build       # tsup → dist/
npm test            # vitest
npm run typecheck   # tsc --noEmit

License

MIT