@groundfloorcloud/cli 0.1.0 → 0.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.
Files changed (3) hide show
  1. package/README.md +137 -114
  2. package/dist/index.js +1090 -30
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -1,15 +1,14 @@
1
1
  # `@groundfloorcloud/cli` (`gf`)
2
2
 
3
- A small, Vercel/`gh`-style CLI to log a developer into the Groundfloor
4
- Control Plane and reuse that session while building locally (in Cursor,
5
- scripts, or any app). It works like `vercel login`: run `gf login` once, the
6
- browser opens, you sign in, and the session is cached and auto-refreshed.
3
+ Sign in to Groundfloor, manage workspaces, and work with Coderunner,
4
+ secrets, files, apps, and Dataplane from your terminal.
7
5
 
8
- The Control Plane never issues its own login tokens it validates identity
9
- provider Bearer JWTs. So `gf` obtains tokens from Groundfloor's managed IdP
10
- (OAuth 2.0 Authorization Code + PKCE) and hands you a valid
11
- `Authorization: Bearer ...` token for CP and Coderunner APIs. Your Portal user
12
- is created just-in-time on the first call.
6
+ `gf login` opens a browser, you sign in, and the session is cached and
7
+ refreshed automatically.
8
+
9
+ Agents in Cursor use [`@groundfloorcloud/mcp`](../mcp/README.md) against the
10
+ same `gf login` session to inspect the workspace and docs, then run `gf`
11
+ commands to take action.
13
12
 
14
13
  ## Install
15
14
 
@@ -18,85 +17,66 @@ npm i -g @groundfloorcloud/cli
18
17
  gf login
19
18
  ```
20
19
 
21
- Or without a global install:
20
+ Without a global install:
22
21
 
23
22
  ```bash
24
23
  npx @groundfloorcloud/cli login
25
24
  ```
26
25
 
27
- ### From this monorepo
28
-
29
- ```bash
30
- npm install
31
- npm run build --workspace=@groundfloorcloud/cli
32
- npm link --workspace=@groundfloorcloud/cli # then: gf --help
33
- ```
26
+ Requires Node.js 20 or later. `gf login` signs in to production
27
+ (`https://platform.groundfloor.cloud`). Use `--dev` or `--stage` for
28
+ other cells; later commands reuse that session.
34
29
 
35
30
  ## Quick start
36
31
 
37
32
  ```bash
38
- gf login # browser sign-in, caches ~/.groundfloor/auth.json
39
- gf whoami # shows identity and verifies CP accepts the token
40
- gf workspaces # list your workspaces
41
- gf workspaces use <uuid> # set a default workspace
42
- gf coderunner ls # list coderunners in the default workspace
33
+ gf login # production
34
+ gf login --stage
35
+ gf login --dev
36
+ gf whoami
37
+ gf workspaces
38
+ gf workspaces use <uuid>
39
+ gf coderunner ls
40
+ gf deploy
43
41
  ```
44
42
 
45
- Use the session from any local app or shell:
43
+ Use the session from a shell or script:
46
44
 
47
45
  ```bash
48
- eval "$(gf env)" # exports GROUNDFLOOR_TOKEN, CONTROLPLANE_URL, ...
46
+ eval "$(gf env)"
49
47
  curl -H "Authorization: Bearer $(gf token)" \
50
- "$CONTROLPLANE_URL/v1/workspaces" | jq .
48
+ "$CONTROLPLANE_URL/v1/workspaces"
51
49
  ```
52
50
 
53
- In Cursor, run `gf login` once, then `gf token` / `gf env` whenever you (or an
54
- agent) need a fresh token to call CP APIs during development.
51
+ ## Deploy workloads
55
52
 
56
- ## Deploying a coderunner (D-061)
53
+ `gf deploy` packages your code and runs the full Coderunner lifecycle:
54
+ create if needed, upload a version, wait for the build, deploy, poll until
55
+ complete, and print IDs and the URL.
57
56
 
58
- **Coderunner is the deploy path.** Do not create an App to run functions/jobs/services
59
- `POST …/apps` with `app_kind=coderunner` is rejected. Use `gf deploy`, Control Plane
60
- `/coderunners` APIs, or the `@groundfloor/coderunner-mcp` MCP server.
61
-
62
- `gf deploy` packages your code and runs the full lifecycle: create the
63
- coderunner if it does not exist, upload a new version, wait for the build,
64
- deploy, **poll deployment until Completed**, and print IDs/URL.
57
+ Do not create an App just to run a function, job, schedule, or service.
58
+ Use `gf deploy`. Bind `--app-id` only when the coderunner should be a helper
59
+ of an existing product App.
65
60
 
