@b0xs/recorder 1.0.0

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 (46) hide show
  1. package/README.md +89 -0
  2. package/dist/api/client.d.ts +111 -0
  3. package/dist/api/client.d.ts.map +1 -0
  4. package/dist/api/client.js +186 -0
  5. package/dist/api/client.js.map +1 -0
  6. package/dist/cli/commands/init.d.ts +7 -0
  7. package/dist/cli/commands/init.d.ts.map +1 -0
  8. package/dist/cli/commands/init.js +104 -0
  9. package/dist/cli/commands/init.js.map +1 -0
  10. package/dist/cli/commands/login.d.ts +7 -0
  11. package/dist/cli/commands/login.d.ts.map +1 -0
  12. package/dist/cli/commands/login.js +154 -0
  13. package/dist/cli/commands/login.js.map +1 -0
  14. package/dist/cli/commands/record.d.ts +14 -0
  15. package/dist/cli/commands/record.d.ts.map +1 -0
  16. package/dist/cli/commands/record.js +244 -0
  17. package/dist/cli/commands/record.js.map +1 -0
  18. package/dist/core/chunk-uploader.d.ts +52 -0
  19. package/dist/core/chunk-uploader.d.ts.map +1 -0
  20. package/dist/core/chunk-uploader.js +180 -0
  21. package/dist/core/chunk-uploader.js.map +1 -0
  22. package/dist/core/pty-manager.d.ts +72 -0
  23. package/dist/core/pty-manager.d.ts.map +1 -0
  24. package/dist/core/pty-manager.js +205 -0
  25. package/dist/core/pty-manager.js.map +1 -0
  26. package/dist/core/recorder.d.ts +104 -0
  27. package/dist/core/recorder.d.ts.map +1 -0
  28. package/dist/core/recorder.js +330 -0
  29. package/dist/core/recorder.js.map +1 -0
  30. package/dist/core/stream-client.d.ts +62 -0
  31. package/dist/core/stream-client.d.ts.map +1 -0
  32. package/dist/core/stream-client.js +185 -0
  33. package/dist/core/stream-client.js.map +1 -0
  34. package/dist/index.d.ts +8 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +75 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/storage/auth-store.d.ts +37 -0
  39. package/dist/storage/auth-store.d.ts.map +1 -0
  40. package/dist/storage/auth-store.js +168 -0
  41. package/dist/storage/auth-store.js.map +1 -0
  42. package/dist/storage/config-store.d.ts +74 -0
  43. package/dist/storage/config-store.d.ts.map +1 -0
  44. package/dist/storage/config-store.js +164 -0
  45. package/dist/storage/config-store.js.map +1 -0
  46. package/package.json +54 -0
