robin_cli_tool 1.1.0

A CLI tool to run scripts for any project
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429

<h1 align="center">robin</h1>
<p align="center">Your own customizable <b>CLI</b> tool</p>
<p align="center">
<a href="https://crates.io/crates/robin_cli_tool"><img alt="Crates.io Version" src="https://img.shields.io/crates/v/robin_cli_tool"></a>
<a href="https://github.com/cesarferreira/robin/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></a>
<img alt="Crates.io Total Downloads" src="https://img.shields.io/crates/d/robin_cli_tool">

  
</p>
<p align="center">
  <img src="media/terminal_ss4.png" width="100%" />
</p>


## Reason
> Maintaining a simple JSON file with all the available tasks allows for easy customization of deployment, release, cleaning, and other project-specific actions. This ensures that everyone on the team can use, edit, and add tasks on a project level.

## Features

- Define and run project-specific scripts via `.robin.json`
- Support for both single commands and command sequences
- Interactive mode with fuzzy search
- List all available commands
- Add new commands easily
- Cross-platform support
- Template initialization for different project types
- Variable substitution with default values
- Enum validation for variables
- Environment variable substitution with defaults (`${VAR:-default}`)

## Installation

```bash
# From crates.io
cargo install robin_cli_tool

# From source
cargo install --path .
```

## Usage

### Initialize a new project

```bash
robin init
```

This creates a `.robin.json` file in your current directory with some template scripts.

### Using templates

```bash
# Initialize with a specific template
robin init --template android    # Android project template
robin init --template ios        # iOS project template
robin init --template flutter    # Flutter project template
robin init --template rails      # Ruby on Rails project template
robin init --template node       # Node.js/TypeScript project template
robin init --template nextjs     # Next.js project template
robin init --template python     # Python project template
robin init --template rust       # Rust project template
robin init --template go         # Go project template
```

Each template comes with a curated set of useful commands for that specific platform or framework. For example:

- **Android**: Gradle commands, testing, linting (ktlint), and deployment
- **iOS**: Xcode build, CocoaPods, testing, SwiftLint, and Fastlane commands
- **Flutter**: Build, test, dependency management, and platform-specific commands
- **Rails**: Server, console, database tasks, testing, and code generation
- **Node.js**: Development, testing (Jest), TypeScript, linting (ESLint), and formatting (Prettier)
- **Python**: Virtual env, testing (pytest), linting (flake8), formatting (black), and type checking (mypy)
- **Rust**: Cargo commands for building, testing, linting (clippy), formatting, and documentation
- **Go**: Build, test, linting (golangci-lint), formatting, and dependency management

If a `.robin.json` file already exists, you'll be prompted to confirm before overriding it.

### List all commands

```bash
robin --list
```

### Interactive mode

```bash
robin --interactive  # or -i
```

### Add a new command

```bash
robin add "deploy" "fastlane deliver --submit-to-review"
```

### Run a command

```bash
robin deploy staging
robin release beta
```

## Configuration

The `.robin.json` file supports both single commands and command sequences:

```json
{
    "scripts": {
        "clean": "rm -rf build/",
        "deploy": "echo 'ruby deploy tool --{{env=[staging,production]}}'",
        "prep-and-deploy": [
            "robin clean",
            "robin build",
            "robin deploy --env=production"
        ],
        "full-release": [
            "flutter clean",
            "flutter pub get",
            "flutter build ios",
            "cd ios && fastlane beta"
        ]
    }
}
```

When using command sequences (arrays):
- Commands are executed in order
- If any command fails, the sequence stops
- Environment variables and working directory are preserved between commands
- Notifications show total execution time for the sequence

## External Configuration

Robin supports including external configuration files, which is particularly useful for monorepos or sharing common scripts across projects:

```json
{
    "include": [
        "../common/robin.base.json",
        "./team-specific.json"
    ],
    "scripts": {
        "local-dev": "npm run dev",
        "test": "npm run test"
    }
}
```

### Monorepo Example

Here's a typical monorepo structure using shared scripts:

```
monorepo/
├── common/
│   └── robin.base.json        # Shared scripts for all projects
├── frontend/
│   ├── .robin.json            # Frontend-specific scripts
│   └── package.json
├── backend/
│   ├── .robin.json            # Backend-specific scripts
│   └── package.json
└── mobile/
    ├── .robin.json            # Mobile-specific scripts
    └── pubspec.yaml
```

`common/robin.base.json`:
```json
{
    "scripts": {
        "lint": "eslint .",
        "format": "prettier --write .",
        "docker:up": "docker-compose up -d",
        "docker:down": "docker-compose down",
        "ci:test": [
            "npm ci",
            "npm run test"
        ]
    }
}
```

`frontend/.robin.json`:
```json
{
    "include": ["../common/robin.base.json"],
    "scripts": {
        "dev": "next dev",
        "build": "next build",
        "start": "next start",
        "deploy:staging": [
            "robin docker:down",
            "robin build",
            "robin docker:up"
        ]
    }
}
```

`mobile/.robin.json`:
```json
{
    "include": ["../common/robin.base.json"],
    "scripts": {
        "dev": "flutter run",
        "build:android": "flutter build apk",
        "build:ios": "flutter build ios",
        "deploy:beta": [
            "robin build:{{platform=[ios,android]}}",
            "fastlane {{platform}} beta"
        ]
    }
}
```

Scripts from included files are merged with local scripts, where local scripts take precedence. This allows you to:
- Share common development workflows across projects
- Maintain consistent CI/CD scripts
- Override shared scripts when needed
- Keep project-specific scripts separate from shared ones