66
61
  ```bash
67
- # Deploy the current folder (zips the working tree, honoring .gitignore)
68
62
  gf deploy
69
-
70
- # Deploy a remote git/bitbucket repo (upload description includes git_sha=…)
71
63
  gf deploy --git https://github.com/me/my-fn.git --ref main
72
-
73
- # Override target + resources + env
74
64
  gf deploy --name my-fn --runtime python --cpu 250m --memory 256Mi \
75
- -e API_KEY=secret -e STAGE=dev
76
-
77
- # Bind a newly created coderunner as a helper of an App (optional)
65
+ -e API_KEY=secret
78
66
  gf deploy --app-id <app-uuid>
79
67
  ```
80
68
 
81
- **Server push-to-deploy:** connect a repo on the coderunner **Git source** card
82
- (or `PUT …/coderunners/{id}/git-source`). Point GitHub/Gitea at
83
- `POST /v1/webhooks/git/{source_id}` with the returned webhook secret. Private
84
- repos use a workspace Secret named in `secret_key`. App creation is not required.
85
-
86
69
  How the target is chosen:
87
70
 
88
- - `--coderunner <id>` deploys into that exact coderunner.
71
+ - `--coderunner <id>` deploys into that coderunner.
89
72
  - Otherwise the name comes from `--name`, then `groundfloor.json`, then the
90
- folder/repo name; its slug is matched against existing coderunners. A match is
91
- reused; otherwise a new coderunner is created (optionally with `--app-id`).
73
+ folder or repo name. A matching slug is reused; otherwise a new coderunner
74
+ is created.
92
75
 
93
- Runtime is auto-detected when not given (`package.json` -> node,
94
- `requirements.txt`/`pyproject.toml` -> python), defaulting to python.
76
+ Runtime is auto-detected when omitted (`package.json` node,
77
+ `requirements.txt` / `pyproject.toml` python), defaulting to python.
95
78
 
96
- ### Optional `groundfloor.json`
97
-
98
- Drop a `groundfloor.json` in your project root to set defaults (CLI flags still
99
- win):
79
+ ### `groundfloor.json`
100
80
 
101
81
  ```json
102
82
  {
@@ -109,13 +89,13 @@ win):
109
89
  }
110
90
  ```
111
91
 
112
- ### Useful flags
92
+ ### Deploy flags
113
93
 
114
94
  | Flag | Description |
115
95
  |------|-------------|
116
- | `-w, --workspace <id>` | Workspace override (else the default from `gf workspaces use`). |
117
- | `-p, --path <dir>` | Local directory to package (default: cwd). |
118
- | `--git <url>` / `--ref <ref>` | Clone and deploy a remote repo at a branch/tag/commit. |
96
+ | `-w, --workspace <id>` | Workspace override (else `gf workspaces use`). |
97
+ | `-p, --path <dir>` | Directory to package (default: cwd). |
98
+ | `--git <url>` / `--ref <ref>` | Clone and deploy a remote repo. |
119
99
  | `--subdir <dir>` | Package a subdirectory of the source. |
120
100
  | `--runtime <r>` | `python` \| `node` \| `dotnet-script`. |
121
101
  | `--workload-type <t>` | `function` \| `service` \| `job` \| `schedule`. |
@@ -124,36 +104,100 @@ win):
124
104
  | `-m, --message <text>` | Version description. |
125
105
  | `--skip-deploy` | Upload a new version but do not deploy it. |
126
106
 
