@tummycrypt/remote-juggler 2.1.0-beta.2

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/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # @tummycrypt/remote-juggler
2
+
3
+ Multi-provider git identity management with MCP server support for AI agents.
4
+
5
+ ## Quick Start
6
+
7
+ ### As an MCP Server (for AI agents)
8
+
9
+ Add to your MCP client configuration (Claude Code, Cursor, VS Code):
10
+
11
+ ```json
12
+ {
13
+ "mcpServers": {
14
+ "remote-juggler": {
15
+ "command": "npx",
16
+ "args": ["-y", "@tummycrypt/remote-juggler", "--mode=mcp"]
17
+ }
18
+ }
19
+ }
20
+ ```
21
+
22
+ ### As a CLI Tool
23
+
24
+ ```bash
25
+ npx @tummycrypt/remote-juggler list
26
+ npx @tummycrypt/remote-juggler switch gitlab-personal
27
+ npx @tummycrypt/remote-juggler status
28
+ ```
29
+
30
+ ### Full Installation
31
+
32
+ For a permanent installation with shell completions and IDE integration:
33
+
34
+ ```bash
35
+ curl -fsSL https://raw.githubusercontent.com/Jesssullivan/RemoteJuggler/main/install.sh | bash
36
+ ```
37
+
38
+ ## What It Does
39
+
40
+ RemoteJuggler manages multiple git identities across providers (GitLab, GitHub, Bitbucket). It handles:
41
+
42
+ - SSH key selection per identity
43
+ - GPG signing configuration
44
+ - Git user.name/user.email switching
45
+ - Credential resolution (Keychain, env vars, SSH agent)
46
+ - Automatic identity detection from repository remotes
47
+
48
+ ## MCP Tools
49
+
50
+ When running as an MCP server, these tools are available to AI agents:
51
+
52
+ | Tool | Description |
53
+ |------|-------------|
54
+ | `juggler_list_identities` | List all configured identities |
55
+ | `juggler_detect_identity` | Auto-detect identity from repo remote URL |
56
+ | `juggler_switch` | Switch to a different identity |
57
+ | `juggler_status` | Get current identity and git config status |
58
+ | `juggler_validate` | Test SSH/API connectivity for an identity |
59
+ | `juggler_store_token` | Store API token in keychain |
60
+ | `juggler_sync_config` | Synchronize managed SSH/git config blocks |
61
+
62
+ ## Supported Platforms
63
+
64
+ - Linux x86_64
65
+ - Linux ARM64
66
+ - macOS x86_64 (Intel)
67
+ - macOS ARM64 (Apple Silicon)
68
+
69
+ ## Links
70
+
71
+ - [GitHub Repository](https://github.com/Jesssullivan/RemoteJuggler)
72
+ - [Full Documentation](https://github.com/Jesssullivan/RemoteJuggler/blob/main/README.md)
73
+ - [MCP Registry](https://modelcontextprotocol.io)
package/bin/cli.js ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * RemoteJuggler CLI wrapper
4
+ *
5
+ * Spawns the platform-native binary with all arguments and stdio inherited,
6
+ * forwarding the exit code. This enables the `npx @tummycrypt/remote-juggler`
7
+ * and `npx @tummycrypt/remote-juggler --mode=mcp` usage patterns.
8
+ */
9
+
10
+ const { spawn } = require("child_process");
11
+ const { join } = require("path");
12
+ const { existsSync } = require("fs");
13
+
14
+ const BINARY_PATH = join(__dirname, "remote-juggler-binary");
15
+
16
+ if (!existsSync(BINARY_PATH)) {
17
+ console.error("RemoteJuggler binary not found. Run: npm install @tummycrypt/remote-juggler");
18
+ console.error("Or install directly: curl -fsSL https://raw.githubusercontent.com/Jesssullivan/RemoteJuggler/main/install.sh | bash");
19
+ process.exit(1);
20
+ }
21
+
22
+ const child = spawn(BINARY_PATH, process.argv.slice(2), {
23
+ stdio: "inherit",
24
+ env: process.env,
25
+ });
26
+
27
+ child.on("error", (err) => {
28
+ console.error(`Failed to start RemoteJuggler: ${err.message}`);
29
+ process.exit(1);
30
+ });
31
+
32
+ child.on("exit", (code, signal) => {
33
+ if (signal) {
34
+ process.kill(process.pid, signal);
35
+ } else {
36
+ process.exit(code || 0);
37
+ }
38
+ });
package/bin/install.js ADDED
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * RemoteJuggler npm postinstall script
4
+ *
5
+ * Downloads the correct platform-specific binary from GitHub Releases
6
+ * and places it alongside this script for the CLI wrapper to invoke.
7
+ */
8
+
9
+ const { createWriteStream, chmodSync, existsSync } = require("fs");
10
+ const { join } = require("path");
11
+ const https = require("https");
12
+ const { execSync } = require("child_process");
13
+
14
+ const pkg = require("../package.json");
15
+ const VERSION = pkg.version;
16
+ const BINARY_PATH = join(__dirname, "remote-juggler-binary");
17
+
18
+ // Map Node.js platform/arch to GitHub Release asset names
19
+ const PLATFORM_MAP = {
20
+ "linux-x64": "remote-juggler-linux-amd64",
21
+ "linux-arm64": "remote-juggler-linux-arm64",
22
+ "darwin-x64": "remote-juggler-darwin-amd64",
23
+ "darwin-arm64": "remote-juggler-darwin-arm64",
24
+ };
25
+
26
+ function getPlatformKey() {
27
+ return `${process.platform}-${process.arch}`;
28
+ }
29
+
30
+ function getDownloadUrl() {
31
+ const key = getPlatformKey();
32
+ const asset = PLATFORM_MAP[key];
33
+ if (!asset) {
34
+ if (process.platform === "win32") {
35
+ console.error("RemoteJuggler does not have a native Windows build.");
36
+ console.error("Use WSL (Windows Subsystem for Linux) instead:");
37
+ console.error(" wsl --install && wsl npm install -g @tummycrypt/remote-juggler");
38
+ console.error("");
39
+ console.error("Or install in WSL directly:");
40
+ console.error(" wsl curl -fsSL https://raw.githubusercontent.com/Jesssullivan/RemoteJuggler/main/install.sh | bash");
41
+ } else {
42
+ console.error(
43
+ `Unsupported platform: ${key}. Supported: ${Object.keys(PLATFORM_MAP).join(", ")}`
44
+ );
45
+ }
46
+ process.exit(1);
47
+ }
48
+ return `https://github.com/Jesssullivan/RemoteJuggler/releases/download/v${VERSION}/${asset}`;
49
+ }
50
+
51
+ function download(url) {
52
+ return new Promise((resolve, reject) => {
53
+ const request = https.get(url, (response) => {
54
+ // Handle redirects (GitHub sends 302 to S3)
55
+ if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
56
+ return download(response.headers.location).then(resolve).catch(reject);
57
+ }
58
+
59
+ if (response.statusCode !== 200) {
60
+ reject(new Error(`Download failed: HTTP ${response.statusCode} from ${url}`));
61
+ return;
62
+ }
63
+
64
+ const file = createWriteStream(BINARY_PATH);
65
+ response.pipe(file);
66
+ file.on("finish", () => {
67
+ file.close();
68
+ chmodSync(BINARY_PATH, 0o755);
69
+ resolve();
70
+ });
71
+ file.on("error", (err) => {
72
+ reject(err);
73
+ });
74
+ });
75
+
76
+ request.on("error", reject);
77
+ request.setTimeout(60000, () => {
78
+ request.destroy();
79
+ reject(new Error("Download timeout (60s)"));
80
+ });
81
+ });
82
+ }
83
+
84
+ async function main() {
85
+ // Skip download if binary already exists (e.g., local development)
86
+ if (existsSync(BINARY_PATH)) {
87
+ console.log("RemoteJuggler binary already exists, skipping download.");
88
+ return;
89
+ }
90
+
91
+ const url = getDownloadUrl();
92
+ const key = getPlatformKey();
93
+ console.log(`Downloading RemoteJuggler v${VERSION} for ${key}...`);
94
+ console.log(` URL: ${url}`);
95
+
96
+ try {
97
+ await download(url);
98
+ console.log(`RemoteJuggler v${VERSION} installed successfully.`);
99
+
100
+ // Quick sanity check
101
+ try {
102
+ const output = execSync(`"${BINARY_PATH}" --help`, {
103
+ timeout: 5000,
104
+ encoding: "utf-8",
105
+ });
106
+ if (output.includes("remote-juggler") || output.includes("RemoteJuggler")) {
107
+ console.log(" Binary verified OK.");
108
+ }
109
+ } catch {
110
+ // Binary may not be fully compatible (e.g., missing libs) but install succeeded
111
+ console.log(" Binary downloaded (verification skipped).");
112
+ }
113
+ } catch (err) {
114
+ console.error(`Failed to download RemoteJuggler: ${err.message}`);
115
+ console.error("");
116
+ console.error("You can install manually:");
117
+ console.error(" curl -fsSL https://raw.githubusercontent.com/Jesssullivan/RemoteJuggler/main/install.sh | bash");
118
+ process.exit(1);
119
+ }
120
+ }
121
+
122
+ main();
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@tummycrypt/remote-juggler",
3
+ "version": "2.1.0-beta.2",
4
+ "description": "Multi-provider git identity management with MCP server support for AI agents",
5
+ "bin": {
6
+ "remote-juggler": "./bin/cli.js"
7
+ },
8
+ "scripts": {
9
+ "postinstall": "node bin/install.js"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/Jesssullivan/RemoteJuggler.git"
14
+ },
15
+ "homepage": "https://github.com/Jesssullivan/RemoteJuggler",
16
+ "keywords": [
17
+ "mcp",
18
+ "git",
19
+ "identity",
20
+ "gitlab",
21
+ "github",
22
+ "ssh",
23
+ "gpg",
24
+ "model-context-protocol"
25
+ ],
26
+ "license": "Zlib",
27
+ "os": [
28
+ "linux",
29
+ "darwin"
30
+ ],
31
+ "cpu": [
32
+ "x64",
33
+ "arm64"
34
+ ],
35
+ "engines": {
36
+ "node": ">=18"
37
+ }
38
+ }