culater 1.0.1 → 1.0.4
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 +8 -3
- package/bin/culater.js +40 -16
- package/lib/server.js +10 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -10,8 +10,6 @@ Access Claude Code from your phone via a secure tunnel.
|
|
|
10
10
|
npx culater mypassword
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
You'll be prompted for an optional [ntfy.sh](https://ntfy.sh) topic to receive push notifications.
|
|
14
|
-
|
|
15
13
|
## Requirements
|
|
16
14
|
|
|
17
15
|
- Node.js 18+
|
|
@@ -28,6 +26,7 @@ sudo apt install cloudflared
|
|
|
28
26
|
## Options
|
|
29
27
|
|
|
30
28
|
```
|
|
29
|
+
-n, --ntfy <topic> ntfy.sh topic for push notifications (saved for next time)
|
|
31
30
|
-d, --dir <path> Working directory (default: current)
|
|
32
31
|
-h, --help Show help
|
|
33
32
|
```
|
|
@@ -38,6 +37,12 @@ sudo apt install cloudflared
|
|
|
38
37
|
# Start with password
|
|
39
38
|
npx culater mysecret
|
|
40
39
|
|
|
40
|
+
# With push notifications (saved to /tmp/culater.json)
|
|
41
|
+
npx culater mysecret -n my-ntfy-topic
|
|
42
|
+
|
|
43
|
+
# Subsequent runs use saved ntfy topic automatically
|
|
44
|
+
npx culater mysecret
|
|
45
|
+
|
|
41
46
|
# Specific directory
|
|
42
47
|
npx culater mysecret -d ~/projects/myapp
|
|
43
48
|
```
|
|
@@ -52,7 +57,7 @@ npx culater mysecret -d ~/projects/myapp
|
|
|
52
57
|
- Streaming indicator
|
|
53
58
|
- Password protection
|
|
54
59
|
- Secure cloudflare tunnel
|
|
55
|
-
-
|
|
60
|
+
- Push notifications via ntfy.sh (remembers your topic)
|
|
56
61
|
|
|
57
62
|
## License
|
|
58
63
|
|
package/bin/culater.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const { execSync } = require('child_process');
|
|
4
|
-
const
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
|
|
6
|
+
const CONFIG_FILE = '/tmp/culater.json';
|
|
5
7
|
|
|
6
8
|
// Check for cloudflared
|
|
7
9
|
try {
|
|
@@ -15,13 +17,32 @@ try {
|
|
|
15
17
|
process.exit(1);
|
|
16
18
|
}
|
|
17
19
|
|
|
20
|
+
// Load saved config
|
|
21
|
+
function loadConfig() {
|
|
22
|
+
try {
|
|
23
|
+
return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
|
|
24
|
+
} catch {
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Save config
|
|
30
|
+
function saveConfig(config) {
|
|
31
|
+
try {
|
|
32
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
33
|
+
} catch {}
|
|
34
|
+
}
|
|
35
|
+
|
|
18
36
|
// Parse args
|
|
19
37
|
const args = process.argv.slice(2);
|
|
20
38
|
let password = null;
|
|
39
|
+
let ntfyTopic = null;
|
|
21
40
|
let workDir = process.cwd();
|
|
22
41
|
|
|
23
42
|
for (let i = 0; i < args.length; i++) {
|
|
24
|
-
if (args[i] === '-
|
|
43
|
+
if (args[i] === '-n' || args[i] === '--ntfy') {
|
|
44
|
+
ntfyTopic = args[++i];
|
|
45
|
+
} else if (args[i] === '-d' || args[i] === '--dir') {
|
|
25
46
|
workDir = args[++i];
|
|
26
47
|
} else if (args[i] === '-h' || args[i] === '--help') {
|
|
27
48
|
console.log(`
|
|
@@ -31,11 +52,13 @@ for (let i = 0; i < args.length; i++) {
|
|
|
31
52
|
npx culater <password> [options]
|
|
32
53
|
|
|
33
54
|
\x1b[1mOPTIONS:\x1b[0m
|
|
55
|
+
-n, --ntfy <topic> ntfy.sh topic for push notifications (saved for next time)
|
|
34
56
|
-d, --dir <path> Working directory (default: current)
|
|
35
57
|
-h, --help Show this help
|
|
36
58
|
|
|
37
59
|
\x1b[1mEXAMPLES:\x1b[0m
|
|
38
60
|
npx culater mysecret
|
|
61
|
+
npx culater mysecret -n my-ntfy-topic
|
|
39
62
|
npx culater mysecret -d ~/projects/myapp
|
|
40
63
|
`);
|
|
41
64
|
process.exit(0);
|
|
@@ -50,19 +73,20 @@ if (!password) {
|
|
|
50
73
|
process.exit(1);
|
|
51
74
|
}
|
|
52
75
|
|
|
53
|
-
//
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
76
|
+
// Load config and use saved ntfy if not provided
|
|
77
|
+
const config = loadConfig();
|
|
78
|
+
if (ntfyTopic) {
|
|
79
|
+
// Save new ntfy topic
|
|
80
|
+
config.ntfyTopic = ntfyTopic;
|
|
81
|
+
saveConfig(config);
|
|
82
|
+
} else if (config.ntfyTopic) {
|
|
83
|
+
// Use saved ntfy topic
|
|
84
|
+
ntfyTopic = config.ntfyTopic;
|
|
85
|
+
}
|
|
61
86
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
87
|
+
// Set env and run server
|
|
88
|
+
process.env.REMOTE_PASSWORD = password;
|
|
89
|
+
process.env.NTFY_TOPIC = ntfyTopic || '';
|
|
90
|
+
process.env.WORK_DIR = workDir;
|
|
66
91
|
|
|
67
|
-
|
|
68
|
-
});
|
|
92
|
+
require('../lib/server.js');
|
package/lib/server.js
CHANGED
|
@@ -5,6 +5,16 @@ const pty = require('node-pty');
|
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const crypto = require('crypto');
|
|
7
7
|
const os = require('os');
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
|
|
10
|
+
// Fix node-pty spawn-helper permissions (needed for npx installs)
|
|
11
|
+
try {
|
|
12
|
+
const ptyRoot = path.dirname(require.resolve('node-pty/package.json'));
|
|
13
|
+
const spawnHelper = path.join(ptyRoot, 'prebuilds', `${os.platform()}-${os.arch()}`, 'spawn-helper');
|
|
14
|
+
if (fs.existsSync(spawnHelper)) {
|
|
15
|
+
fs.chmodSync(spawnHelper, 0o755);
|
|
16
|
+
}
|
|
17
|
+
} catch {}
|
|
8
18
|
|
|
9
19
|
const PASSWORD = process.env.REMOTE_PASSWORD || 'changeme';
|
|
10
20
|
const PORT = process.env.PORT || 3456;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "culater",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Remote terminal for Claude Code - c(See) you later!",
|
|
5
5
|
"bin": {
|
|
6
6
|
"culater": "./bin/culater.js"
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
],
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"node-pty": "^1.
|
|
23
|
+
"node-pty": "^1.1.0",
|
|
24
24
|
"ws": "^8.16.0"
|
|
25
25
|
},
|
|
26
26
|
"engines": {
|