## Variable Substitution

### Basic Variables
Use `{{variable}}` in your scripts and pass them as `--variable=XXX` when running the command:

```json
{
    "scripts": {
        "deploy": "fastlane {{platform}} {{env}}"
    }
}
```

Then run:
```bash
robin deploy --platform=ios --env=staging
```

### Default Values
You can specify default values for variables using `{{variable=default}}` syntax:

```json
{
    "scripts": {
        "build": "echo \"Building {{mode=debug}}\"",
        "deploy": "echo \"Deploying to {{env=staging}} with version {{version=latest}}\""
    }
}
```

Using default values:
```bash
robin build             # Will use default: debug
robin deploy            # Will use defaults: staging and latest

# Override defaults:
robin build --mode=release                  # Will use: release
robin deploy --env=prod --version=1.0.0     # Will use: prod and 1.0.0
```

### Enum Validation
You can restrict variable values to a specific set using `{{variable=[value1, value2, ...]}}` syntax:

```json
{
    "scripts": {
        "deploy": "echo \"Deploying to {{env=[staging, prod]}}\"",
        "build": "cargo build --{{mode=[debug, release]}}",
        "deploy:app": "fastlane {{platform=[ios, android]}} {{env=[dev, staging, prod]}} --track={{track=[alpha, beta, production]}}"
    }
}
```

Using enum validation:
```bash
# Simple validation
robin deploy --env=staging   # Works: 'staging' is allowed
robin deploy --env=prod      # Works: 'prod' is allowed
robin deploy --env=dev       # Fails: only 'staging' or 'prod' are allowed

# Build modes
robin build --mode=debug     # Works: 'debug' is allowed
robin build --mode=release   # Works: 'release' is allowed
robin build --mode=test      # Fails: only 'debug' or 'release' are allowed

# Multiple validations
robin deploy:app \
    --platform=ios \
    --env=staging \
    --track=beta            # Works: all values are allowed

robin deploy:app \
    --platform=web \        # Fails: 'web' is not in [ios, android]
    --env=staging \
    --track=beta
```

Variables work in both single commands and command sequences:
```json
{
    "scripts": {
        "deploy-sequence": [
            "flutter clean",
            "flutter build {{platform=[ios,android]}}",
            "fastlane {{platform}} beta"
        ]
    }
}
```

### Environment Variables with Defaults
In addition to the `{{...}}` syntax (which reads from `--variable=` arguments), you can
read values from the **environment** using Docker Compose-style `${VAR:-default}` syntax:

```json
{
    "scripts": {
        "serve": "echo \"starting on port ${PORT:-8080}\"",
        "deploy": "kubectl apply -n ${NAMESPACE:-default} -f deploy.yaml"
    }
}
```

```bash
robin serve              # PORT unset -> "starting on port 8080"
PORT=9000 robin serve    # PORT set   -> "starting on port 9000"
```

Two forms are supported (defaults only):

| Syntax | Behavior |
|--------|----------|
| `${VAR:-default}` | Use `$VAR` if it is set **and non-empty**, otherwise `default`. |
| `${VAR-default}`  | Use `$VAR` if it is **set** (even if empty), otherwise `default`. |

A bare `${VAR}` (with no default) is left untouched and expanded by the shell at run
time, exactly as before.

## Development Environment

### Doctor Command
The `doctor` command helps verify your development environment is properly set up:

```bash
robin doctor
```

This will check:
- 📦 Required Tools
  - Cargo and Rust
  - Ruby and Fastlane
  - Flutter
  - Node.js and npm
- 🔧 Environment Variables
  - ANDROID_HOME
  - JAVA_HOME
  - FLUTTER_ROOT
- 📱 Platform Tools
  - Android Debug Bridge (adb)
  - Xcode Command Line Tools
  - CocoaPods
- 🔐 Git Configuration
  - user.name
  - user.email

Example output:
```bash
🔍 Checking development environment...

📦 Required Tools:
✅ Cargo: cargo 1.75.0
✅ Rust: rustc 1.75.0
✅ Ruby: ruby 3.2.2
✅ Fastlane: fastlane 2.217.0
❌ Flutter not found
✅ Node.js: v20.10.0
✅ npm: 10.2.3

🔧 Environment Variables:
✅ ANDROID_HOME is set
✅ JAVA_HOME is set
❌ FLUTTER_ROOT is not set

📱 Platform Tools:
✅ Android Debug Bridge (adb): Android Debug Bridge version 1.0.41
✅ Xcode Command Line Tools: installed
✅ CocoaPods: 1.14.3

🔐 Git Configuration:
✅ Git user.name is set
✅ Git user.email is set
```

### Update Development Tools
To update all development tools to their latest versions:

```bash
robin doctor:update
```

This will update:
- Rust (via rustup)
- Flutter
- Fastlane (via gem)
- Global npm packages
- CocoaPods repositories

## Update Notifications

Robin checks [crates.io](https://crates.io/crates/robin_cli_tool) for newer
releases and prints a short notice when your installed version is out of date:

```
➜ A new version of robin is available: 1.5.0 (you have 1.0.2).
  Update with: cargo install robin_cli_tool
```

The check is throttled to at most once per day (the result is cached under your
OS cache directory), so it never slows down day-to-day usage. To disable it
entirely, set the `ROBIN_NO_UPDATE_CHECK` environment variable.

## License

MIT © [Cesar Ferreira](http://cesarferreira.com)