Skip to content

Commit d3ac5e1

Browse files
committed
cp dines
1 parent d39fd60 commit d3ac5e1

39 files changed

Lines changed: 1627 additions & 786 deletions

.prettierignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
node_modules
2+
dist
3+
build
4+
coverage
5+
.next
6+
*.log
7+
package-lock.json

.prettierrc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"semi": true,
3+
"singleQuote": true,
4+
"tabWidth": 2,
5+
"trailingComma": "es5",
6+
"printWidth": 100,
7+
"arrowParens": "avoid"
8+
}

package-lock.json

Lines changed: 19 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
"version:patch": "npm version patch",
1515
"version:minor": "npm version minor",
1616
"version:major": "npm version major",
17-
"release": "npm run build && npm publish"
17+
"release": "npm run build && npm publish",
18+
"format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json}\"",
19+
"format:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json}\""
1820
},
1921
"keywords": [
2022
"runloop",
@@ -68,6 +70,7 @@
6870
"devDependencies": {
6971
"@types/node": "^22.7.9",
7072
"@types/react": "^18.3.11",
73+
"prettier": "^3.6.2",
7174
"typescript": "^5.6.3"
7275
}
7376
}

src/cli.ts

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,7 @@ process.on('SIGINT', () => {
2727

2828
const program = new Command();
2929

30-
program
31-
.name('rln')
32-
.description('Beautiful CLI for Runloop devbox management')
33-
.version(VERSION);
30+
program.name('rln').description('Beautiful CLI for Runloop devbox management').version(VERSION);
3431

3532
program
3633
.command('auth')
@@ -41,10 +38,7 @@ program
4138
});
4239

4340
// Devbox commands
44-
const devbox = program
45-
.command('devbox')
46-
.description('Manage devboxes')
47-
.alias('d');
41+
const devbox = program.command('devbox').description('Manage devboxes').alias('d');
4842

