xkat-cli 1.1.0 → 1.1.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 +43 -18
- package/bin/xkat-cli.js +5 -4
- package/package.json +1 -2
- package/scripts/install.js +17 -15
package/README.md
CHANGED
|
@@ -1,40 +1,65 @@
|
|
|
1
1
|
# xKat (Local Terminal Bridge)
|
|
2
2
|
|
|
3
|
-
xKat Agent
|
|
3
|
+
xKat Agent is a bridge tool that securely connects a browser-based coding
|
|
4
|
+
learning platform to your local environment.
|
|
4
5
|
|
|
5
|
-
##
|
|
6
|
+
## Features
|
|
6
7
|
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
- **Zero-install local shell bridge**: Connects the web IDE terminal in your
|
|
9
|
+
browser directly to your local shell. A single `npx xkat up` spawns a native
|
|
10
|
+
shell (PTY) with your current user permissions — no extra install or setup.
|
|
11
|
+
- **Real-time file sync**: Watches file changes (VFS) in your local working
|
|
12
|
+
directory and syncs them with the web dashboard instantly.
|
|
13
|
+
- **Security-first design**: Binds to the 127.0.0.1 loopback and verifies the
|
|
14
|
+
request Origin to keep local control safe.
|
|
15
|
+
- **(Optional) SSH mode**: If you provide credentials (user/password), it can
|
|
16
|
+
connect to a local SSH server instead. The default is the zero-install
|
|
17
|
+
direct shell.
|
|
10
18
|
|
|
11
|
-
##
|
|
19
|
+
## Getting started
|
|
12
20
|
|
|
13
|
-
|
|
21
|
+
Run instantly via npm without a separate install:
|
|
14
22
|
|
|
15
23
|
```bash
|
|
16
24
|
npx xkat up
|
|
17
25
|
```
|
|
18
26
|
|
|
19
|
-
|
|
27
|
+
Or install globally:
|
|
20
28
|
|
|
21
29
|
```bash
|
|
22
|
-
npm install -g xkat
|
|
30
|
+
npm install -g xkat-cli
|
|
23
31
|
xkat up
|
|
24
32
|
```
|
|
25
33
|
|
|
26
|
-
##
|
|
34
|
+
## System requirements
|
|
27
35
|
|
|
28
|
-
- **
|
|
29
|
-
- **
|
|
36
|
+
- **Node.js**: 16.x or newer.
|
|
37
|
+
- **OpenSSH Server (optional)**: Not needed for the default zero-install shell
|
|
38
|
+
mode. Only required when using the SSH credentials mode.
|
|
30
39
|
|
|
31
|
-
##
|
|
40
|
+
## Security guidelines
|
|
32
41
|
|
|
33
|
-
xKat Agent
|
|
34
|
-
1. **Localhost Only**: 포트 10022는 오직 로컬호스트에서만 접근 가능합니다.
|
|
35
|
-
2. **Origin Verification**: 공식 서비스 도메인에서 온 연결요청만 수락합니다.
|
|
36
|
-
3. **Audit Log**: 모든 접속 시도와 파일 변경 이벤트는 타임스탬프와 함께 로컬로그에 기록됩니다.
|
|
42
|
+
xKat Agent includes the following safeguards:
|
|
37
43
|
|
|
38
|
-
|
|
44
|
+
1. **Localhost only**: Port 10022 is reachable only from localhost.
|
|
45
|
+
2. **Origin verification**: Only connection requests from the official service
|
|
46
|
+
domains are accepted.
|
|
47
|
+
3. **Audit log**: Every connection attempt and file-change event is recorded
|
|
48
|
+
locally with a timestamp.
|
|
49
|
+
|
|
50
|
+
## Releasing (maintainers)
|
|
51
|
+
|
|
52
|
+
See `docs/xkat-agent/deployment-pipeline.md` and
|
|
53
|
+
`.github/workflows/release-agent.yml` for the release pipeline. Summary:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
cd apps/xkat-agent
|
|
57
|
+
npm version patch --no-git-tag-version
|
|
58
|
+
git add package.json && git commit -m "chore(agent): release vX.Y.Z"
|
|
59
|
+
git tag agent-v$(node -p "require('./package.json').version")
|
|
60
|
+
git push origin main --tags
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## License
|
|
39
64
|
|
|
40
65
|
MIT License
|
package/bin/xkat-cli.js
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* xkat-cli.js
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* A lightweight wrapper invoked when the user runs the `xkat` command from npm.
|
|
6
|
+
* Its only job: locate the Rust binary downloaded during postinstall and hand
|
|
7
|
+
* over execution to it.
|
|
7
8
|
*/
|
|
8
9
|
const { spawnSync } = require('child_process');
|
|
9
10
|
const path = require('path');
|
|
@@ -38,11 +39,11 @@ const binaryPath = path.join(__dirname, '..', 'binaries', getBinaryName());
|
|
|
38
39
|
|
|
39
40
|
if (!fs.existsSync(binaryPath)) {
|
|
40
41
|
console.error('❌ xkat-agent binary not found.');
|
|
41
|
-
console.error(' Try reinstalling: npm install -g xkat-
|
|
42
|
+
console.error(' Try reinstalling: npm install -g xkat-cli');
|
|
42
43
|
process.exit(1);
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
//
|
|
46
|
+
// Forward all argv straight to the Rust binary
|
|
46
47
|
const result = spawnSync(binaryPath, process.argv.slice(2), {
|
|
47
48
|
stdio: 'inherit',
|
|
48
49
|
env: process.env,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xkat-cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "xKat Local Terminal Agent - Bridge between Web IDE and Local Shell",
|
|
5
5
|
"main": "bin/xkat-cli.js",
|
|
6
6
|
"bin": {
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
},
|
|
21
21
|
"keywords": [
|
|
22
22
|
"xkat",
|
|
23
|
-
"codingkat",
|
|
24
23
|
"terminal",
|
|
25
24
|
"ssh",
|
|
26
25
|
"bridge",
|
package/scripts/install.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* install.js — postinstall
|
|
3
|
-
* npm install
|
|
4
|
-
*
|
|
2
|
+
* install.js — postinstall script
|
|
3
|
+
* Runs automatically right after `npm install`. Downloads the prebuilt Rust
|
|
4
|
+
* binary matching the user's OS/architecture from GitHub Releases (or R2).
|
|
5
5
|
*/
|
|
6
6
|
const os = require('os');
|
|
7
7
|
const fs = require('fs');
|
|
8
8
|
const path = require('path');
|
|
9
9
|
const https = require('https');
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
// Version is the single source of truth from package.json, so a release bump
|
|
12
|
+
// (npm version patch) automatically points install at the matching R2 folder.
|
|
13
|
+
const VERSION = require('../package.json').version;
|
|
12
14
|
const BASE_URL = `https://dl.xkat.space/v${VERSION}`;
|
|
13
15
|
|
|
14
16
|
function getPlatformTarget() {
|
|
@@ -30,23 +32,23 @@ async function main() {
|
|
|
30
32
|
const target = getPlatformTarget();
|
|
31
33
|
|
|
32
34
|
if (!target) {
|
|
33
|
-
console.log(`⚠️ xkat-agent:
|
|
34
|
-
console.log('
|
|
35
|
+
console.log(`⚠️ xkat-agent: unsupported platform (${os.platform()}-${os.arch()})`);
|
|
36
|
+
console.log(' Build manually: cd apps/xkat-agent && cargo build --release');
|
|
35
37
|
return;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
const binDir = path.join(__dirname, '..', 'binaries');
|
|
39
41
|
const destPath = path.join(binDir, target);
|
|
40
42
|
|
|
41
|
-
//
|
|
43
|
+
// Skip if already downloaded
|
|
42
44
|
if (fs.existsSync(destPath)) {
|
|
43
|
-
console.log(`✅ xkat-agent
|
|
45
|
+
console.log(`✅ xkat-agent binary already present: ${target}`);
|
|
44
46
|
return;
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
console.log(`📥 xkat-agent
|
|
49
|
+
console.log(`📥 Downloading xkat-agent... (${target})`);
|
|
48
50
|
|
|
49
|
-
// binaries
|
|
51
|
+
// Create the binaries directory
|
|
50
52
|
if (!fs.existsSync(binDir)) {
|
|
51
53
|
fs.mkdirSync(binDir, { recursive: true });
|
|
52
54
|
}
|
|
@@ -55,14 +57,14 @@ async function main() {
|
|
|
55
57
|
|
|
56
58
|
try {
|
|
57
59
|
await downloadFile(url, destPath);
|
|
58
|
-
//
|
|
60
|
+
// Grant execute permission (Unix only)
|
|
59
61
|
if (os.platform() !== 'win32') {
|
|
60
62
|
fs.chmodSync(destPath, 0o755);
|
|
61
63
|
}
|
|
62
|
-
console.log(`✅
|
|
64
|
+
console.log(`✅ Installed! Run: xkat up`);
|
|
63
65
|
} catch (err) {
|
|
64
|
-
console.log(`⚠️
|
|
65
|
-
console.log('
|
|
66
|
+
console.log(`⚠️ Binary download failed: ${err.message}`);
|
|
67
|
+
console.log(' To build locally: cd apps/xkat-agent && cargo build --release');
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
70
|
|
|
@@ -70,7 +72,7 @@ function downloadFile(url, dest) {
|
|
|
70
72
|
return new Promise((resolve, reject) => {
|
|
71
73
|
const file = fs.createWriteStream(dest);
|
|
72
74
|
https.get(url, (response) => {
|
|
73
|
-
// GitHub Releases
|
|
75
|
+
// GitHub Releases use 302 redirects
|
|
74
76
|
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
75
77
|
https.get(response.headers.location, (redirected) => {
|
|
76
78
|
redirected.pipe(file);
|