bod-cli 0.3.1
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/.cursor/skills/using-bod-cli/SKILL.md +274 -0
- package/.github/workflows/publish.yml +54 -0
- package/CLAUDE.md +50 -0
- package/dist/cli.js +12903 -0
- package/package.json +21 -0
- package/src/cli.ts +146 -0
- package/src/client.ts +42 -0
- package/src/commands/add.ts +79 -0
- package/src/commands/apps.ts +71 -0
- package/src/commands/deploy.ts +103 -0
- package/src/commands/env.ts +107 -0
- package/src/commands/init/init.ts +277 -0
- package/src/commands/init/templates.ts +171 -0
- package/src/commands/login.ts +60 -0
- package/src/commands/logs.ts +46 -0
- package/src/commands/open.ts +29 -0
- package/src/commands/remove.ts +16 -0
- package/src/commands/rollback.ts +28 -0
- package/src/commands/serve.ts +36 -0
- package/src/commands/ssh.ts +48 -0
- package/src/config.ts +82 -0
- package/src/utils/logger.ts +20 -0
- package/src/utils/output.ts +26 -0
- package/src/utils/resolve.ts +32 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: using-bod-cli
|
|
3
|
+
description: Guide for AI agents to use the bod CLI to scaffold, deploy, manage, and operate apps on Bodify. Use when creating new projects, deploying code, managing environments, viewing logs, or operating deployed apps.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Using bod-cli
|
|
7
|
+
|
|
8
|
+
`bod` is the unified CLI for the Bod product family. Currently supports Bodify (self-hosted deployment platform).
|
|
9
|
+
|
|
10
|
+
## Setup
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# Install globally (from the bod-cli directory)
|
|
14
|
+
bun link
|
|
15
|
+
|
|
16
|
+
# Or run directly
|
|
17
|
+
bun /path/to/bod-cli/src/cli.ts <command>
|
|
18
|
+
|
|
19
|
+
# First-run: authenticate with a Bodify instance
|
|
20
|
+
bod login https://your-bodify-server.com --key YOUR_API_KEY
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Config stored at `~/.bod/config.json`. Supports multiple instances.
|
|
24
|
+
|
|
25
|
+
## End-to-End: New Project
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# 1. Create directory and init
|
|
29
|
+
mkdir my-api && cd my-api
|
|
30
|
+
bod init
|
|
31
|
+
# → Select template (caab / caab-db / static / server)
|
|
32
|
+
# → Enter app name
|
|
33
|
+
# → Auto: scaffolds files, git init, registers with Bodify, bun install
|
|
34
|
+
|
|
35
|
+
# 2. Deploy
|
|
36
|
+
bod deploy
|
|
37
|
+
|
|
38
|
+
# 3. Monitor
|
|
39
|
+
bod logs my-api -f
|
|
40
|
+
bod apps status my-api
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## End-to-End: Existing Project
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
cd my-existing-project
|
|
47
|
+
bod init
|
|
48
|
+
# → Auto-detects type (api.ts=caab, dist/=static, server.ts=server, packages/=mixed)
|
|
49
|
+
# → Creates bodify.yaml, registers with Bodify, sets up .claude/ config
|
|
50
|
+
|
|
51
|
+
bod deploy
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Command Reference
|
|
55
|
+
|
|
56
|
+
### `bod login <url>`
|
|
57
|
+
Authenticate with a Bodify instance.
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
bod login https://bodify.example.com # prompts for API key
|
|
61
|
+
bod login https://bodify.example.com --key=$KEY # non-interactive
|
|
62
|
+
bod login https://bodify.example.com --name=prod # custom alias
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Verifies connectivity (`/healthz`), fetches capabilities (`/config/public`), saves to config.
|
|
66
|
+
|
|
67
|
+
### `bod init`
|
|
68
|
+
Initialize or connect a project to Bodify.
|
|
69
|
+
|
|
70
|
+
**Empty directory:** prompts for template, scaffolds complete project:
|
|
71
|
+
- Source files (api.ts / App.tsx / server.ts)
|
|
72
|
+
- `package.json`, `tsconfig.json`, `bodify.yaml`
|
|
73
|
+
- `.claude/CLAUDE.md` — project context for Claude agents
|
|
74
|
+
- `.claude/mcp_servers.json` — MCP connection to Bodify
|
|
75
|
+
- `.gitignore`, git init + initial commit
|
|
76
|
+
- Registers app with Bodify API
|
|
77
|
+
- `.npmrc` if registry enabled
|
|
78
|
+
- `bun install`
|
|
79
|
+
|
|
80
|
+
**Existing directory:** detects app type, creates `bodify.yaml`, registers, generates `.claude/` config.
|
|
81
|
+
|
|
82
|
+
### `bod deploy [app] [--branch=...]`
|
|
83
|
+
Trigger deployment. Reads app name from positional arg or `bodify.yaml`. Auto-detects current git branch.
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
bod deploy # from project dir with bodify.yaml
|
|
87
|
+
bod deploy my-api # explicit app name
|
|
88
|
+
bod deploy my-api --branch=lab # specific branch
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Two deploy modes** (auto-detected):
|
|
92
|
+
- **Git-based**: if the app has a `repo` URL, Bodify clones from git (standard flow)
|
|
93
|
+
- **Upload-based**: if no repo URL, the CLI tars the local working directory and uploads it directly — no git remote needed
|
|
94
|
+
|
|
95
|
+
Polls for completion (up to 4 min), shows status updates.
|
|
96
|
+
|
|
97
|
+
### `bod rollback [app] [--branch=...]`
|
|
98
|
+
Rollback to previous deployment.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
bod rollback my-api
|
|
102
|
+
bod rollback my-api --branch=lab
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### `bod apps list`
|
|
106
|
+
List all registered apps with name, domain, branch, type, repo.
|
|
107
|
+
|
|
108
|
+
### `bod apps status <app>`
|
|
109
|
+
Detailed view: app config, running instances, recent deployments.
|
|
110
|
+
|
|
111
|
+
### `bod logs <app> [-f] [--lines=100]`
|
|
112
|
+
View application logs.
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
bod logs my-api # last 100 lines
|
|
116
|
+
bod logs my-api --lines=500 # more lines
|
|
117
|
+
bod logs my-api -f # follow mode (polls every 2s)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### `bod open <app>`
|
|
121
|
+
Open an app in the default browser. Resolves the URL from the app's domain.
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
bod open my-api # opens https://my-api.bodify.example.com
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### `bod env list|set|unset <app>`
|
|
128
|
+
Manage environment variables.
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
bod env list my-api
|
|
132
|
+
bod env set my-api DATABASE_URL=postgres://...
|
|
133
|
+
bod env set my-api -f .env # bulk set from .env file
|
|
134
|
+
bod env unset my-api OLD_VAR
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### `bod add <pkg>` / `bod remove <pkg>`
|
|
138
|
+
Registry-aware package management. If Bodify registry is enabled, `bun add` uses it automatically.
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
bod add @bod.ee/db # from Bodify registry
|
|
142
|
+
bod add lodash # falls through to npm
|
|
143
|
+
bod remove @bod.ee/db
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Multi-Instance Support
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# Add another instance
|
|
150
|
+
bod login https://staging.example.com --name=staging
|
|
151
|
+
|
|
152
|
+
# Use specific instance for a command
|
|
153
|
+
bod apps list --instance=staging
|
|
154
|
+
|
|
155
|
+
# Or via env var
|
|
156
|
+
BOD_INSTANCE=staging bod apps list
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Templates
|
|
160
|
+
|
|
161
|
+
| Template | Files | Use Case |
|
|
162
|
+
|----------|-------|----------|
|
|
163
|
+
| `caab` | `api.ts` with Resource convention | REST API, methods → endpoints |
|
|
164
|
+
| `caab-db` | `api.ts` + BodDB setup | API with embedded database |
|
|
165
|
+
| `static` | React + Vite + `vite.config.ts` | SPA, served from `dist/` |
|
|
166
|
+
| `server` | `server.ts` with `Bun.serve()` | Custom HTTP server |
|
|
167
|
+
|
|
168
|
+
### CaaB Templates Use Resource Convention
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
abstract class Resource {
|
|
172
|
+
static readonly [Symbol.for('bodify.Resource')] = true;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
class Items extends Resource {
|
|
176
|
+
async get() { ... } // GET /items
|
|
177
|
+
async getById(id: string) { ... } // GET /items/by-id/:id
|
|
178
|
+
async post(body: {...}) { ... } // POST /items
|
|
179
|
+
async delete(id: string) { ... } // DELETE /items/:id
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export default class Api extends Resource {
|
|
183
|
+
items = new Items();
|
|
184
|
+
async getHealthz() { ... } // GET /healthz
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Server Template Requirements
|
|
189
|
+
|
|
190
|
+
- Read `PORT` from `process.env.PORT`
|
|
191
|
+
- Expose `GET /healthz` returning JSON
|
|
192
|
+
- Bodify health-checks this endpoint
|
|
193
|
+
|
|
194
|
+
## AI-First: Generated `.claude/` Config
|
|
195
|
+
|
|
196
|
+
`bod init` generates two files for Claude Code integration:
|
|
197
|
+
|
|
198
|
+
**`.claude/CLAUDE.md`** — Project context with:
|
|
199
|
+
- Commands cheat sheet
|
|
200
|
+
- CaaB convention reference (for caab/caab-db templates)
|
|
201
|
+
- BodDB API reference (for database-enabled apps)
|
|
202
|
+
- Server requirements (for server template)
|
|
203
|
+
- MCP integration note
|
|
204
|
+
|
|
205
|
+
**`.claude/mcp_servers.json`** — MCP connection using `${BODIFY_API_KEY}` env var reference (not hardcoded keys). Users set the env var and Claude Code can manage the app via MCP tools.
|
|
206
|
+
|
|
207
|
+
## Config File
|
|
208
|
+
|
|
209
|
+
`~/.bod/config.json`:
|
|
210
|
+
```json
|
|
211
|
+
{
|
|
212
|
+
"instances": {
|
|
213
|
+
"my-server": {
|
|
214
|
+
"url": "https://bodify.example.com",
|
|
215
|
+
"apiKey": "$BODIFY_KEY",
|
|
216
|
+
"capabilities": {
|
|
217
|
+
"registryEnabled": true,
|
|
218
|
+
"baseDomain": "bodify.example.com",
|
|
219
|
+
"githubConfigured": true
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
"defaultInstance": "my-server"
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
API key supports env var references: `$VAR_NAME` or `env:VAR_NAME`.
|
|
228
|
+
|
|
229
|
+
## Common Agent Tasks
|
|
230
|
+
|
|
231
|
+
### "Set up a new CaaB API"
|
|
232
|
+
```bash
|
|
233
|
+
mkdir my-api && cd my-api
|
|
234
|
+
bod init # select caab or caab-db
|
|
235
|
+
# Edit api.ts to add your resources
|
|
236
|
+
bod deploy
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### "Deploy a specific branch"
|
|
240
|
+
```bash
|
|
241
|
+
bod deploy my-app --branch=feature-xyz
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### "Deploy without a git remote"
|
|
245
|
+
```bash
|
|
246
|
+
# Works from any local project — tars and uploads source directly
|
|
247
|
+
bod init # register app (no git remote needed)
|
|
248
|
+
bod deploy # auto-detects no repo, uploads tarball
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### "Debug a failing deployment"
|
|
252
|
+
```bash
|
|
253
|
+
bod apps status my-app # check deployment status
|
|
254
|
+
bod logs my-app -f # check logs
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### "Add an env var and redeploy"
|
|
258
|
+
```bash
|
|
259
|
+
bod env set my-app API_SECRET=xxx
|
|
260
|
+
bod deploy my-app
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### "Bulk set env vars from .env file"
|
|
264
|
+
```bash
|
|
265
|
+
bod env set my-app -f .env
|
|
266
|
+
bod deploy my-app
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### "Connect an existing project"
|
|
270
|
+
```bash
|
|
271
|
+
cd existing-project
|
|
272
|
+
bod init # auto-detects type, registers with Bodify
|
|
273
|
+
bod deploy
|
|
274
|
+
```
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: Publish to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
publish-npm:
|
|
10
|
+
if: "!contains(github.event.head_commit.message, '[skip ci]')"
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
permissions:
|
|
13
|
+
contents: write
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
with:
|
|
18
|
+
fetch-depth: 0
|
|
19
|
+
|
|
20
|
+
- uses: actions/setup-node@v4
|
|
21
|
+
with:
|
|
22
|
+
node-version: '20'
|
|
23
|
+
registry-url: 'https://registry.npmjs.org/'
|
|
24
|
+
|
|
25
|
+
- uses: oven-sh/setup-bun@v1
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: bun install --frozen-lockfile
|
|
29
|
+
|
|
30
|
+
- name: Build
|
|
31
|
+
run: bun run build
|
|
32
|
+
|
|
33
|
+
- name: Configure Git
|
|
34
|
+
run: |
|
|
35
|
+
git config user.name "GitHub Actions Bot"
|
|
36
|
+
git config user.email "actions@github.com"
|
|
37
|
+
|
|
38
|
+
- name: Bump version and commit
|
|
39
|
+
run: |
|
|
40
|
+
npm version patch --no-git-tag-version
|
|
41
|
+
VERSION=$(node -p "require('./package.json').version")
|
|
42
|
+
git add package.json
|
|
43
|
+
git commit -m "chore: release v${VERSION} [skip ci]"
|
|
44
|
+
|
|
45
|
+
- name: Publish to npm
|
|
46
|
+
run: npm publish --access public
|
|
47
|
+
env:
|
|
48
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
49
|
+
|
|
50
|
+
- name: Push tag
|
|
51
|
+
run: |
|
|
52
|
+
VERSION=$(node -p "require('./package.json').version")
|
|
53
|
+
git tag "v${VERSION}"
|
|
54
|
+
git push --follow-tags
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# bod-cli
|
|
2
|
+
|
|
3
|
+
Unified CLI for the Bod product family. Currently supports Bodify (self-hosted Vercel alternative).
|
|
4
|
+
|
|
5
|
+
## Skill Path
|
|
6
|
+
|
|
7
|
+
See `.cursor/skills/using-bod-cli/SKILL.md` — full command reference, templates, AI integration, common tasks.
|
|
8
|
+
|
|
9
|
+
## Quick Reference
|
|
10
|
+
|
|
11
|
+
- Runtime: Bun
|
|
12
|
+
- Framework: citty (defineCommand/runMain)
|
|
13
|
+
- Config: `~/.bod/config.json` (Zod-validated, multi-instance)
|
|
14
|
+
- Interactive prompts: @inquirer/prompts
|
|
15
|
+
|
|
16
|
+
## Architecture
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
src/
|
|
20
|
+
├── cli.ts # citty entry + interactive menu
|
|
21
|
+
├── config.ts # ~/.bod/config.json management
|
|
22
|
+
├── client.ts # HTTP client (auth, JSON, errors)
|
|
23
|
+
├── utils/
|
|
24
|
+
│ ├── logger.ts # component logger
|
|
25
|
+
│ ├── output.ts # printTable, printJson, printKv
|
|
26
|
+
│ └── resolve.ts # resolveAppId, readAppNameFromYaml
|
|
27
|
+
└── commands/
|
|
28
|
+
├── login.ts # bod login <url>
|
|
29
|
+
├── init/ # bod init (scaffold or connect)
|
|
30
|
+
│ ├── init.ts
|
|
31
|
+
│ └── templates.ts
|
|
32
|
+
├── deploy.ts # bod deploy [app]
|
|
33
|
+
├── rollback.ts # bod rollback [app]
|
|
34
|
+
├── apps.ts # bod apps list|status
|
|
35
|
+
├── logs.ts # bod logs <app> [-f]
|
|
36
|
+
├── env.ts # bod env list|set|unset (set supports -f .env)
|
|
37
|
+
├── open.ts # bod open <app>
|
|
38
|
+
├── add.ts # bod add <pkg>
|
|
39
|
+
└── remove.ts # bod remove <pkg>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Key Patterns
|
|
43
|
+
|
|
44
|
+
- Config supports env var references: `$VAR` or `env:VAR`
|
|
45
|
+
- Client auto-adds Bearer auth from config
|
|
46
|
+
- Commands use citty `defineCommand` with `args` and `run`
|
|
47
|
+
- First-run redirects to `bod login`
|
|
48
|
+
- Global `--instance` flag / `BOD_INSTANCE` env var for multi-instance
|
|
49
|
+
- `resolveAppId` in `utils/resolve.ts` — shared name→ID lookup
|
|
50
|
+
- Templates use proper CaaB Resource convention from bodify scaffolding docs
|