bitgit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 b0ase
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,126 @@
1
+ # bitgit
2
+
3
+ **`git push` for Bitcoin.** Inscribe content, register domains, and manage tokens on BSV.
4
+
5
+ ```
6
+ npm install -g bitgit
7
+ ```
8
+
9
+ ## Commands
10
+
11
+ ```bash
12
+ bit init # scaffold .bit.yaml for your project
13
+ bit push # git push + inscribe changed content on BSV
14
+ bit register <domain> # inscribe a domain on DNS-DEX
15
+ bit status # show wallet, domain, token & version chain
16
+ ```
17
+
18
+ ## Quick Start
19
+
20
+ ```bash
21
+ # 1. Set up your project
22
+ cd your-project
23
+ bit init
24
+
25
+ # 2. Configure your BSV key
26
+ export BOASE_TREASURY_PRIVATE_KEY="your-wif-key"
27
+
28
+ # 3. Push content to Bitcoin
29
+ bit push
30
+ ```
31
+
32
+ `bit push` does two things:
33
+ 1. `git push` to your remote (if there are commits to push)
34
+ 2. Inscribes changed content on BSV (OP_RETURN with Bitcoin Schema)
35
+
36
+ Every inscription is chained — each transaction's change output feeds the next input, so you can inscribe dozens of files in one session without waiting for confirmations.
37
+
38
+ ## .bit.yaml
39
+
40
+ `bit init` creates a `.bit.yaml` in your project root:
41
+
42
+ ```yaml
43
+ project:
44
+ name: my-project
45
+ domain: my-project.com
46
+ token: MYTOKEN
47
+
48
+ wallet:
49
+ key_env: BOASE_TREASURY_PRIVATE_KEY
50
+
51
+ content:
52
+ type: blog # blog | repo | domain | custom
53
+ source: content/blog/ # directory to watch
54
+ format: bitcoin_schema # bitcoin_schema | op_return
55
+ protocol: my-project-blog
56
+
57
+ db:
58
+ supabase_url_env: NEXT_PUBLIC_SUPABASE_URL
59
+ supabase_key_env: SUPABASE_SERVICE_ROLE_KEY
60
+ version_table: blog_post_versions
61
+
62
+ dns_dex:
63
+ token_symbol: $my-project.com
64
+ ```
65
+
66
+ ## Inscription Formats
67
+
68
+ ### Bitcoin Schema (default)
69
+
70
+ Uses the B + MAP + AIP Bitcom protocols:
71
+ - **B** — content storage (full markdown/JSON)
72
+ - **MAP** — queryable metadata (indexed by GorillaPool)
73
+ - **AIP** — cryptographic authorship proof (ECDSA signature)
74
+
75
+ ### Simple OP_RETURN
76
+
77
+ `OP_FALSE OP_RETURN <protocol> <content-type> <payload>`
78
+
79
+ ## DNS-DEX Domain Registration
80
+
81
+ ```bash
82
+ bit register kwegwong.com
83
+ bit register kwegwong.com --category=culture --supply=1000000000
84
+ ```
85
+
86
+ Inscribes a `dnsdex-domain` token on BSV and prints the DNS TXT records to add for verification.
87
+
88
+ ## Broadcast Fallback Chain
89
+
90
+ Transactions are broadcast with automatic fallback:
91
+ 1. WhatsOnChain API
92
+ 2. GorillaPool ARC
93
+ 3. TAAL ARC
94
+
95
+ ## Dry Run
96
+
97
+ All commands support `--dry-run` to preview without broadcasting:
98
+
99
+ ```bash
100
+ bit push --dry-run
101
+ bit register example.com --dry-run
102
+ ```
103
+
104
+ ## Environment Variables
105
+
106
+ | Variable | Required | Description |
107
+ |----------|----------|-------------|
108
+ | `BOASE_TREASURY_PRIVATE_KEY` | Yes | BSV private key (WIF format) |
109
+ | `NEXT_PUBLIC_SUPABASE_URL` | Optional | Supabase URL for version chain DB |
110
+ | `SUPABASE_SERVICE_ROLE_KEY` | Optional | Supabase service role key |
111
+
112
+ ## Lineage
113
+
114
+ `bitgit` is the evolution of [`bgit`](https://www.npmjs.com/package/bgit-cli) (v2, 2026). Same DNA — commit/push to Bitcoin — but instead of wrapping git with a payment gate, `bit` adds Bitcoin alongside git.
115
+
116
+ ## Part of the PATH Protocol
117
+
118
+ - [$401](https://path401.com) — Identity
119
+ - [$402](https://path402.com) — Payment
120
+ - [$403](https://path403.com) — Conditions
121
+ - [DNS-DEX](https://dns-dex.com) — Domain tokenization
122
+ - [b0ase.com](https://b0ase.com) — Venture studio
123
+
124
+ ## License
125
+
126
+ MIT
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "bitgit",
3
+ "version": "0.1.0",
4
+ "description": "git push for Bitcoin — inscribe content, register domains, manage tokens on BSV",
5
+ "type": "module",
6
+ "bin": {
7
+ "bit": "./src/cli.ts"
8
+ },
9
+ "scripts": {
10
+ "dev": "tsx src/cli.ts",
11
+ "typecheck": "tsc --noEmit"
12
+ },
13
+ "keywords": [
14
+ "bitcoin",
15
+ "bsv",
16
+ "bitcoinsv",
17
+ "git",
18
+ "blockchain",
19
+ "inscription",
20
+ "op-return",
21
+ "cli",
22
+ "dns-dex",
23
+ "path402"
24
+ ],
25
+ "author": "b0ase <richard@b0ase.com> (https://b0ase.com)",
26
+ "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/b0ase/bitgit.git"
30
+ },
31
+ "homepage": "https://github.com/b0ase/bitgit#readme",
32
+ "bugs": {
33
+ "url": "https://github.com/b0ase/bitgit/issues"
34
+ },
35
+ "dependencies": {
36
+ "@bsv/sdk": "^1.1.23",
37
+ "@supabase/supabase-js": "^2.49.1",
38
+ "dotenv": "^16.4.7",
39
+ "yaml": "^2.7.0"
40
+ },
41
+ "devDependencies": {
42
+ "@types/node": "^22.12.0",
43
+ "tsx": "^4.19.2",
44
+ "typescript": "^5.7.3"
45
+ },
46
+ "engines": {
47
+ "node": ">=20"
48
+ },
49
+ "files": [
50
+ "src/",
51
+ "README.md",
52
+ "LICENSE"
53
+ ]
54
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Transaction broadcast with multi-provider fallback
3
+ *
4
+ * Chain: WhatsOnChain → GorillaPool ARC → TAAL ARC
5
+ * Extracted from 8+ identical copies across b0ase.com.
6
+ */
7
+
8
+ const WHATSONCHAIN_API = 'https://api.whatsonchain.com/v1/bsv/main';
9
+ const GORILLAPOOL_ARC = 'https://arc.gorillapool.io/v1/tx';
10
+ const TAAL_ARC = 'https://arc.taal.com/v1/tx';
11
+
12
+ /**
13
+ * Broadcast a signed transaction to the BSV network.
14
+ * Tries WoC first, then GorillaPool ARC, then TAAL ARC.
15
+ * Always trims the returned TXID.
16
+ */
17
+ export async function broadcast(rawTx: string): Promise<string> {
18
+ // 1. WhatsOnChain
19
+ const wocRes = await fetch(`${WHATSONCHAIN_API}/tx/raw`, {
20
+ method: 'POST',
21
+ headers: { 'Content-Type': 'application/json' },
22
+ body: JSON.stringify({ txhex: rawTx }),
23
+ });
24
+ if (wocRes.ok) {
25
+ return (await wocRes.text()).replace(/"/g, '').trim();
26
+ }
27
+ const wocErr = await wocRes.text();
28
+
29
+ // 2. GorillaPool ARC (binary)
30
+ const gpRes = await fetch(GORILLAPOOL_ARC, {
31
+ method: 'POST',
32
+ headers: { 'Content-Type': 'application/octet-stream' },
33
+ body: Buffer.from(rawTx, 'hex'),
34
+ });
35
+ if (gpRes.ok) {
36
+ const data = await gpRes.json();
37
+ return (data.txid || '').trim();
38
+ }
39
+ const gpErr = await gpRes.text();
40
+
41
+ // 3. TAAL ARC (binary)
42
+ const taalRes = await fetch(TAAL_ARC, {
43
+ method: 'POST',
44
+ headers: { 'Content-Type': 'application/octet-stream' },
45
+ body: Buffer.from(rawTx, 'hex'),
46
+ });
47
+ if (taalRes.ok) {
48
+ const data = await taalRes.json();
49
+ return (data.txid || '').trim();
50
+ }
51
+ const taalErr = await taalRes.text();
52
+
53
+ throw new Error(
54
+ `Broadcast failed on all providers:\n WoC: ${wocErr}\n GorillaPool: ${gpErr}\n TAAL: ${taalErr}`,
55
+ );
56
+ }
@@ -0,0 +1,103 @@
1
+ /**
2
+ * OP_RETURN script builders
3
+ *
4
+ * Two formats:
5
+ * 1. Simple: OP_FALSE OP_RETURN <protocol> <content-type> <payload>
6
+ * 2. Bitcoin Schema: B + MAP + AIP (Bitcom protocols)
7
+ *
8
+ * Extracted from lib/blog-inscription.ts.
9
+ */
10
+
11
+ import { PrivateKey, Script } from '@bsv/sdk';
12
+
13
+ // Bitcom protocol addresses
14
+ const B_PROTOCOL = '19HxigV4QyBv3tHpQVcUEQyq1pzZVdoAut';
15
+ const MAP_PROTOCOL = '1PuQa7K62MiKCtssSLKy1kh56WWU7MtUR5';
16
+ const AIP_PROTOCOL = '15PciHG22SNLQJXMoSUaWVi7WSqc7hCfva';
17
+
18
+ /**
19
+ * Simple OP_RETURN: protocol tag + content-type + payload
20
+ */
21
+ export function buildOpReturn(
22
+ protocol: string,
23
+ contentType: string,
24
+ payload: string,
25
+ ): Script {
26
+ const script = new Script();
27
+ script.writeOpCode(0); // OP_FALSE
28
+ script.writeOpCode(106); // OP_RETURN
29
+ script.writeBin(Buffer.from(protocol, 'utf8'));
30
+ script.writeBin(Buffer.from(contentType, 'utf8'));
31
+ script.writeBin(Buffer.from(payload, 'utf8'));
32
+ return script;
33
+ }
34
+
35
+ /**
36
+ * Bitcoin Schema OP_RETURN: B (content) + MAP (metadata) + AIP (signature)
37
+ *
38
+ * @param content - raw content (markdown, JSON, etc.)
39
+ * @param contentType - MIME type (e.g. 'text/markdown', 'application/json')
40
+ * @param mapData - key-value pairs for MAP protocol indexing
41
+ * @param signingKey - optional PrivateKey for AIP authorship proof
42
+ */
43
+ export function buildBitcoinSchema(
44
+ content: string,
45
+ contentType: string,
46
+ mapData: Record<string, string>,
47
+ signingKey?: PrivateKey,
48
+ ): Script {
49
+ const script = new Script();
50
+ const contentBytes = Buffer.from(content, 'utf8');
51
+
52
+ script.writeOpCode(0); // OP_FALSE
53
+ script.writeOpCode(106); // OP_RETURN
54
+
55
+ // --- B Protocol: content ---
56
+ script.writeBin(Buffer.from(B_PROTOCOL, 'utf8'));
57
+ script.writeBin(contentBytes);
58
+ script.writeBin(Buffer.from(contentType, 'utf8'));
59
+ script.writeBin(Buffer.from('utf-8', 'utf8'));
60
+
61
+ // --- Pipe separator ---
62
+ script.writeBin(Buffer.from('|', 'utf8'));
63
+
64
+ // --- MAP Protocol: metadata ---
65
+ script.writeBin(Buffer.from(MAP_PROTOCOL, 'utf8'));
66
+ script.writeBin(Buffer.from('SET', 'utf8'));
67
+
68
+ // Collect buffers for AIP signing payload
69
+ const sigParts: Buffer[] = [
70
+ Buffer.from(B_PROTOCOL),
71
+ contentBytes,
72
+ Buffer.from(contentType),
73
+ Buffer.from('utf-8'),
74
+ Buffer.from('|'),
75
+ Buffer.from(MAP_PROTOCOL),
76
+ Buffer.from('SET'),
77
+ ];
78
+
79
+ for (const [key, value] of Object.entries(mapData)) {
80
+ script.writeBin(Buffer.from(key, 'utf8'));
81
+ script.writeBin(Buffer.from(value, 'utf8'));
82
+ sigParts.push(Buffer.from(key), Buffer.from(value));
83
+ }
84
+
85
+ // --- Pipe separator ---
86
+ script.writeBin(Buffer.from('|', 'utf8'));
87
+ sigParts.push(Buffer.from('|'));
88
+
89
+ // --- AIP Protocol: authorship proof ---
90
+ if (signingKey) {
91
+ const address = signingKey.toPublicKey().toAddress();
92
+ const signingPayload = Buffer.concat(sigParts);
93
+ const signature = signingKey.sign(Array.from(signingPayload));
94
+ const sigBase64 = signature.toDER('base64') as string;
95
+
96
+ script.writeBin(Buffer.from(AIP_PROTOCOL, 'utf8'));
97
+ script.writeBin(Buffer.from('BITCOIN_ECDSA', 'utf8'));
98
+ script.writeBin(Buffer.from(address, 'utf8'));
99
+ script.writeBin(Buffer.from(sigBase64, 'utf8'));
100
+ }
101
+
102
+ return script;
103
+ }
package/src/bsv/tx.ts ADDED
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Transaction building for OP_RETURN inscriptions
3
+ *
4
+ * Handles the mock-source-tx pattern and the sourceTXID overwrite bug.
5
+ * Extracted from 12+ identical copies across b0ase.com.
6
+ */
7
+
8
+ import { PrivateKey, Transaction, P2PKH, Script } from '@bsv/sdk';
9
+ import type { UTXO } from './utxo.js';
10
+
11
+ export interface InscriptionTxResult {
12
+ tx: Transaction;
13
+ txid: string;
14
+ fee: number;
15
+ changeSats: number;
16
+ }
17
+
18
+ /**
19
+ * Build a signed transaction with an OP_RETURN data output.
20
+ *
21
+ * @param privateKey - signing key
22
+ * @param utxo - input UTXO
23
+ * @param opReturnScript - pre-built OP_RETURN script (from script.ts)
24
+ * @param feeRate - sats per byte (default 0.5)
25
+ * @param payloadSize - estimated payload size for fee calc (if 0, uses 500 byte estimate)
26
+ */
27
+ export async function buildInscriptionTx(opts: {
28
+ privateKey: PrivateKey;
29
+ utxo: UTXO;
30
+ opReturnScript: Script;
31
+ feeRate?: number;
32
+ payloadSize?: number;
33
+ }): Promise<InscriptionTxResult> {
34
+ const { privateKey, utxo, opReturnScript, feeRate = 0.5, payloadSize = 0 } = opts;
35
+ const address = privateKey.toPublicKey().toAddress();
36
+
37
+ const tx = new Transaction();
38
+
39
+ // Build mock source transaction for SIGHASH verification.
40
+ // We only need enough outputs to reach the UTXO's vout index.
41
+ const mockSourceTx = new Transaction();
42
+ for (let i = 0; i <= utxo.vout; i++) {
43
+ mockSourceTx.addOutput({
44
+ lockingScript: i === utxo.vout ? utxo.script : new Script(),
45
+ satoshis: i === utxo.vout ? utxo.satoshis : 1,
46
+ });
47
+ }
48
+
49
+ tx.addInput({
50
+ sourceTXID: utxo.txid,
51
+ sourceOutputIndex: utxo.vout,
52
+ unlockingScriptTemplate: new P2PKH().unlock(privateKey),
53
+ sourceTransaction: mockSourceTx,
54
+ });
55
+
56
+ // CRITICAL: addInput() overwrites sourceTXID when sourceTransaction is provided.
57
+ // Must re-set it after addInput().
58
+ tx.inputs[0].sourceTXID = utxo.txid;
59
+
60
+ // OP_RETURN output (0 satoshis)
61
+ tx.addOutput({
62
+ lockingScript: opReturnScript,
63
+ satoshis: 0,
64
+ });
65
+
66
+ // Fee calculation
67
+ const estimatedSize = (payloadSize || 500) + 200; // payload + tx overhead
68
+ const fee = Math.max(500, Math.ceil(estimatedSize * feeRate));
69
+ const changeSats = utxo.satoshis - fee;
70
+
71
+ if (changeSats < 0) {
72
+ throw new Error(
73
+ `Insufficient sats for fee. Need ${fee}, have ${utxo.satoshis}`,
74
+ );
75
+ }
76
+
77
+ // Change output
78
+ if (changeSats > 0) {
79
+ tx.addOutput({
80
+ lockingScript: new P2PKH().lock(address),
81
+ satoshis: changeSats,
82
+ });
83
+ }
84
+
85
+ await tx.sign();
86
+
87
+ const txid = tx.id('hex') as string;
88
+
89
+ return { tx, txid, fee, changeSats };
90
+ }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * UTXO fetching from WhatsOnChain
3
+ *
4
+ * Extracted from 10+ identical copies across b0ase.com scripts.
5
+ */
6
+
7
+ import { Script, P2PKH } from '@bsv/sdk';
8
+
9
+ const WHATSONCHAIN_API = 'https://api.whatsonchain.com/v1/bsv/main';
10
+ const FETCH_TIMEOUT_MS = 30_000;
11
+
12
+ export interface UTXO {
13
+ txid: string;
14
+ vout: number;
15
+ satoshis: number;
16
+ script: Script;
17
+ }
18
+
19
+ /** Raw shape returned by WhatsOnChain API */
20
+ interface WocUtxo {
21
+ tx_hash: string;
22
+ tx_pos: number;
23
+ value: number;
24
+ }
25
+
26
+ async function fetchWithTimeout(
27
+ url: string,
28
+ options: RequestInit = {},
29
+ timeoutMs = FETCH_TIMEOUT_MS,
30
+ ): Promise<Response> {
31
+ const controller = new AbortController();
32
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
33
+ try {
34
+ const response = await fetch(url, { ...options, signal: controller.signal });
35
+ clearTimeout(timeoutId);
36
+ return response;
37
+ } catch (error) {
38
+ clearTimeout(timeoutId);
39
+ if (error instanceof Error && error.name === 'AbortError') {
40
+ throw new Error(`Request timeout after ${timeoutMs}ms`);
41
+ }
42
+ throw error;
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Fetch all UTXOs for an address, sorted largest-first.
48
+ */
49
+ export async function fetchUtxos(address: string): Promise<UTXO[]> {
50
+ const url = `${WHATSONCHAIN_API}/address/${address}/unspent`;
51
+ const response = await fetchWithTimeout(url);
52
+ if (!response.ok) {
53
+ throw new Error(`Failed to fetch UTXOs: ${response.statusText}`);
54
+ }
55
+
56
+ const raw: WocUtxo[] = await response.json();
57
+ const lockScript = new P2PKH().lock(address);
58
+
59
+ return raw
60
+ .sort((a, b) => b.value - a.value)
61
+ .map((u) => ({
62
+ txid: u.tx_hash,
63
+ vout: u.tx_pos,
64
+ satoshis: u.value,
65
+ script: lockScript,
66
+ }));
67
+ }
68
+
69
+ /**
70
+ * Select a single UTXO with at least `minSats` satoshis.
71
+ * Optionally exclude specific txids (e.g. unconfirmed change).
72
+ */
73
+ export async function selectUtxo(
74
+ address: string,
75
+ minSats = 1000,
76
+ excludeTxids: string[] = [],
77
+ ): Promise<UTXO> {
78
+ const utxos = await fetchUtxos(address);
79
+ const eligible = utxos.filter(
80
+ (u) => u.satoshis >= minSats && !excludeTxids.includes(u.txid),
81
+ );
82
+
83
+ if (eligible.length === 0) {
84
+ throw new Error(
85
+ `No UTXO with >= ${minSats} sats. Found ${utxos.length} total UTXOs.`,
86
+ );
87
+ }
88
+
89
+ return eligible[0]; // largest first
90
+ }
package/src/cli.ts ADDED
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env npx tsx
2
+ /**
3
+ * bit — Bitcoin CLI for the PATH Protocol
4
+ *
5
+ * Usage:
6
+ * bit init Scaffold .bit.yaml for a new project
7
+ * bit push git push + inscribe changed content on BSV
8
+ * bit register <domain> Inscribe a domain on DNS-DEX
9
+ * bit status Show Bitcoin state for this project
10
+ */
11
+
12
+ import * as dotenv from 'dotenv';
13
+ import { resolve } from 'path';
14
+ import { existsSync } from 'fs';
15
+
16
+ // Load .env.local from cwd, then .env
17
+ const cwd = process.cwd();
18
+ for (const envFile of ['.env.local', '.env']) {
19
+ const p = resolve(cwd, envFile);
20
+ if (existsSync(p)) {
21
+ dotenv.config({ path: p });
22
+ break;
23
+ }
24
+ }
25
+
26
+ const args = process.argv.slice(2);
27
+ const command = args[0];
28
+
29
+ async function main() {
30
+ switch (command) {
31
+ case 'init': {
32
+ const { init } = await import('./commands/init.js');
33
+ await init();
34
+ break;
35
+ }
36
+ case 'push': {
37
+ const { push } = await import('./commands/push.js');
38
+ await push(args.slice(1));
39
+ break;
40
+ }
41
+ case 'register': {
42
+ const domain = args[1];
43
+ if (!domain) {
44
+ console.error('Usage: bit register <domain>');
45
+ process.exit(1);
46
+ }
47
+ const { register } = await import('./commands/register.js');
48
+ await register(domain, args.slice(2));
49
+ break;
50
+ }
51
+ case 'status': {
52
+ const { status } = await import('./commands/status.js');
53
+ await status();
54
+ break;
55
+ }
56
+ case '--help':
57
+ case '-h':
58
+ case undefined: {
59
+ console.log(`
60
+ bit — Bitcoin CLI for the PATH Protocol
61
+
62
+ Commands:
63
+ bit init Scaffold .bit.yaml for a new project
64
+ bit push git push + inscribe changed content on BSV
65
+ bit register <domain> Inscribe a domain on DNS-DEX
66
+ bit status Show Bitcoin state for this project
67
+
68
+ Options:
69
+ --help, -h Show this help
70
+ --version Show version
71
+
72
+ Examples:
73
+ bit init
74
+ bit push
75
+ bit push --dry-run
76
+ bit register kwegwong.com
77
+ bit status
78
+ `.trim());
79
+ break;
80
+ }
81
+ case '--version': {
82
+ const { readFileSync } = await import('fs');
83
+ const { resolve } = await import('path');
84
+ const { fileURLToPath } = await import('url');
85
+ const __dirname = resolve(fileURLToPath(import.meta.url), '..');
86
+ const pkg = JSON.parse(readFileSync(resolve(__dirname, '../package.json'), 'utf8'));
87
+ console.log(pkg.version);
88
+ break;
89
+ }
90
+ default: {
91
+ console.error(`Unknown command: ${command}`);
92
+ console.error('Run `bit --help` for usage.');
93
+ process.exit(1);
94
+ }
95
+ }
96
+ }
97
+
98
+ main().catch((err) => {
99
+ console.error('Fatal:', err.message || err);
100
+ process.exit(1);
101
+ });