@sharnix/agent 1.0.6 → 1.0.7

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.
Files changed (3) hide show
  1. package/README.md +43 -47
  2. package/index.js +25 -12
  3. package/package.json +6 -16
package/README.md CHANGED
@@ -2,47 +2,48 @@
2
2
 
3
3
  Instantly share your local app with anyone — no config, no port forwarding, no deployment.
4
4
 
5
- ## First-time setup (one command)
5
+ ## Usage
6
6
 
7
7
  ```bash
8
- npx @sharnix/agent setup
8
+ npx @sharnix/agent --port 3000
9
9
  ```
10
10
 
11
- This is all a new user needs to run. It will:
11
+ That's it. If this is your first time on this machine, the CLI will handle setup automatically — no separate setup step needed.
12
+
13
+ ## First-time setup (automatic)
12
14
 
13
- 1. Open your browser to relay.sharnix.com sign in if you haven't already
14
- 2. Click **"Authorize & create key"** — one click
15
- 3. The CLI captures your API key automatically
16
- 4. Writes the MCP config to Claude Desktop, Cursor, and Windsurf automatically (whichever are installed)
17
- 5. Prints your key and tells you to restart your editor
15
+ When no key is found, the CLI starts a one-time device flow:
18
16
 
19
- After that, your AI agent has full MCP access and you can start tunneling.
17
+ 1. Generates a short-lived auth URL and prints it in the terminal
18
+ 2. You (or your AI agent) open the URL in any browser — phone, laptop, doesn't matter
19
+ 3. Sign in and click **"Authorize"** — one click
20
+ 4. The CLI receives your key automatically via polling — nothing to copy or paste
21
+ 5. Key saved to `~/.sharnix/key.json` for all future runs
22
+ 6. Tunnel connects immediately
23
+
24
+ **Every run after that is silent** — the CLI reads the saved key and connects with no prompts.
20
25
 
21
26
  ## Tunneling your app
22
27
 
23
28
  ```bash
29
+ # Tunnel port 3000 (key read from ~/.sharnix/key.json or env)
24
30
  npx @sharnix/agent --port 3000
25
- ```
26
31
 
27
- The API key is read from `SHARNIX_API_KEY` in your environment, or saved automatically by `setup`.
28
-
29
- ```bash
30
- # Tunnel port 3000
32
+ # Pass key explicitly
31
33
  SHARNIX_API_KEY=shx_... npx @sharnix/agent --port 3000
32
34
 
33
- # Tunnel and immediately print a share link (no dashboard needed)
34
- SHARNIX_API_KEY=shx_... npx @sharnix/agent --port 3000 --share
35
-
36
35
  # With a label
37
- SHARNIX_API_KEY=shx_... npx @sharnix/agent --port 8080 --label "staging"
36
+ npx @sharnix/agent --port 8080 --label "staging"
38
37
  ```
39
38
 
40
- Save the key to your shell profile so you don't repeat it:
39
+ ## Key resolution order
41
40
 
42
- ```bash
43
- # ~/.bashrc or ~/.zshrc
44
- export SHARNIX_API_KEY=shx_...
45
- ```
41
+ The CLI checks for a key in this order:
42
+
43
+ 1. `SHARNIX_API_KEY` environment variable
44
+ 2. `SHARNIX_KEY` environment variable
45
+ 3. `~/.sharnix/key.json` (saved automatically after first setup)
46
+ 4. Device flow (auto-started if none of the above exist)
46
47
 
47
48
  ## What it does
48
49
 
@@ -57,35 +58,22 @@ export SHARNIX_API_KEY=shx_...
57
58
 
58
59
  | Flag | Default | Description |
59
60
  |------|---------|-------------|
60
- | `setup` | — | First-time setup: creates API key and writes MCP config automatically |
61
61
  | `--port`, `-p` | `3000` | Local port to forward |
62
62
  | `--label`, `-l` | — | Human-readable label for this tunnel |
63
- | `--name` | `local-dev` | Agent name used on first-time setup |
64
- | `--share` | — | Create a read-only share link on connect and print the URL |
63
+ | `--name` | `local-dev` | Agent name registered on first setup |
65
64
  | `--help`, `-h` | — | Show help |
66
65
 
67
66
  ## Environment variables
68
67
 
69
68
  | Variable | Description |
70
69
  |----------|-------------|
71
- | `SHARNIX_API_KEY` | Your API key — set automatically by `setup`, or from Settings |
70
+ | `SHARNIX_API_KEY` | API key — overrides saved key file |
71
+ | `SHARNIX_KEY` | Alias for `SHARNIX_API_KEY` |
72
72
  | `SHARNIX_URL` | Override relay URL (default: `https://relay.sharnix.com`) |
73
73
 
