sub-store-convert runs the node conversion logic from Sub-Store as a standalone library, CLI, HTTP service, and Cloudflare Worker.
It can convert remote subscription links into formats used by clients such as Surge, Quantumult X, Loon, Clash/Mihomo, Stash, Shadowrocket, Surfboard, sing-box, Egern, and more.
- Standalone conversion core extracted from Sub-Store.
- HTTP API compatible with the common
subconverterstyle:/sub?target=...&url=.... - Local server support with Node.js or Bun.
- CLI for quick one-off conversions.
- Cloudflare Workers and Docker deployment support.
- Multiple subscription URLs supported by separating them with
|.
This repository is a pnpm workspace with three packages:
| Package | Description |
|---|---|
@sub-store-convert/core |
Core conversion library. Exports convert() and lower-level parser/producer helpers. |
@sub-store-convert/app |
Hono HTTP app for local server and Cloudflare Workers. |
@sub-store-convert/cli |
Interactive CLI wrapper around the core converter. |
- Node.js 22 or later is recommended.
- pnpm is used for workspace dependency management.
- Bun is optional, but used by the Docker runtime and supported by the local server script.
- Wrangler is required only for Cloudflare Workers deployment.
Clone the repository with its Sub-Store submodule:
git clone --recursive git@github.com:TBXark/sub-store-convert.git
cd sub-store-convert
pnpm installIf you cloned without --recursive, initialize the submodule before installing or building:
git submodule update --init --recursive
pnpm installBuild the core package first:
pnpm run build:coreStart the HTTP service locally:
pnpm run startThe service listens on http://localhost:3000 by default. Use PORT to change the port:
PORT=8080 pnpm run startConvert a subscription through the HTTP API:
curl "http://localhost:3000/sub?target=surge&url=https%3A%2F%2Fexample.com%2Fsubscription"GET /sub?target=<target>&url=<subscription-url>
Required query parameters:
| Parameter | Description |
|---|---|
target |
Output format, for example surge, qx, mihomo, sing-box, or json. |
url |
Remote subscription URL. Multiple URLs can be joined with ` |
Additional query parameters are passed to the converter as options. String values of true, false, and numeric values are converted to booleans or numbers automatically.
Example with multiple subscription URLs:
curl "http://localhost:3000/sub?target=mihomo&url=https%3A%2F%2Fexample.com%2Fa%7Chttps%3A%2F%2Fexample.com%2Fb"Run the workspace CLI:
pnpm run cli https://example.com/subscriptionThe CLI prompts for the target format. Press Enter to use the default target, surge.
Use the core package directly from JavaScript:
import { convert } from '@sub-store-convert/core'
const output = await convert('https://example.com/subscription', 'surge', {
udp: true,
})
console.log(output)Common target names include:
| Target | Aliases |
|---|---|
| Quantumult X | qx, QX, QuantumultX |
| Surge | surge, Surge, SurgeMac |
| Loon | Loon |
| Clash | Clash |
| Mihomo / Clash.Meta | meta, clashmeta, clash.meta, Clash.Meta, ClashMeta, mihomo, Mihomo |
| URI | uri, URI |
| V2Ray | v2, v2ray, V2Ray |
| JSON | json, JSON |
| Stash | stash, Stash |
| Shadowrocket | shadowrocket, Shadowrocket, ShadowRocket |
| Surfboard | surfboard, Surfboard |
| sing-box | singbox, sing-box |
| Egern | egern, Egern |
Supported input formats are inherited from Sub-Store parsers, including common URI formats and client formats such as Clash, Surge, Loon, and Quantumult X.
| Command | Description |
|---|---|
pnpm run build:core |
Build @sub-store-convert/core. |
pnpm run build:app |
Build the Cloudflare Worker bundle. |
pnpm run build:docker |
Build the Docker image ghcr.io/tbxark/sub-store-convert:latest. |
pnpm run start |
Start the HTTP service with Bun, falling back to Node.js. |
pnpm run start:bun |
Start the HTTP service with Bun. |
pnpm run start:node |
Start the HTTP service with Node.js. |
pnpm run start:docker |
Run the published Docker image on port 3000. |
pnpm run cli |
Run the CLI package. |
pnpm run clean |
Remove workspace dependencies and build output. |
TAG=<version> pnpm run update:vendor |
Update the vendored Sub-Store submodule and package versions. |
pnpm run publish |
Publish the built core package. |
The Worker configuration lives in packages/app/wrangler.jsonc.
Build the Worker bundle:
pnpm run build:appDeploy with Wrangler:
pnpm --filter @sub-store-convert/app worker:deployBuild the Docker image locally:
pnpm run build:dockerRun the image:
docker run --rm --name sub-store-convert -p 3000:3000 ghcr.io/tbxark/sub-store-convert:latestOr use the workspace shortcut:
pnpm run start:dockerSub-Store is vendored as a git submodule at packages/core/src/vendors/Sub-Store.
To update it to a specific tag or version:
TAG=<version> pnpm run update:vendorsub-store-convert is licensed under the MIT License. See the LICENSE file for more information.