107
+ ## Publish a Shell app
108
+
109
+ Product **Apps** are packaging (Shell Module Federation remotes, or a
110
+ standalone wrapper around a service). That is separate from `gf deploy`.
111
+
112
+ **Always start from the official starter-kit.** Do not scaffold `App.tsx` or
113
+ put `BrowserRouter` in the federated export — that crashes the Shell.
114
+
115
+ ```bash
116
+ gf apps init --slug my-federated-app
117
+ cd my-federated-app
118
+ gf apps create --name "My Federated App" --slug my-federated-app \
119
+ --manifest ./groundfloor.manifest.json
120
+ npm install
121
+ npm run release
122
+ gf apps publish --path release.zip
123
+ ```
124
+
125
+ `gf apps init` downloads the public ZIP from the Customer Portal
126
+ (`/downloads/shell-starter-kit.zip` on the current cell) and stamps
127
+ `APP_ID` / `groundfloor.manifest.json` `appId` to the slug.
128
+
129
+ `gf apps publish` uploads `release.zip` (or `remoteEntry.js`), flattens a
130
+ Vite `dist/assets/` layout so chunks sit next to `remoteEntry.js`, finalizes
131
+ the release, and by default PATCHes the Portal manifest from
132
+ `groundfloor.manifest.json` next to the bundle. Pass an app id/slug, or set
133
+ `appId` in that manifest. Prefer `npm run release` over zipping `dist/` by hand.
134
+
135
+ Wrap an existing **service** coderunner as a product:
136
+
137
+ ```bash
138
+ gf apps create --kind standalone --name "My Product" --slug my-product \
139
+ --primary-coderunner <coderunner-id>
140
+ ```
141
+
142
+ Do not create `app_kind=coderunner`. Functions, jobs, schedules, and services
143
+ use `gf deploy`.
144
+
145
+ ## Secrets, files, Dataplane
146
+
147
+ ```bash
148
+ gf dataplane status
149
+ gf dataplane provision
150
+
151
+ gf secrets ls
152
+ gf secrets set DATABASE_URL 'postgres://…'
153
+ gf secrets get DATABASE_URL
154
+ gf secrets rm DATABASE_URL
155
+
156
+ gf files ls
157
+ gf files upload ./report.pdf
158
+ gf files download <file-id> -o ./report.pdf
159
+ gf files rm <file-id>
160
+
161
+ gf apps ls
162
+ gf apps get <id|slug>
163
+ ```
164
+
127
165
  ## Commands
128
166
 
129
167
  | Command | Description |
130
168
  |---------|-------------|
131
- | `gf login [--device]` | Browser PKCE login (or device-code flow with `--device`). |
169
+ | `gf login [--dev\|--stage] [--device]` | Browser sign-in (production default). |
132
170
  | `gf logout` | Clear the cached session. |
133
- | `gf whoami` | Show identity and verify the CP session end-to-end. |
134
- | `gf token` | Print a fresh (auto-refreshed) access token to stdout. |
135
- | `gf env` | Print `export ...` lines for `eval "$(gf env)"`. |
171
+ | `gf whoami` | Show identity and verify the Control Plane session. |
172
+ | `gf token` | Print a fresh access token. |
173
+ | `gf env` | Print `export …` lines for `eval "$(gf env)"`. |
136
174
  | `gf workspaces` (`ws`) | List workspaces; `gf workspaces use <id>` sets the default. |
137
- | `gf coderunner ls` (`cr ls`) | List coderunners in the default (or `--workspace`) workspace. |
138
- | `gf coderunner status -c <id\|slug>` | Status + current deployment JSON. |
139
- | `gf coderunner run -c <id\|slug> [--payload '{}']` | Smoke invoke a deployed function/job. |
140
- | `gf deploy` | Package code (local folder or `--git` repo) and deploy it as a coderunner. |
141
-
142
- ### MCP (agents)
143
-
144
- See [`packages/coderunner-mcp/README.md`](../coderunner-mcp/README.md) and
145
- [`docs/plans/apps-and-coderunner.md`](../../docs/plans/apps-and-coderunner.md) Phase 1.
175
+ | `gf coderunner ls` (`cr ls`) | List coderunners. |
176
+ | `gf coderunner status -c <id\|slug>` | Status and current deployment. |
177
+ | `gf coderunner run -c <id\|slug> [--payload '{}']` | Invoke a deployed function or job. |
178
+ | `gf deploy` | Package code and deploy as a coderunner. |
179
+ | `gf domains ls\|add\|rm\|verify -c <id\|slug>` | Custom domains for a service. |
180
+ | `gf secrets ls\|get\|set\|rm` | Workspace secrets. |
181
+ | `gf files ls\|upload\|download\|rm` | Workspace files. |
182
+ | `gf apps init --slug <slug>` | Download the official Shell starter-kit and stamp APP_ID. |
183
+ | `gf apps ls\|get\|create\|publish` | Product apps (Shell publish / standalone wrap). |
184
+ | `gf dataplane status\|provision` | Dataplane setup for the workspace. |
146
185
 
147
186
  ## Configuration
148
187
 
149
- Settings resolve with precedence: command flags > environment > config file >
150
- built-in dev defaults.
188
+ Settings resolve as: command flags > environment > `~/.groundfloor/config.json`
189
+ > Groundfloor production.
151
190
 
