From 46c93bfdf2dcad4cd841366d4de874591d6092d6 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 28 Aug 2026 16:23:16 +0000 Subject: [PATCH] Rename the project to shadowtools Covers the whole repository: README title, CI badge and clone URLs, the package name and bin entry, the usage banner, the module name in the documented examples, and the CLI entry point, which moves from shadowboxKey.js to shadowtools.js with git mv so history follows it. Three mentions of Shadowbox deliberately stay: the README and package description both name 'Outline VPN (Shadowbox) server', and the npm keyword. Shadowbox is Outline's own server component, not this project, so renaming those would make the docs wrong. The npm name shadowtools is unregistered, so nothing needs a scope. Version bumped to 4.0.0 since the package identity changes; nothing has been published under the old name, so no upgrade path is owed. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01QJR2DDBimsijgYgZS3bUS8 --- .github/workflows/ci.yml | 4 ++-- README.md | 38 +++++++++++++++---------------- index.js | 2 +- package.json | 12 +++++----- shadowboxKey.js => shadowtools.js | 18 +++++++-------- test/api.test.js | 2 +- test/cli.test.js | 2 +- 7 files changed, 39 insertions(+), 39 deletions(-) rename shadowboxKey.js => shadowtools.js (96%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3cf35c3..e886b45 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: # node --check only looks at its first argument, so check each file in turn. - name: Check syntax run: | - for file in index.js shadowboxKey.js lib/*.js test/*.js; do + for file in index.js shadowtools.js lib/*.js test/*.js; do node --check "$file" done @@ -40,7 +40,7 @@ jobs: run: npm test - name: Check the CLI starts and prints help - run: node shadowboxKey.js --help + run: node shadowtools.js --help - name: Check the module exports load run: | diff --git a/README.md b/README.md index 52dc621..7c54197 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# ShadowboxKeys +# shadowtools -[![CI](https://github.com/rahmanow/ShadowboxKeys/actions/workflows/ci.yml/badge.svg)](https://github.com/rahmanow/ShadowboxKeys/actions/workflows/ci.yml) +[![CI](https://github.com/rahmanow/shadowtools/actions/workflows/ci.yml/badge.svg)](https://github.com/rahmanow/shadowtools/actions/workflows/ci.yml) Manage access keys on your [Outline VPN](https://getoutline.org/) (Shadowbox) server, from the terminal, a local web interface, or your own code. It lists, creates, renames and deletes keys, sets per-key data limits, reports how much data each key has used, and prints scannable QR codes so people can onboard with the Outline app instead of copy-pasting `ss://` strings. @@ -17,14 +17,14 @@ This project supersedes [outline-br](https://github.com/rahmanow/outline-br), wh ## Installation ```bash -git clone https://github.com/rahmanow/ShadowboxKeys.git -cd ShadowboxKeys +git clone https://github.com/rahmanow/shadowtools.git +cd shadowtools npm install ``` ## Configuration -Configure the tool either with environment variables (recommended — keeps secrets out of the code) or by editing the constants at the top of `shadowboxKey.js`. +Configure the tool either with environment variables (recommended — keeps secrets out of the code) or by editing the constants at the top of `shadowtools.js`. | Setting | Environment variable | Description | | --- | --- | --- | @@ -56,7 +56,7 @@ source .env ## Commands ``` -node shadowboxKey.js [options] +node shadowtools.js [options] ``` | Command | What it does | @@ -89,7 +89,7 @@ Sizes accept a unit suffix: `10GB`, `500MB`, `2TB`, or a plain byte count. List every key: ```console -$ node shadowboxKey.js list +$ node shadowtools.js list ID NAME LIMIT ACCESS URL -- ----- ----- ----------------------------------------------------- 0 Alice 10 GB ss://YWVzOnBhc3N3b3Jk@vpn.example.com:443/?outline=1 @@ -99,7 +99,7 @@ ID NAME LIMIT ACCESS URL Create a key with a 50 GB cap and show its QR code: ```console -$ node shadowboxKey.js add Carol --limit 50GB --qr +$ node shadowtools.js add Carol --limit 50GB --qr Created key "Carol" (id 2) Data limit: 50 GB ss://bmV3a2V5@vpn.example.com:502/?outline=1 @@ -113,7 +113,7 @@ Carol: See who is using how much: ```console -$ node shadowboxKey.js usage +$ node shadowtools.js usage ID NAME USED LIMIT OF LIMIT -- ----- ------ ----- -------- 0 Alice 3.0 GB 10 GB 30% @@ -125,14 +125,14 @@ Total transferred: 3.5 GB Cap a heavy user, then lift the cap later: ```bash -node shadowboxKey.js limit Alice 10GB -node shadowboxKey.js limit Alice none +node shadowtools.js limit Alice 10GB +node shadowtools.js limit Alice none ``` Export usage for a spreadsheet: ```bash -node shadowboxKey.js usage --csv > usage.csv +node shadowtools.js usage --csv > usage.csv ``` ## Web interface @@ -140,7 +140,7 @@ node shadowboxKey.js usage --csv > usage.csv If you would rather click than type: ```bash -node shadowboxKey.js ui +node shadowtools.js ui ``` It prints a URL to open: @@ -186,7 +186,7 @@ port. Everything the CLI does is available as a module. `require` the package and you get three helpers plus the underlying client: ```js -const { listKeys, getUsage, getKeys, OutlineClient } = require('shadowbox-keys'); +const { listKeys, getUsage, getKeys, OutlineClient } = require('shadowtools'); const API = 'https://1.2.3.4:16942/AbCdEf123'; const options = { domain: 'vpn.example.com', certSha256: 'E3823F9B...52F5A584' }; @@ -221,7 +221,7 @@ await client.clearServerDataLimit(); Failures caused by bad input or a bad response throw `UserError`, which is also exported, so you can tell them apart from bugs: ```js -const { UserError } = require('shadowbox-keys'); +const { UserError } = require('shadowtools'); try { await listKeys(API, { certSha256: expected }); @@ -241,7 +241,7 @@ const keys = require('outline-br'); keys('https://1.2.3.4:16942/AbCdEf123', '87.65.43.21'); // after -const { getKeys } = require('shadowbox-keys'); +const { getKeys } = require('shadowtools'); await getKeys('https://1.2.3.4:16942/AbCdEf123', '87.65.43.21'); ``` @@ -253,7 +253,7 @@ New code should prefer `listKeys()`, which returns structured data and leaves pr ``` index.js Programmatic API: listKeys, getUsage, getKeys -shadowboxKey.js CLI entry point: argument parsing and commands +shadowtools.js CLI entry point: argument parsing and commands lib/outline.js Outline Management API client lib/format.js Byte formatting, size parsing, table/CSV output lib/errors.js UserError, for messages shown without a stack trace @@ -281,7 +281,7 @@ Outline servers use a self-signed TLS certificate for the Management API, so the Setting `OUTLINE_CERT_SHA256` closes that gap. The tool then checks the certificate the server presents against the fingerprint you configured, and **aborts before sending anything** if they differ: ```console -$ OUTLINE_CERT_SHA256=aaaa...aaaa node shadowboxKey.js list +$ OUTLINE_CERT_SHA256=aaaa...aaaa node shadowtools.js list The server presented an unexpected TLS certificate, so the request was not sent. expected: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa received: e3823f9bb490d35487ee013ec7d23a3662f76b95eb01a40f4851905152f5a584 @@ -303,7 +303,7 @@ The HTTP calls use the built-in `node:https` module because the global `fetch()` ## Troubleshooting -- **`Please configure your Management API URL first`** — set `OUTLINE_API_URL`, or replace the placeholder in `shadowboxKey.js`. +- **`Please configure your Management API URL first`** — set `OUTLINE_API_URL`, or replace the placeholder in `shadowtools.js`. - **`Could not reach the Outline server`** — check that the Management API URL is correct and that its port (usually `16942`) is reachable from your machine. - **`Cannot find module 'qrcode-terminal'`** — run `npm install` in the project directory first. - **`The server presented an unexpected TLS certificate`** — either `OUTLINE_CERT_SHA256` is stale (recopy `certSha256` from Outline Manager after rebuilding or migrating the server), or something other than your Outline server answered. See [certificate pinning](#certificate-pinning). diff --git a/index.js b/index.js index 1d704b8..d34ba94 100644 --- a/index.js +++ b/index.js @@ -3,7 +3,7 @@ /** * Programmatic entry point. * - * The CLI in shadowboxKey.js is one consumer of this API; the exports below are + * The CLI in shadowtools.js is one consumer of this API; the exports below are * the same building blocks it uses, so anything the CLI can do is reachable from * code. getKeys() is kept signature-compatible with the outline-br module this * project absorbed, so existing callers keep working. diff --git a/package.json b/package.json index 8c8d41e..5ed3d0f 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,19 @@ { - "name": "shadowbox-keys", - "version": "3.0.0", + "name": "shadowtools", + "version": "4.0.0", "description": "Manage Outline VPN (Shadowbox) access keys from the command line or from code: list, create, rename, delete, set data limits, report usage and print QR codes", "license": "MIT", "main": "index.js", "bin": { - "shadowbox-keys": "shadowboxKey.js" + "shadowtools": "shadowtools.js" }, "files": [ "index.js", - "shadowboxKey.js", + "shadowtools.js", "lib/" ], "scripts": { - "start": "node shadowboxKey.js", + "start": "node shadowtools.js", "test": "node --test" }, "keywords": [ @@ -28,7 +28,7 @@ ], "repository": { "type": "git", - "url": "git+https://github.com/rahmanow/ShadowboxKeys.git" + "url": "git+https://github.com/rahmanow/shadowtools.git" }, "engines": { "node": ">=14" diff --git a/shadowboxKey.js b/shadowtools.js similarity index 96% rename from shadowboxKey.js rename to shadowtools.js index 17598a7..0abeb31 100755 --- a/shadowboxKey.js +++ b/shadowtools.js @@ -14,9 +14,9 @@ const { OutlineClient } = require('./lib/outline'); const { UserError } = require('./lib/errors'); const { formatBytes, parseBytes, rewriteAccessUrl, printTable, printCsv } = require('./lib/format'); -const USAGE = `ShadowboxKeys - manage access keys on your Outline VPN server +const USAGE = `shadowtools - manage access keys on your Outline VPN server -Usage: node shadowboxKey.js [options] +Usage: node shadowtools.js [options] Commands: list List every access key with its access URL @@ -49,11 +49,11 @@ Configuration (environment variables): any server presenting a different certificate. Examples: - node shadowboxKey.js list --qr - node shadowboxKey.js add Alice --limit 50GB - node shadowboxKey.js limit Alice 10GB - node shadowboxKey.js usage --csv - node shadowboxKey.js ui --port 9000 + node shadowtools.js list --qr + node shadowtools.js add Alice --limit 50GB + node shadowtools.js limit Alice 10GB + node shadowtools.js usage --csv + node shadowtools.js ui --port 9000 `; /** Splits argv into positional arguments and a flag map. */ @@ -285,7 +285,7 @@ async function main() { return; } - // Listing is the historical default, so bare `node shadowboxKey.js` still works. + // Listing is the historical default, so bare `node shadowtools.js` still works. const command = commands[commandName || 'list']; if (!command) { throw new UserError(`Unknown command "${commandName}". Run with --help to see what is available.`); @@ -294,7 +294,7 @@ async function main() { if (managementApiUrl.includes('xx.xx.xx.xxx')) { throw new UserError( 'Please configure your Management API URL first.\n' + - 'Set the OUTLINE_API_URL environment variable, or edit the managementApiUrl constant in shadowboxKey.js.' + 'Set the OUTLINE_API_URL environment variable, or edit the managementApiUrl constant in shadowtools.js.' ); } diff --git a/test/api.test.js b/test/api.test.js index 38f7706..9228ef6 100644 --- a/test/api.test.js +++ b/test/api.test.js @@ -23,7 +23,7 @@ const hasOpenssl = (() => { /** Creates a throwaway self-signed certificate, mimicking an Outline server's. */ function createCertificate() { - const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'shadowbox-keys-test-')); + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'shadowtools-test-')); const keyPath = path.join(dir, 'key.pem'); const certPath = path.join(dir, 'cert.pem'); diff --git a/test/cli.test.js b/test/cli.test.js index 231d035..52b393d 100644 --- a/test/cli.test.js +++ b/test/cli.test.js @@ -3,7 +3,7 @@ const test = require('node:test'); const assert = require('node:assert'); -const { parseArgs, findKey } = require('../shadowboxKey'); +const { parseArgs, findKey } = require('../shadowtools'); const { OutlineClient, normalizeFingerprint } = require('../lib/outline'); const { UserError } = require('../lib/errors');