74
- ## What setup writes automatically
75
-
76
- `npx @sharnix/agent setup` detects which editors are installed and writes the MCP config to:
77
-
78
- | Editor | Config file |
79
- |--------|-------------|
80
- | Claude Desktop (macOS) | `~/Library/Application Support/Claude/claude_desktop_config.json` |
81
- | Claude Desktop (Windows) | `%APPDATA%\Claude\claude_desktop_config.json` |
82
- | Claude Desktop (Linux) | `~/.config/Claude/claude_desktop_config.json` |
83
- | Cursor | `~/.cursor/mcp.json` |
84
- | Windsurf | `~/.codeium/windsurf/mcp_config.json` |
85
-
86
- It merges into the existing config — it will never overwrite other MCP servers you have configured.
74
+ ## MCP config for AI editors
87
75
 
88
- The block it writes looks like this:
76
+ To give your AI agent (Claude Desktop, Cursor, Windsurf) MCP access to Sharnix, add this to your editor's config file and restart:
89
77
 
90
78
  ```json
91
79
  {
@@ -101,11 +89,18 @@ The block it writes looks like this:
101
89
  }
102
90
  ```
103
91
 
92
+ | Editor | Config file |
93
+ |--------|-------------|
94
+ | Claude Desktop (macOS) | `~/Library/Application Support/Claude/claude_desktop_config.json` |
95
+ | Claude Desktop (Windows) | `%APPDATA%\Claude\claude_desktop_config.json` |
96
+ | Claude Desktop (Linux) | `~/.config/Claude/claude_desktop_config.json` |
97
+ | Cursor | `~/.cursor/mcp.json` |
98
+ | Windsurf | `~/.codeium/windsurf/mcp_config.json` |
99
+
104
100
  ## Creating share links
105
101
 
106
102
  Once the agent is running, create share links from:
107
103
 