package/README.md ADDED
@@ -0,0 +1,89 @@
1
+ # @b0xs/recorder
2
+
3
+ CLI tool for recording terminal sessions to the BOXS platform.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @b0xs/recorder
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### First-time Setup
14
+
15
+ ```bash
16
+ # Authenticate with your API key
17
+ boxs login
18
+
19
+ # Initialize config (optional)
20
+ boxs init
21
+ ```
22
+
23
+ ### Recording a Session
24
+
25
+ ```bash
26
+ # Start recording
27
+ boxs record
28
+
29
+ # Record with a specific title
30
+ boxs record --title "My pentesting session"
31
+
32
+ # Record and run a specific command
33
+ boxs record "nmap -sV scanme.nmap.org"
34
+ ```
35
+
36
+ ### Options
37
+
38
+ - `--title` - Session title
39
+ - `--description` - Session description
40
+ - `--visibility` - Session visibility (public, private, unlisted)
41
+
42
+ ## Features
43
+
44
+ - **Real-time upload** - Chunks uploaded every 60 seconds
45
+ - **Offline mode** - Continue recording without network, auto-upload when reconnected
46
+ - **Command detection** - Automatically detect and mark commands in timeline
47
+ - **Crash recovery** - Resume incomplete sessions after crashes
48
+ - **Secure auth** - API keys stored in OS keychain
49
+
50
+ ## Configuration
51
+
52
+ Config file: `~/.boxs/config.json`
53
+
54
+ ```json
55
+ {
56
+ "apiUrl": "https://boxs.sh",
57
+ "defaults": {
58
+ "visibility": "private",
59
+ "chunkDuration": 60000
60
+ },
61
+ "recorder": {
62
+ "promptPatterns": ["\\\\$\\\\s$", "#\\\\s$"],
63
+ "maxBufferedChunks": 10,
64
+ "uploadRetries": 5
65
+ }
66
+ }
67
+ ```
68
+
69
+ ## How It Works
70
+
71
+ 1. **Captures terminal** - Uses PTY to capture all terminal I/O
72
+ 2. **Encodes with BoxsBinary** - Compresses data using custom binary format
73
+ 3. **Uploads chunks** - Sends 60-second chunks to BOXS platform
74
+ 4. **Detects commands** - Marks command execution for timeline
75
+
76
+ ## License
77
+
78
+ MIT
79
+
80
+ ## Related Packages
81
+
82
+ - [`@b0xs/binary`](https://www.npmjs.com/package/@b0xs/binary) - Binary format encoder/decoder
83
+ - [`@b0xs/termbox`](https://www.npmjs.com/package/@b0xs/termbox) - React player component
84
+
85
+ ## Links
86
+
87
+ - [GitHub](https://github.com/ozipi/recorder)
88
+ - [Documentation](https://boxs.sh/docs)
89
+ - [Website](https://boxs.sh)
@@ -0,0 +1,111 @@
1
+ /**
2
+ * API Client for BOXS Platform
3
+ *
4
+ * Handles all HTTP requests to the BOXS API with authentication
5
+ */
6
+ export interface CreateSessionRequest {
7
+ title: string;
8
+ description?: string;
9
+ visibility?: 'public' | 'private' | 'unlisted' | 'team';
10
+ }
11
+ export interface CreateSessionResponse {
12
+ id: string;
13
+ title: string;
14
+ description?: string;
15
+ visibility: string;
16
+ status: string;
17
+ userId: string;
18
+ createdAt: string;
19
+ uploadEndpoint: string;
20
+ }
21
+ export interface UploadChunkResponse {
22
+ chunk: {
23
+ index: number;
24
+ url: string;
25
+ pathname: string;
26
+ size: number;
27
+ offset: number;
28
+ duration: number;
29
+ frameCount: number;
30
+ eventCount: number;
31
+ };
32
+ totalChunks: number;
33
+ }
34
+ export interface UpdateSessionRequest {
35
+ status?: 'recording' | 'completed' | 'failed';
36
+ title?: string;
37
+ description?: string;
38
+ visibility?: 'public' | 'private' | 'unlisted' | 'team';
39
+ }
40
+ export interface APIClientOptions {
41
+ apiKey: string;
42
+ baseUrl?: string;
43
+ timeout?: number;
44
+ }
45
+ export declare class APIClient {
46
+ private client;
47
+ private apiKey;
48
+ private baseUrl;
49
+ constructor(options: APIClientOptions);
50
+ /**
51
+ * Validate API key by making a test request
52
+ */
53
+ validateApiKey(): Promise<boolean>;
54
+ /**
55
+ * Create a new recording session
56
+ */
57
+ createSession(request: CreateSessionRequest): Promise<CreateSessionResponse>;
58
+ /**
59
+ * Upload a chunk to a session
60
+ */
61
+ uploadChunk(sessionId: string, chunkData: Buffer): Promise<UploadChunkResponse>;
62
+ /**
63
+ * Update session metadata or status
64
+ */
65
+ updateSession(sessionId: string, updates: UpdateSessionRequest): Promise<void>;
66
+ /**
67
+ * Get session details
68
+ */
69
+ getSession(sessionId: string): Promise<any>;
70
+ /**
71
+ * Get the full session URL for sharing
72
+ */
73
+ getSessionUrl(sessionId: string): string;
74
+ /**
75
+ * Start streaming session (get WebSocket token)
76
+ */
77
+ startStream(sessionId: string): Promise<{
78
+ streamToken: string;
79
+ wsUrl: string;
80
+ }>;
81
+ /**
82
+ * Stop streaming session
83
+ */
84
+ stopStream(sessionId: string): Promise<void>;
85
+ }
86
+ export declare class APIError extends Error {
87
+ statusCode?: number | undefined;
88
+ constructor(message: string, statusCode?: number | undefined);
89
+ }
90
+ export declare class AuthenticationError extends APIError {
91
+ constructor(message: string);
92
+ }
93
+ export declare class ForbiddenError extends APIError {
94
+ constructor(message: string);
95
+ }
96
+ export declare class NotFoundError extends APIError {
97
+ constructor(message: string);
98
+ }
99
+ export declare class ConflictError extends APIError {
100
+ constructor(message: string);
101
+ }
102
+ export declare class RateLimitError extends APIError {
103
+ constructor(message: string);
104
+ }
105
+ export declare class ServerError extends APIError {
106
+ constructor(message: string);
107
+ }
108
+ export declare class NetworkError extends APIError {
109
+ constructor(message: string);
110
+ }
111
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ /**
3
+ * API Client for BOXS Platform
4
+ *
5
+ * Handles all HTTP requests to the BOXS API with authentication
6
+ */
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.NetworkError = exports.ServerError = exports.RateLimitError = exports.ConflictError = exports.NotFoundError = exports.ForbiddenError = exports.AuthenticationError = exports.APIError = exports.APIClient = void 0;
12
+ const axios_1 = __importDefault(require("axios"));
13
+ class APIClient {
14
+ constructor(options) {
15
+ this.apiKey = options.apiKey;
16
+ this.baseUrl = options.baseUrl || 'https://boxs.sh';
17
+ this.client = axios_1.default.create({
18
+ baseURL: this.baseUrl,
19
+ timeout: options.timeout || 30000,
20
+ headers: {
21
+ 'Authorization': `Bearer ${this.apiKey}`,
22
+ 'Content-Type': 'application/json',
23
+ },
24
+ });
25
+ // Add response interceptor for error handling
26
+ this.client.interceptors.response.use((response) => response, (error) => {
27
+ if (error.response) {
28
+ const status = error.response.status;
29
+ const data = error.response.data;
30
+ switch (status) {
31
+ case 401:
32
+ throw new AuthenticationError('Invalid API key. Run: boxs login');
33
+ case 403:
34
+ throw new ForbiddenError('Access forbidden');
35
+ case 404:
36
+ throw new NotFoundError(data.error || 'Resource not found');
37
+ case 409:
38
+ throw new ConflictError(data.error || 'Conflict');
39
+ case 429:
40
+ throw new RateLimitError('Rate limit exceeded. Please try again later.');
41
+ case 500:
42
+ case 502:
43
+ case 503:
44
+ throw new ServerError('Server error. Retrying...');
45
+ default:
46
+ throw new APIError(data.error || 'Unknown API error', status);
47
+ }
48
+ }
49
+ else if (error.request) {
50
+ throw new NetworkError('Network error. Check your connection.');
51
+ }
52
+ else {
53
+ throw new APIError(error.message);
54
+ }
55
+ });
56
+ }
57
+ /**
58
+ * Validate API key by making a test request
59
+ */
60
+ async validateApiKey() {
61
+ try {
62
+ await this.client.get('/api/users/me');
63
+ return true;
64
+ }
65
+ catch (error) {
66
+ if (error instanceof AuthenticationError) {
67
+ return false;
68
+ }
69
+ throw error;
70
+ }
71
+ }
72
+ /**
73
+ * Create a new recording session
74
+ */
75
+ async createSession(request) {
76
+ const response = await this.client.post('/api/sessions', {
77
+ title: request.title,
78
+ description: request.description,
79
+ visibility: request.visibility || 'private',
80
+ });
81
+ return response.data;
82
+ }
83
+ /**
84
+ * Upload a chunk to a session
85
+ */
86
+ async uploadChunk(sessionId, chunkData) {
87
+ const response = await this.client.post(`/api/sessions/${sessionId}/chunks`, chunkData, {
88
+ headers: {
89
+ 'Content-Type': 'application/octet-stream',
90
+ },
91
+ });
92
+ return response.data;
93
+ }
94
+ /**
95
+ * Update session metadata or status
96
+ */
97
+ async updateSession(sessionId, updates) {
98
+ await this.client.patch(`/api/sessions/${sessionId}`, updates);
99
+ }
100
+ /**
101
+ * Get session details
102
+ */
103
+ async getSession(sessionId) {
104
+ const response = await this.client.get(`/api/sessions/${sessionId}`);
105
+ return response.data;
106
+ }
107
+ /**
108
+ * Get the full session URL for sharing
109
+ */
110
+ getSessionUrl(sessionId) {
111
+ return `${this.baseUrl}/sessions/${sessionId}`;
112
+ }
113
+ /**
114
+ * Start streaming session (get WebSocket token)
115
+ */
116
+ async startStream(sessionId) {
117
+ const response = await this.client.post(`/api/sessions/${sessionId}/start-stream`);
118
+ return response.data;
119
+ }
120
+ /**
121
+ * Stop streaming session
122
+ */
123
+ async stopStream(sessionId) {
124
+ await this.client.post(`/api/sessions/${sessionId}/stop-stream`);
125
+ }
126
+ }
127
+ exports.APIClient = APIClient;
128
+ // Custom error classes
129
+ class APIError extends Error {
130
+ constructor(message, statusCode) {
131
+ super(message);
132
+ this.statusCode = statusCode;
133
+ this.name = 'APIError';
134
+ }
135
+ }
136
+ exports.APIError = APIError;
137
+ class AuthenticationError extends APIError {
138
+ constructor(message) {
139
+ super(message, 401);
140
+ this.name = 'AuthenticationError';
141
+ }
142
+ }
143
+ exports.AuthenticationError = AuthenticationError;
144
+ class ForbiddenError extends APIError {
145
+ constructor(message) {
146
+ super(message, 403);
147
+ this.name = 'ForbiddenError';
148
+ }
149
+ }
150
+ exports.ForbiddenError = ForbiddenError;
151
+ class NotFoundError extends APIError {
152
+ constructor(message) {
153
+ super(message, 404);
154
+ this.name = 'NotFoundError';
155
+ }
156
+ }
157
+ exports.NotFoundError = NotFoundError;
158
+ class ConflictError extends APIError {
159
+ constructor(message) {
160
+ super(message, 409);
161
+ this.name = 'ConflictError';
162
+ }
163
+ }
164
+ exports.ConflictError = ConflictError;
165
+ class RateLimitError extends APIError {
166
+ constructor(message) {
167
+ super(message, 429);
168
+ this.name = 'RateLimitError';
169
+ }
170
+ }
171
+ exports.RateLimitError = RateLimitError;
172
+ class ServerError extends APIError {
173
+ constructor(message) {
174
+ super(message, 500);
175
+ this.name = 'ServerError';
176
+ }
177
+ }
178
+ exports.ServerError = ServerError;
179
+ class NetworkError extends APIError {
180
+ constructor(message) {
181
+ super(message);
182
+ this.name = 'NetworkError';
183
+ }
184
+ }
185
+ exports.NetworkError = NetworkError;
186
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Init Command
3
+ *
4
+ * Initialize configuration file with user preferences
5
+ */
6
+ export declare function initCommand(): Promise<void>;
7
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAgEjD"}
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ /**
3
+ * Init Command
4
+ *
5
+ * Initialize configuration file with user preferences
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ var __importDefault = (this && this.__importDefault) || function (mod) {
41
+ return (mod && mod.__esModule) ? mod : { "default": mod };
42
+ };
43
+ Object.defineProperty(exports, "__esModule", { value: true });
44
+ exports.initCommand = initCommand;
45
+ const readline = __importStar(require("readline"));
46
+ const chalk_1 = __importDefault(require("chalk"));
47
+ const config_store_1 = require("../../storage/config-store");
48
+ async function initCommand() {
49
+ console.log(chalk_1.default.cyan('\n⚙️ BOXS Recorder Configuration\n'));
50
+ const configStore = new config_store_1.ConfigStore();
51
+ const rl = readline.createInterface({
52
+ input: process.stdin,
53
+ output: process.stdout,
54
+ });
55
+ const question = (prompt, defaultValue) => {
56
+ return new Promise((resolve) => {
57
+ const promptText = defaultValue
58
+ ? `${prompt} ${chalk_1.default.gray(`(default: ${defaultValue})`)}: `
59
+ : `${prompt}: `;
60
+ rl.question(promptText, (answer) => {
61
+ resolve(answer || defaultValue || '');
62
+ });
63
+ });
64
+ };
65
+ try {
66
+ // API URL
67
+ const currentApiUrl = configStore.getApiUrl();
68
+ const apiUrl = await question('API URL', currentApiUrl);
69
+ if (apiUrl && apiUrl !== currentApiUrl) {
70
+ configStore.setApiUrl(apiUrl);
71
+ }
72
+ // Default visibility
73
+ const currentVisibility = configStore.getDefaultVisibility();
74
+ console.log(chalk_1.default.gray('\nVisibility options: public, private, unlisted, team'));
75
+ const visibility = await question('Default visibility', currentVisibility);
76
+ if (visibility && ['public', 'private', 'unlisted', 'team'].includes(visibility)) {
77
+ configStore.setDefaultVisibility(visibility);
78
+ }
79
+ // Chunk duration
80
+ const currentDuration = configStore.getChunkDuration();
81
+ const duration = await question('Chunk duration (ms)', currentDuration.toString());
82
+ if (duration) {
83
+ const durationNum = parseInt(duration);
84
+ if (!isNaN(durationNum)) {
85
+ try {
86
+ configStore.setChunkDuration(durationNum);
87
+ }
88
+ catch (error) {
89
+ console.log(chalk_1.default.yellow(`\n⚠ ${error.message}`));
90
+ }
91
+ }
92
+ }
93
+ rl.close();
94
+ console.log(chalk_1.default.green('\n✓ Configuration saved!'));
95
+ console.log(chalk_1.default.gray(`\nConfig file: ${configStore.getConfigPath()}`));
96
+ console.log(chalk_1.default.gray('\nYou can edit this file directly or run this command again.\n'));
97
+ }
98
+ catch (error) {
99
+ rl.close();
100
+ console.log(chalk_1.default.red(`\n✗ Error: ${error.message}\n`));
101
+ process.exit(1);
102
+ }
103
+ }
104
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Login Command
3
+ *
4
+ * Authenticate with BOXS platform using API key
5
+ */
6
+ export declare function loginCommand(): Promise<void>;
7
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/login.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CA+DlD"}