152
- | Setting | Flag | Env | Default |
153
- |---------|------|-----|---------|
154
- | IdP issuer | `--issuer` | `GROUNDFLOOR_ISSUER` | `https://auth.dev.groundfloor.cloud/realms/groundfloor_dev` |
191
+ `gf login` with no cell flag **always** uses production, even if a previous
192
+ `--dev` / `--stage` session is still in `config.json`. Pass `--dev`, `--stage`,
193
+ or `--env <production|stage|dev>` to pick another cell. `--api-url` / `--issuer`
194
+ still override the hosts for that login.
195
+
196
+ | Setting | Flag | Env | Production default |
197
+ |---------|------|-----|--------------------|
198
+ | Control Plane URL | `--api-url` | `GROUNDFLOOR_API_URL` | `https://platform.groundfloor.cloud` |
199
+ | IdP issuer | `--issuer` | `GROUNDFLOOR_ISSUER` | Groundfloor managed IdP |
155
200
  | OIDC client id | `--client-id` | `GROUNDFLOOR_CLIENT_ID` | `groundfloor-cli` |
156
- | Control Plane URL | `--api-url` | `GROUNDFLOOR_API_URL` | `http://localhost:8088` |
157
201
  | Default workspace | (via `gf workspaces use`) | `GROUNDFLOOR_WORKSPACE_ID` | (none) |
158
202
 
159
203
  State is stored under `~/.groundfloor/`:
@@ -161,41 +205,20 @@ State is stored under `~/.groundfloor/`:
161
205
  - `auth.json` — cached tokens (chmod `600`).
162
206
  - `config.json` — non-secret defaults (issuer, client id, api url, workspace).
163
207
 
164
- `gf login --issuer ... --client-id ... --api-url ...` persists those values so
165
- later commands match the login.
166
-
167
- ## Identity provider setup (one-time)
168
-
169
- `gf` needs a **public** OIDC client (default id `groundfloor-cli`) with:
170
-
171
- - Standard Flow enabled, PKCE method `S256`.
172
- - Valid redirect URIs covering the loopback callback. The CLI redirects to
173
- `http://127.0.0.1:<port>/callback`, so configure **both**:
174
- - `http://127.0.0.1/*`
175
- - `http://localhost/*`
176
- - Optionally, OAuth 2.0 Device Authorization Grant enabled for `gf login --device`.
177
-
178
- Then add the client id to the Control Plane `KEYCLOAK_AUDIENCE`
179
- (see `.env.example`) so its tokens verify. The CLI user still needs workspace
180
- membership in the Portal for workspace-scoped routes.
181
-
182
- ### Redirect URI mismatch ("Invalid parameter: redirect_uri")
183
-
184
- This means the client's Valid Redirect URIs do not match the loopback URL the
185
- CLI sends. Options:
208
+ ### Redirect URI mismatch
186
209
 
187
- - Ensure the client lists `http://127.0.0.1/*` (the CLI defaults to `127.0.0.1`).
188
- - If your IdP only matches `localhost`, run `gf login --redirect-host localhost`.
189
- - If wildcard/port matching is restrictive, pin an exact URI: register
190
- `http://127.0.0.1:8976/callback` on the client and run
191
- `gf login --redirect-port 8976`.
210
+ `gf login` uses a loopback callback (`http://127.0.0.1:<port>/callback`). If
211
+ sign-in fails with an invalid redirect URI:
192
212
 
193
- ## Scope
213
+ - Prefer `127.0.0.1` (the CLI default).
214
+ - If your identity provider only allows `localhost`, run
215
+ `gf login --redirect-host localhost`.
216
+ - To pin a port: `gf login --redirect-port 8976`.
194
217
 
195
- - Phase 1: authenticated developer session (`gf login` + token reuse).
196
- - Phase 2: `gf deploy` for local folders and remote git/bitbucket repos. The CLI
197
- packages the code into a ZIP and drives the Control Plane create -> upload ->
198
- build -> deploy lifecycle (upstream Code Runner is ZIP-based).
218
+ ## More
199
219
 
200
- Server-side push-to-deploy (Control Plane pulling from git via webhooks) is a
201
- possible future enhancement and is not part of this CLI.
220
+ - [Customer Portal](https://app.groundfloor.cloud)
221
+ - [Developers](https://docs.groundfloor.cloud/docs/customer-portal/developers)
222
+ - [Deploy with agents](https://docs.groundfloor.cloud/docs/customer-portal/agents)
223
+ - [Coderunner](https://docs.groundfloor.cloud/docs/customer-portal/coderunner)
224
+ - [API authentication](https://docs.groundfloor.cloud/docs/api/authentication)