108
- - **Terminal** — `npx @sharnix/agent --port 3000 --share` prints a URL immediately
109
104
  - **AI agent** — ask Claude/Cursor: *"share my app with the client"* via [`@sharnix/mcp-server`](https://www.npmjs.com/package/@sharnix/mcp-server)
110
105
  - **Dashboard** — [relay.sharnix.com/app](https://relay.sharnix.com/app)
111
106
 
@@ -113,11 +108,12 @@ Share links support permissions (`read-only`, `full`), expiry dates, email restr
113
108
 
114
109
  ## How it works
115
110
 
116
- 1. `setup` creates an API key via browser auth and writes MCP config to your editors
117
- 2. On first tunnel run, agent credentials (`agentId` + `secret`) are auto-provisioned via the API and saved to `~/.sharnix/agent.json`
118
- 3. A stable tunnel ID is generated per working directory and saved to `~/.sharnix/tunnel-<hash>.json`
119
- 4. The agent opens a WebSocket to the relay and registers the tunnel
120
- 5. When a visitor opens a share link, the relay forwards their HTTP request over the WebSocket to your local app and streams the response back
111
+ 1. On first run with no key, the CLI starts a device flow: prints a one-time auth URL and polls for completion
112
+ 2. You open the URL in any browser, sign in, click Authorize key is saved to `~/.sharnix/key.json` automatically
113
+ 3. Agent credentials (`agentId` + `secret`) are provisioned via the API and saved to `~/.sharnix/agent.json`
114
+ 4. A stable tunnel ID is generated per working directory and saved to `~/.sharnix/tunnel-<hash>.json`
115
+ 5. The agent opens a WebSocket to the relay and registers the tunnel
116
+ 6. When a visitor opens a share link, the relay forwards their HTTP request over the WebSocket to your local app and streams the response back
121
117
 
122
118
  ## License
123
119
 
package/index.js CHANGED
@@ -12,6 +12,10 @@ const RELAY_BASE = (process.env.SHARNIX_URL || 'https://relay.sharnix.com').repl
12
12
  const WS_BASE = RELAY_BASE.replace(/^http/, 'ws');
13
13
  const API_KEY = process.env.SHARNIX_API_KEY || '';
14
14
 
15
+ // ── Config persistence (declared early so dispatch below can rely on it) ──────
16
+ const CONFIG_DIR = path.join(os.homedir(), '.sharnix');
17
+ if (!fs.existsSync(CONFIG_DIR)) fs.mkdirSync(CONFIG_DIR, { recursive: true });
18
+
15
19
  // ── CLI args ──────────────────────────────────────────────────────────────────
16
20
  const args = process.argv.slice(2);
17
21
  const get = (flag) => {
@@ -30,7 +34,8 @@ if (has('--help') || has('-h')) {
30
34
  sharnix — tunnel your local app through Sharnix
31
35
 
32
36
  Usage:
33
- npx @sharnix/agent setup First-time setup (no API key needed)
37
+ npx @sharnix/agent setup First-time setup on your local machine
38
+ npx @sharnix/agent setup --print-url Print auth URL and exit (for remote/agent use)
34
39
  npx @sharnix/agent --port <port> Tunnel a local port
35
40
  SHARNIX_API_KEY=shx_... npx @sharnix/agent --port 3000
36
41
 
@@ -50,11 +55,13 @@ if (has('--help') || has('-h')) {
50
55
 
51
56
  // ── Setup command (device-flow bootstrap, no API key required) ────────────────
52
57
  if (args[0] === 'setup') {
53
- runSetup().catch((err) => { console.error(`\n Error: ${err.message}\n`); process.exit(1); });
58
+ runSetup(has('--print-url')).catch((err) => { console.error(`\n Error: ${err.message}\n`); process.exit(1); });
54
59
  } else {
55
60
  if (!API_KEY) {
56
- console.error('\n Error: SHARNIX_API_KEY is not set.');
57
- console.error(' Run: npx @sharnix/agent setup\n');
61
+ console.error('\n Error: SHARNIX_API_KEY is not set.\n');
62
+ console.error(' On your local machine: npx @sharnix/agent setup');
63
+ console.error(' On a remote machine: SHARNIX_API_KEY=shx_... npx @sharnix/agent --port 3000');
64
+ console.error('\n Get your key from relay.sharnix.com/app/settings → API Keys\n');
58
65
  process.exit(1);
59
66
  }
60
67
  if (isNaN(port) || port < 1 || port > 65535) {
@@ -65,10 +72,7 @@ if (args[0] === 'setup') {
65
72
  }
66
73
 
67
74
 
68
- // ── Config persistence ────────────────────────────────────────────────────────
69
- const CONFIG_DIR = path.join(os.homedir(), '.sharnix');
70
- if (!fs.existsSync(CONFIG_DIR)) fs.mkdirSync(CONFIG_DIR, { recursive: true });
71
-
75
+ // ── Config persistence helpers ────────────────────────────────────────────────
72
76
  function loadJson(file) {
73
77
  try { return JSON.parse(fs.readFileSync(file, 'utf8')); } catch { return null; }
74
78
  }
@@ -271,8 +275,8 @@ function main() {
271
275
  }
272
276
 
273
277
  // ── Setup: device-flow bootstrap ─────────────────────────────────────────────
274
- async function runSetup() {
275
- const { execSync, spawn } = require('child_process');
278
+ async function runSetup(printUrlOnly = false) {
279
+ const { spawn } = require('child_process');
276
280
 
277
281
  console.log('\n Sharnix Setup\n');
278
282
 
@@ -283,16 +287,25 @@ async function runSetup() {
283
287
  const { code, authUrl } = await r.json();
284
288
  process.stdout.write(' done\n\n');
285
289
 
290
+ if (printUrlOnly) {
291
+ // Non-blocking mode for agents running on remote machines
292
+ console.log(' Authorization URL (open this in your browser):\n');
293
+ console.log(` ${authUrl}\n`);
294
+ console.log(' After authorizing, run the tunnel with:');
295
+ console.log(` SHARNIX_API_KEY=<your-key> npx @sharnix/agent --port 3000\n`);
296
+ console.log(' Your key will be shown on the authorization page after you click "Authorize".\n');
297
+ process.exit(0);
298
+ }
299
+
286
300
  console.log(' Opening your browser to authorize…');
287
301
  console.log(` URL: ${authUrl}\n`);
288
302
 
289
303
  // Open browser cross-platform
290
304
  try {
291
- const cmd = process.platform === 'win32' ? 'start' :
292
- process.platform === 'darwin' ? 'open' : 'xdg-open';
293
305
  if (process.platform === 'win32') {
294
306
  spawn('cmd', ['/c', 'start', '', authUrl], { detached: true, stdio: 'ignore' });
295
307
  } else {
308
+ const cmd = process.platform === 'darwin' ? 'open' : 'xdg-open';
296
309
  spawn(cmd, [authUrl], { detached: true, stdio: 'ignore' });
297
310
  }
298
311
  } catch {}
package/package.json CHANGED
@@ -1,27 +1,17 @@
1
1
  {
2
2
  "name": "@sharnix/agent",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "Tunnel your local app through Sharnix — share previews with one command",
5
- "keywords": [
6
- "tunnel",
7
- "preview",
8
- "sharing",
9
- "localhost",
10
- "sharnix"
11
- ],
5
+ "keywords": ["tunnel", "preview", "sharing", "localhost", "sharnix"],
12
6
  "homepage": "https://relay.sharnix.com",
13
7
  "license": "MIT",
14
- "engines": {
15
- "node": ">=18"
16
- },
8
+ "engines": { "node": ">=18" },
17
9
  "main": "./index.js",
18
10
  "bin": {
19
- "sharnix-agent": "./index.js",
20
- "sharnix": "./index.js"
11
+ "sharnix-agent": "index.js",
12
+ "sharnix": "index.js"
21
13
  },
22
- "files": [
23
- "index.js"
24
- ],
14
+ "files": ["index.js"],
25
15
  "dependencies": {
26
16
  "ws": "^8.18.0"
27
17
  }