4943
devbox
5044
.command('create')
@@ -59,7 +53,7 @@ devbox
5953
.description('List all devboxes')
6054
.option('-s, --status <status>', 'Filter by status')
6155
.option('-o, --output [format]', 'Output format: text|json|yaml (default: interactive)')
62-
.action(async (options) => {
56+
.action(async options => {
6357
// Only use alternate screen for interactive mode
6458
if (!options.output) {
6559
const { runInteractiveCommand } = await import('./utils/interactiveCommand.js');
@@ -90,17 +84,14 @@ devbox
9084
.action(uploadFile);
9185

9286
// Snapshot commands
93-
const snapshot = program
94-
.command('snapshot')
95-
.description('Manage devbox snapshots')
96-
.alias('snap');
87+
const snapshot = program.command('snapshot').description('Manage devbox snapshots').alias('snap');
9788

9889
snapshot
9990
.command('list')
10091
.description('List all snapshots')
10192
.option('-d, --devbox <id>', 'Filter by devbox ID')
10293
.option('-o, --output [format]', 'Output format: text|json|yaml (default: interactive)')
103-
.action(async (options) => {
94+
.action(async options => {
10495
const { listSnapshots } = await import('./commands/snapshot/list.js');
10596
if (!options.output) {
10697
const { runInteractiveCommand } = await import('./utils/interactiveCommand.js');
@@ -131,16 +122,13 @@ snapshot
131122
});
132123

133124
// Blueprint commands
134-
const blueprint = program
135-
.command('blueprint')
136-
.description('Manage blueprints')
137-
.alias('bp');
125+
const blueprint = program.command('blueprint').description('Manage blueprints').alias('bp');
138126

139127
blueprint
140128
.command('list')
141129
.description('List all blueprints')
142130
.option('-o, --output [format]', 'Output format: text|json|yaml (default: interactive)')
143-
.action(async (options) => {
131+
.action(async options => {
144132
const { listBlueprints } = await import('./commands/blueprint/list.js');
145133
if (!options.output) {
146134
const { runInteractiveCommand } = await import('./utils/interactiveCommand.js');
@@ -151,16 +139,14 @@ blueprint
151139
});
152140

153141
// MCP server commands
154-
const mcp = program
155-
.command('mcp')
156-
.description('Model Context Protocol (MCP) server commands');
142+
const mcp = program.command('mcp').description('Model Context Protocol (MCP) server commands');
157143

158144
mcp
159145
.command('start')
160146
.description('Start the MCP server')
161147
.option('--http', 'Use HTTP/SSE transport instead of stdio')
162148
.option('-p, --port <port>', 'Port to listen on for HTTP mode (default: 3000)', parseInt)
163-
.action(async (options) => {
149+
.action(async options => {
164150
if (options.http) {
165151
const { startMcpHttpServer } = await import('./commands/mcp-http.js');
166152
await startMcpHttpServer(options.port);
@@ -183,7 +169,7 @@ program
183169
.command('mcp-server', { hidden: true })
184170
.option('--http', 'Use HTTP/SSE transport instead of stdio')
185171
.option('-p, --port <port>', 'Port to listen on for HTTP mode (default: 3000)', parseInt)
186-
.action(async (options) => {
172+
.action(async options => {
187173
if (options.http) {
188174
const { startMcpHttpServer } = await import('./commands/mcp-http.js');
189175
await startMcpHttpServer(options.port);
@@ -197,7 +183,14 @@ program
197183
(async () => {
198184
// Check if API key is configured (except for auth and mcp commands)
199185
const args = process.argv.slice(2);
200-
if (args[0] !== 'auth' && args[0] !== 'mcp' && args[0] !== 'mcp-server' && args[0] !== '--help' && args[0] !== '-h' && args.length > 0) {
186+
if (
187+
args[0] !== 'auth' &&
188+
args[0] !== 'mcp' &&
189+
args[0] !== 'mcp-server' &&
190+
args[0] !== '--help' &&
191+
args[0] !== '-h' &&
192+
args.length > 0
193+
) {
201194
const config = getConfig();
202195
if (!config.apiKey) {
203196
console.error('\n❌ API key not configured. Run: rln auth\n');

src/commands/blueprint/list.tsx

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ const ListBlueprintsUI: React.FC<{
6868
},
6969
];
7070

71-
7271
// Clear console when transitioning to detail view
7372
const prevShowDetailsRef = React.useRef(showDetails);
7473
React.useEffect(() => {
@@ -123,7 +122,7 @@ const ListBlueprintsUI: React.FC<{
123122
useInput((input, key) => {
124123
// Handle operation input mode
125124
if (executingOperation && !operationResult && !operationError) {
126-
const currentOp = allOperations.find((op) => op.key === executingOperation);
125+
const currentOp = allOperations.find(op => op.key === executingOperation);
127126
if (currentOp?.needsInput) {
128127
if (key.return) {
129128
executeOperation();
@@ -188,7 +187,7 @@ const ListBlueprintsUI: React.FC<{
188187

189188
// Filter operations based on blueprint status
190189
const operations = selectedBlueprint
191-
? allOperations.filter((op) => {
190+
? allOperations.filter(op => {
192191
const status = selectedBlueprint.status;
193192

194193
// Only allow creating devbox if build is complete
@@ -203,8 +202,7 @@ const ListBlueprintsUI: React.FC<{
203202

204203
// Operation result display
205204
if (operationResult || operationError) {
206-
const operationLabel =
207-
operations.find((o) => o.key === executingOperation)?.label || 'Operation';
205+
const operationLabel = operations.find(o => o.key === executingOperation)?.label || 'Operation';
208206
return (
209207
<>
210208
<Breadcrumb
@@ -230,7 +228,7 @@ const ListBlueprintsUI: React.FC<{
230228

231229
// Operation input mode
232230
if (executingOperation && selectedBlueprint) {
233-
const currentOp = allOperations.find((op) => op.key === executingOperation);
231+
const currentOp = allOperations.find(op => op.key === executingOperation);
234232
const needsInput = currentOp?.needsInput;
235233
const operationLabel = currentOp?.label || 'Operation';
236234

@@ -377,21 +375,13 @@ const ListBlueprintsUI: React.FC<{
377375
<Text color={colors.warning} bold>
378376
{figures.squareSmallFilled} Dockerfile Setup
379377
</Text>
380-
{ds.base_image && (
381-
<Text dimColor>Base Image: {ds.base_image}</Text>
382-
)}
383-
{ds.entrypoint && (
384-
<Text dimColor>Entrypoint: {ds.entrypoint}</Text>
385-
)}
378+
{ds.base_image && <Text dimColor>Base Image: {ds.base_image}</Text>}
379+
{ds.entrypoint && <Text dimColor>Entrypoint: {ds.entrypoint}</Text>}
386380
{ds.system_packages && ds.system_packages.length > 0 && (
387-
<Text dimColor>
388-
System Packages: {ds.system_packages.join(', ')}
389-
</Text>
381+
<Text dimColor>System Packages: {ds.system_packages.join(', ')}</Text>
390382
)}
391383
{ds.python_packages && ds.python_packages.length > 0 && (
392-
<Text dimColor>
393-
Python Packages: {ds.python_packages.join(', ')}
394-
</Text>
384+
<Text dimColor>Python Packages: {ds.python_packages.join(', ')}</Text>
395385
)}
396386
</Box>
397387
)}
@@ -419,14 +409,14 @@ const ListBlueprintsUI: React.FC<{
419409
<OperationsMenu
420410
operations={operations}
421411
selectedIndex={selectedOperation}
422-
onNavigate={(direction) => {
412+
onNavigate={direction => {
423413
if (direction === 'up' && selectedOperation > 0) {
424414
setSelectedOperation(selectedOperation - 1);
425415
} else if (direction === 'down' && selectedOperation < operations.length - 1) {
426416
setSelectedOperation(selectedOperation + 1);
427417
}
428418
}}
429-
onSelect={(op) => {
419+
onSelect={op => {
430420
console.clear();
431421
setExecutingOperation(op.key as OperationType);
432422
}}
@@ -466,11 +456,16 @@ const ListBlueprintsUI: React.FC<{
466456
render: (blueprint: any, index: number, isSelected: boolean) => {
467457
const statusDisplay = getStatusDisplay(blueprint.status);
468458
return (
469-
<Text color={isSelected ? 'white' : statusDisplay.color} bold={true} inverse={isSelected} wrap="truncate">
459+
<Text
460+
color={isSelected ? 'white' : statusDisplay.color}
461+
bold={true}
462+
inverse={isSelected}
463+
wrap="truncate"
464+
>
470465
{statusDisplay.icon}{' '}
471466
</Text>
472467
);
473-
}
468+
},
474469
},
475470
{
476471
key: 'id',
@@ -482,11 +477,17 @@ const ListBlueprintsUI: React.FC<{
482477
const truncated = value.slice(0, width - 1);
483478
const padded = truncated.padEnd(width, ' ');
484479
return (
485-
<Text color={isSelected ? 'white' : colors.textDim} bold={false} dimColor={!isSelected} inverse={isSelected} wrap="truncate">
480+
<Text
481+
color={isSelected ? 'white' : colors.textDim}
482+
bold={false}
483+
dimColor={!isSelected}
484+
inverse={isSelected}
485+
wrap="truncate"
486+
>
486487
{padded}
487488
</Text>
488489
);
489-
}
490+
},
490491
},
491492
{
492493
key: 'statusText',
@@ -497,18 +498,20 @@ const ListBlueprintsUI: React.FC<{
497498
const truncated = statusDisplay.text.slice(0, statusTextWidth);
498499
const padded = truncated.padEnd(statusTextWidth, ' ');
499500
return (
500-
<Text color={isSelected ? 'white' : statusDisplay.color} bold={true} inverse={isSelected} wrap="truncate">
501+
<Text
502+
color={isSelected ? 'white' : statusDisplay.color}
503+
bold={true}
504+
inverse={isSelected}
505+
wrap="truncate"
506+
>
501507
{padded}
502508
</Text>
503509
);
504-
}
510+
},
505511
},
506-
createTextColumn(
507-
'name',
508-
'Name',
509-
(blueprint: any) => blueprint.name || '(unnamed)',
510-
{ width: nameWidth }
511-
),
512+
createTextColumn('name', 'Name', (blueprint: any) => blueprint.name || '(unnamed)', {
513+
width: nameWidth,
514+
}),
512515
createTextColumn(
513516
'description',
514517
'Description',

src/commands/devbox/delete.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,7 @@ const DeleteDevboxUI: React.FC<{ id: string }> = ({ id }) => {
3333
<>
3434
<Header title="Shutdown Devbox" subtitle={`Shutting down devbox: ${id}`} />
3535
{loading && <SpinnerComponent message="Shutting down devbox..." />}
36-
{success && (
37-
<SuccessMessage
38-
message="Devbox shut down successfully!"
39-
details={`ID: ${id}`}
40-
/>
41-
)}
36+
{success && <SuccessMessage message="Devbox shut down successfully!" details={`ID: ${id}`} />}
4237
{error && <ErrorMessage message="Failed to shutdown devbox" error={error} />}
4338
</>
4439
);

src/commands/devbox/exec.tsx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ import { SpinnerComponent } from '../../components/Spinner.js';
66
import { ErrorMessage } from '../../components/ErrorMessage.js';
77
import { colors } from '../../utils/theme.js';
88

9-
const ExecCommandUI: React.FC<{ id: string; command: string[] }> = ({
10-
id,
11-
command,
12-
}) => {
9+
const ExecCommandUI: React.FC<{ id: string; command: string[] }> = ({ id, command }) => {
1310
const [loading, setLoading] = React.useState(true);
1411
const [output, setOutput] = React.useState<string>('');
1512
const [error, setError] = React.useState<Error | null>(null);
@@ -34,10 +31,7 @@ const ExecCommandUI: React.FC<{ id: string; command: string[] }> = ({
3431

3532
return (
3633
<>
37-
<Header
38-
title="Execute Command"
39-
subtitle={`Running in devbox: ${id}`}
40-
/>
34+
<Header title="Execute Command" subtitle={`Running in devbox: ${id}`} />
4135
{loading && <SpinnerComponent message="Executing command..." />}
4236
{!loading && !error && (
4337
<Box flexDirection="column" marginTop={1}>

0 commit comments

Comments
 (0)