catence 0.2.0-beta.10 → 0.2.0-beta.11
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/README.md +21 -217
- package/dist/contracts/release.d.ts +1 -1
- package/dist/contracts/release.js +1 -1
- package/dist/core/query/repository.js +5 -1
- package/dist/elt/application/management.js +32 -7
- package/dist/elt/storage/progress-sidecar.d.ts +26 -0
- package/dist/elt/storage/progress-sidecar.js +87 -0
- package/docs/architecture.md +11 -1
- package/docs/configuration.md +221 -0
- package/docs/deployment/docker.md +528 -0
- package/docs/deployment/local-console.md +230 -0
- package/docs/deployment/local-mcp.md +304 -0
- package/docs/distribution.md +58 -0
- package/docs/mcp-activity-retrieval.md +37 -30
- package/package.json +1 -1
- package/docs/deployment.md +0 -338
- package/docs/docker-deployment.md +0 -232
package/package.json
CHANGED
package/docs/deployment.md
DELETED
|
@@ -1,338 +0,0 @@
|
|
|
1
|
-
# Deploying Catence Console
|
|
2
|
-
|
|
3
|
-
Catence Console is a password-protected local web chat that starts a matching
|
|
4
|
-
Catence runtime on loopback. There are two supported ways to run it: **locally**
|
|
5
|
-
(npm package + Python Console on your machine) or **in Docker** (one container
|
|
6
|
-
built from the public registries). Both paths end with the same Console, data
|
|
7
|
-
directory layout, model configuration, and credentials model.
|
|
8
|
-
|
|
9
|
-
Everything below assumes a recent beta or stable release; channels are
|
|
10
|
-
explained in the [beta release notes](../README.md#beta-releases).
|
|
11
|
-
|
|
12
|
-
## Prerequisites
|
|
13
|
-
|
|
14
|
-
- Node.js 22+ and Python 3.12+ with [uv](https://docs.astral.sh/uv/)
|
|
15
|
-
(local path), or Docker Engine with the `docker compose` plugin (Docker path).
|
|
16
|
-
- Provider credentials for the athletes you choose to sync (Garmin,
|
|
17
|
-
Intervals.icu, Strava).
|
|
18
|
-
- One model-provider key (OpenAI, Anthropic, OpenCode Go, Azure, or any
|
|
19
|
-
OpenAI-compatible endpoint).
|
|
20
|
-
|
|
21
|
-
## What gets stored where
|
|
22
|
-
|
|
23
|
-
| What | Where | Example |
|
|
24
|
-
| --- | --- | --- |
|
|
25
|
-
| Catalog + athlete stores | data home | `~/.catence/` or `/data` in Docker |
|
|
26
|
-
| Model profiles (no secrets) | `config.json` in the data home | `console.profiles` |
|
|
27
|
-
| Provider credentials | per-athlete secret file, mode 0600 | `catence-data secret set` |
|
|
28
|
-
| API keys | process environment only | `.env` in Docker, shell exports locally |
|
|
29
|
-
| Chat history + preferences | data home | `console/chat-history.sqlite3` |
|
|
30
|
-
|
|
31
|
-
Credentials never land in `config.json`; profiles reference environment
|
|
32
|
-
variable *names* (`apiKeyEnv`, `apiBaseEnv`, `apiVersionEnv`). See
|
|
33
|
-
[`llm-providers.md`](llm-providers.md) for the profile reference and
|
|
34
|
-
[`config.example.json`](../config.example.json) for a complete example.
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## Path A — Local deployment
|
|
39
|
-
|
|
40
|
-
### 1. Install the runtime and the Console
|
|
41
|
-
|
|
42
|
-
```sh
|
|
43
|
-
npm install --global catence@beta # or catence@latest for stable
|
|
44
|
-
uv tool install catence-console # persistent `catence-console` command
|
|
45
|
-
# alternative to the last line: uvx catence-console@<version> serve (ephemeral)
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
`catence-console serve` launches a matching Catence runtime automatically: it
|
|
49
|
-
uses a globally installed `catence` if present, otherwise `npx catence@<pinned>`.
|
|
50
|
-
|
|
51
|
-
### 2. Create the catalog and first athlete
|
|
52
|
-
|
|
53
|
-
```sh
|
|
54
|
-
catence-data setup --athlete alex --label "Alex"
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
This creates `~/.catence/` (or `$CATENCE_HOME`). It also tolerates a directory
|
|
58
|
-
that already holds only Console artifacts (`config.json`, `console/`).
|
|
59
|
-
|
|
60
|
-
### 3. Store provider credentials (stdin only, never shell history)
|
|
61
|
-
|
|
62
|
-
Garmin (`email`, `password`), Intervals.icu (`apiKey`, `athleteId`), and Strava
|
|
63
|
-
(`clientId`, `clientSecret`):
|
|
64
|
-
|
|
65
|
-
```sh
|
|
66
|
-
# Garmin
|
|
67
|
-
printf %s 'alex@example.com' | catence-data --athlete alex secret set --provider garmin --field email --value-stdin
|
|
68
|
-
printf %s 'your-garmin-password' | catence-data --athlete alex secret set --provider garmin --field password --value-stdin
|
|
69
|
-
# Intervals.icu
|
|
70
|
-
printf %s 'intervals-api-key' | catence-data --athlete alex secret set --provider intervals --field apiKey --value-stdin
|
|
71
|
-
printf %s '12345' | catence-data --athlete alex secret set --provider intervals --field athleteId --value-stdin
|
|
72
|
-
# Strava (create an API application at https://www.strava.com/settings/api)
|
|
73
|
-
printf %s 'strava-client-id' | catence-data --athlete alex secret set --provider strava --field clientId --value-stdin
|
|
74
|
-
printf %s 'strava-client-secret' | catence-data --athlete alex secret set --provider strava --field clientSecret --value-stdin
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
Set only the providers you actually sync; `secret set` accepts each field
|
|
78
|
-
independently.
|
|
79
|
-
|
|
80
|
-
### 4. Sync data and build retrieval context
|
|
81
|
-
|
|
82
|
-
```sh
|
|
83
|
-
catence-data --athlete alex sync --provider all
|
|
84
|
-
catence-data --athlete alex build-retrieval-index
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### 5. Configure the model
|
|
88
|
-
|
|
89
|
-
On the first chat, the Console wizard asks for a provider and model and writes
|
|
90
|
-
a starter profile. To start from the documented profiles instead, copy the
|
|
91
|
-
`console` section from [`config.example.json`](../config.example.json) into
|
|
92
|
-
`~/.catence/config.json`. To add OpenCode Go models, run the
|
|
93
|
-
[model discovery script](#model-discovery-opencode-go) below.
|
|
94
|
-
|
|
95
|
-
### 6. Set the model credentials and Console login
|
|
96
|
-
|
|
97
|
-
```sh
|
|
98
|
-
export OPENAI_API_KEY='…' # or ANTHROPIC_API_KEY / OPENCODE_GO_API_KEY …
|
|
99
|
-
export CATENCE_CONSOLE_USERNAME='coach'
|
|
100
|
-
export CATENCE_CONSOLE_PASSWORD_HASH="$(catence-console auth hash-password)"
|
|
101
|
-
export CHAINLIT_AUTH_SECRET="$(openssl rand -hex 32)"
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### 7. Start the Console
|
|
105
|
-
|
|
106
|
-
```sh
|
|
107
|
-
catence-console serve
|
|
108
|
-
# open http://127.0.0.1:8000
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
The Model dropdown in the settings panel lists every profile's deployments.
|
|
112
|
-
Preflight with:
|
|
113
|
-
|
|
114
|
-
```sh
|
|
115
|
-
catence-console doctor
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
---
|
|
119
|
-
|
|
120
|
-
## Path B — Docker deployment
|
|
121
|
-
|
|
122
|
-
### 1. Deploy with the script
|
|
123
|
-
|
|
124
|
-
```sh
|
|
125
|
-
curl -fsSL https://raw.githubusercontent.com/rifusaki/catence/beta/scripts/deploy-console.sh | bash -s beta
|
|
126
|
-
# or from a checkout: ./scripts/deploy-console.sh beta
|
|
127
|
-
# use `stable` instead of `beta` for the stable channel
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
The script resolves the newest matching versions from npm and PyPI, writes a
|
|
131
|
-
self-contained `catence-deploy/` project (Dockerfile, docker-compose.yml, and
|
|
132
|
-
`.env` with placeholders), builds the image, **seeds a starter
|
|
133
|
-
`/data/config.json`** into the data volume, and starts the stack — or, when
|
|
134
|
-
secrets are missing, prints the remaining steps and exits.
|
|
135
|
-
|
|
136
|
-
### 2. Fill in `catence-deploy/.env`
|
|
137
|
-
|
|
138
|
-
```sh
|
|
139
|
-
CATENCE_CONSOLE_USERNAME=coach
|
|
140
|
-
CATENCE_CONSOLE_PASSWORD_HASH='…' # generate: ./catence-deploy/hash-password.sh
|
|
141
|
-
CHAINLIT_AUTH_SECRET='…' # generate: openssl rand -hex 32
|
|
142
|
-
OPENAI_API_KEY='…' # or ANTHROPIC_API_KEY / OPENCODE_GO_API_KEY …
|
|
143
|
-
OPENAI_API_BASE='' # only for OpenAI-compatible endpoints
|
|
144
|
-
OPENCODE_GO_API_KEY='…' # the OpenCode Go base URLs are pre-filled below
|
|
145
|
-
OPENCODE_GO_API_BASE='https://opencode.ai/zen/go/v1'
|
|
146
|
-
OPENCODE_GO_MESSAGES_API_BASE='https://opencode.ai/zen/go'
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
Then start the stack (or re-run the script, which re-reads the saved `.env`):
|
|
150
|
-
|
|
151
|
-
```sh
|
|
152
|
-
docker compose -f catence-deploy/docker-compose.yml --env-file catence-deploy/.env up -d
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
### 3. Initialize an athlete store
|
|
156
|
-
|
|
157
|
-
The data volume already contains a seeded `config.json`, so `setup` accepts
|
|
158
|
-
it. Run through the container:
|
|
159
|
-
|
|
160
|
-
```sh
|
|
161
|
-
docker compose -f catence-deploy/docker-compose.yml --env-file catence-deploy/.env run --rm \
|
|
162
|
-
--entrypoint catence-data console setup --athlete alex --label "Alex"
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
### 4. Store provider credentials
|
|
166
|
-
|
|
167
|
-
Garmin (`email`, `password`), Intervals.icu (`apiKey`, `athleteId`), and Strava
|
|
168
|
-
(`clientId`, `clientSecret`), one `printf` per field:
|
|
169
|
-
|
|
170
|
-
```sh
|
|
171
|
-
# Garmin
|
|
172
|
-
printf %s 'alex@example.com' | docker compose -f catence-deploy/docker-compose.yml --env-file catence-deploy/.env run --rm -T \
|
|
173
|
-
--entrypoint catence-data console --athlete alex secret set \
|
|
174
|
-
--provider garmin --field email --value-stdin
|
|
175
|
-
printf %s 'your-garmin-password' | docker compose -f catence-deploy/docker-compose.yml --env-file catence-deploy/.env run --rm -T \
|
|
176
|
-
--entrypoint catence-data console --athlete alex secret set \
|
|
177
|
-
--provider garmin --field password --value-stdin
|
|
178
|
-
# Intervals.icu
|
|
179
|
-
printf %s 'intervals-api-key' | docker compose -f catence-deploy/docker-compose.yml --env-file catence-deploy/.env run --rm -T \
|
|
180
|
-
--entrypoint catence-data console --athlete alex secret set \
|
|
181
|
-
--provider intervals --field apiKey --value-stdin
|
|
182
|
-
printf %s '12345' | docker compose -f catence-deploy/docker-compose.yml --env-file catence-deploy/.env run --rm -T \
|
|
183
|
-
--entrypoint catence-data console --athlete alex secret set \
|
|
184
|
-
--provider intervals --field athleteId --value-stdin
|
|
185
|
-
# Strava (create an API application at https://www.strava.com/settings/api)
|
|
186
|
-
printf %s 'strava-client-id' | docker compose -f catence-deploy/docker-compose.yml --env-file catence-deploy/.env run --rm -T \
|
|
187
|
-
--entrypoint catence-data console --athlete alex secret set \
|
|
188
|
-
--provider strava --field clientId --value-stdin
|
|
189
|
-
printf %s 'strava-client-secret' | docker compose -f catence-deploy/docker-compose.yml --env-file catence-deploy/.env run --rm -T \
|
|
190
|
-
--entrypoint catence-data console --athlete alex secret set \
|
|
191
|
-
--provider strava --field clientSecret --value-stdin
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
Set only the providers you actually sync. Use the same `--entrypoint
|
|
195
|
-
catence-data` pattern for `sync`, `backfill`, and `auth strava`.
|
|
196
|
-
|
|
197
|
-
### 5. Configure the model
|
|
198
|
-
|
|
199
|
-
The seeded `config.json` already offers OpenAI, OpenAI-compatible, and
|
|
200
|
-
Anthropic starter profiles, so the settings panel works before the first chat.
|
|
201
|
-
Edit `/data/config.json` inside the volume:
|
|
202
|
-
|
|
203
|
-
```sh
|
|
204
|
-
docker compose -f catence-deploy/docker-compose.yml --env-file catence-deploy/.env run --rm \
|
|
205
|
-
--entrypoint sh console -c 'cat > /data/config.json' # paste JSON, then Ctrl-D
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
With `--home <dir>` (bind mount), edit `<dir>/config.json` on the host
|
|
209
|
-
instead. To add OpenCode Go models, see [model discovery](#model-discovery-opencode-go).
|
|
210
|
-
|
|
211
|
-
### 6. Verify with doctor
|
|
212
|
-
|
|
213
|
-
`catence-console doctor` checks each profile's environment variables and the
|
|
214
|
-
local Catence runtime. The deploy scaffold includes a helper for it:
|
|
215
|
-
|
|
216
|
-
```sh
|
|
217
|
-
./catence-deploy/doctor.sh
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
The helper runs the doctor *inside the running container* with `exec` — the
|
|
221
|
-
container's own loopback holds the live MCP server at `127.0.0.1:8787`, and the
|
|
222
|
-
provider keys from `.env` are already in its environment. (A `docker compose
|
|
223
|
-
run` container has a separate loopback and would report the runtime as
|
|
224
|
-
unreachable.) The equivalent long form is:
|
|
225
|
-
|
|
226
|
-
```sh
|
|
227
|
-
docker compose -f catence-deploy/docker-compose.yml --env-file catence-deploy/.env exec console \
|
|
228
|
-
/opt/catence-console/bin/catence-console doctor --home /data --mcp-url http://127.0.0.1:8787/mcp
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
Expect `"ready": true` once the model key is set; missing keys show up per
|
|
232
|
-
profile without ever printing their values.
|
|
233
|
-
|
|
234
|
-
### 7. Sync, backfill, and inspect athlete data
|
|
235
|
-
|
|
236
|
-
The deploy scaffold includes a helper that runs `catence-data` *inside the
|
|
237
|
-
running container* with `exec`, so the athlete's provider secrets from the
|
|
238
|
-
data volume are already available:
|
|
239
|
-
|
|
240
|
-
```sh
|
|
241
|
-
./catence-deploy/sync.sh --athlete alex sync # incremental sync, all providers
|
|
242
|
-
./catence-deploy/sync.sh --athlete alex backfill 2026-01-01 # full backfill from a date
|
|
243
|
-
./catence-deploy/sync.sh --athlete alex status # coverage and errors
|
|
244
|
-
./catence-deploy/sync.sh athletes # list athlete IDs
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
`sync` defaults to `--provider all`; extra flags pass through, for example
|
|
248
|
-
`./catence-deploy/sync.sh --athlete alex sync --refresh` or
|
|
249
|
-
`./catence-deploy/sync.sh --athlete alex backfill 2026-01-01 --provider garmin`.
|
|
250
|
-
Set a default athlete with `export CATENCE_ATHLETE=alex` to drop the
|
|
251
|
-
`--athlete` argument. The equivalent long form is:
|
|
252
|
-
|
|
253
|
-
```sh
|
|
254
|
-
docker compose -f catence-deploy/docker-compose.yml --env-file catence-deploy/.env exec console \
|
|
255
|
-
catence-data sync --athlete alex --provider all --home /data
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
### 8. Expose the Console safely
|
|
259
|
-
|
|
260
|
-
Keep the Console port bound to `127.0.0.1` (the default) and front it with a
|
|
261
|
-
Cloudflare Tunnel or reverse proxy at HTTPS. Never expose Catence's MCP port
|
|
262
|
-
8787 — it stays loopback-only inside the container. For remote MCP checks use
|
|
263
|
-
SSH port forwarding (`ssh -L 8787:127.0.0.1:8787 server`).
|
|
264
|
-
|
|
265
|
-
---
|
|
266
|
-
|
|
267
|
-
## Model discovery (OpenCode Go)
|
|
268
|
-
|
|
269
|
-
OpenCode Go publishes an OpenAI-compatible API at
|
|
270
|
-
`https://opencode.ai/zen/go/v1`; its model list is public. The discovery
|
|
271
|
-
script fetches it and merges two ready-made profiles into `config.json`:
|
|
272
|
-
`opencode-go` (chat + responses models, base `…/zen/go/v1`) and
|
|
273
|
-
`opencode-go-messages` (messages models, base `…/zen/go`). Existing profiles,
|
|
274
|
-
limits, and `defaultProfile` are preserved unless `--set-default` is passed.
|
|
275
|
-
|
|
276
|
-
```sh
|
|
277
|
-
# Local (from a checkout)
|
|
278
|
-
npm run discover:opencode-go -- --write ~/.catence/config.json
|
|
279
|
-
|
|
280
|
-
# Docker (the script ships inside the npm package in the image)
|
|
281
|
-
docker compose -f catence-deploy/docker-compose.yml --env-file catence-deploy/.env run --rm \
|
|
282
|
-
--entrypoint node console \
|
|
283
|
-
/usr/local/lib/node_modules/catence/scripts/discover-opencode-go.mjs --write /data/config.json
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
Then set the credentials and verify. The generated `.env` already contains
|
|
287
|
-
`OPENCODE_GO_API_BASE` and `OPENCODE_GO_MESSAGES_API_BASE`, so on Docker only
|
|
288
|
-
the key is missing:
|
|
289
|
-
|
|
290
|
-
```sh
|
|
291
|
-
export OPENCODE_GO_API_KEY='…' # any non-empty value passes the key check
|
|
292
|
-
catence-console doctor
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
The `openai/responses/…` models (for example `grok-4.5`) go through LiteLLM's
|
|
296
|
-
responses bridge and are the least battle-tested path; smoke-test one chat turn
|
|
297
|
-
before relying on them.
|
|
298
|
-
|
|
299
|
-
---
|
|
300
|
-
|
|
301
|
-
## Updating
|
|
302
|
-
|
|
303
|
-
From `catence-data update`-capable releases (0.2.0-beta.3 and later), the
|
|
304
|
-
runtime updates both components on the tracked channel — beta installs follow
|
|
305
|
-
the npm `beta` tag and matching PyPI prereleases:
|
|
306
|
-
|
|
307
|
-
```sh
|
|
308
|
-
catence-data update --check # report only; exit 1 when updates are pending
|
|
309
|
-
catence-data update # npm runtime + uv tool catence-console upgrade
|
|
310
|
-
catence-data update --channel stable # move off a beta onto the stable channel
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
Older betas (for example a beta 2 install) predate the command; upgrade them
|
|
314
|
-
manually once:
|
|
315
|
-
|
|
316
|
-
```sh
|
|
317
|
-
npm install --global catence@beta
|
|
318
|
-
uv tool install --upgrade catence-console
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
Docker deployments: re-run `deploy-console.sh beta` (or `stable`); it
|
|
322
|
-
re-resolves the newest versions from the registries and rebuilds. The data
|
|
323
|
-
volume and your `config.json` are preserved.
|
|
324
|
-
|
|
325
|
-
## Troubleshooting
|
|
326
|
-
|
|
327
|
-
- **"No Catence config exists"** — should not happen after a seeded deploy or
|
|
328
|
-
wizard run; ensure `/data/config.json` (Docker) or `~/.catence/config.json`
|
|
329
|
-
exists and contains a `console` section.
|
|
330
|
-
- **"Refusing to initialize"** — the data home contains unrelated files; the
|
|
331
|
-
error lists them. Console artifacts (`config.json`, `console/`, and Chainlit's
|
|
332
|
-
`.files/`, `.chainlit/`, `public/`) are allowed; anything else blocks `setup`.
|
|
333
|
-
- **Settings panel has no Model dropdown** — the Console loads profiles from
|
|
334
|
-
`config.json`; write one via the wizard, a manual copy, or the discovery
|
|
335
|
-
script.
|
|
336
|
-
- **Profile not ready** — `catence-console doctor` lists the missing
|
|
337
|
-
environment variables; set them in `.env` (Docker) or the shell (local) and
|
|
338
|
-
restart the Console.
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
# Docker Deployment Quick Start and Common Commands
|
|
2
|
-
|
|
3
|
-
This document mirrors the [local quick start](../README.md#quick-start) and [common operations](../README.md#common-operations) for Catence when deployed via Docker. It assumes you have completed the [deployment steps](deployment.md#path-b--docker-deployment) and have a running `catence-deploy` stack.
|
|
4
|
-
|
|
5
|
-
## Quick Start (Docker)
|
|
6
|
-
|
|
7
|
-
All commands run from the `catence-deploy` directory created by the deploy script.
|
|
8
|
-
|
|
9
|
-
### 1. Initialize an athlete store
|
|
10
|
-
|
|
11
|
-
```sh
|
|
12
|
-
docker compose -f docker-compose.yml --env-file .env run --rm \
|
|
13
|
-
--entrypoint catence-data console setup --athlete alex --label "Alex"
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
### 2. Store provider credentials (stdin only, never shell history)
|
|
17
|
-
|
|
18
|
-
```sh
|
|
19
|
-
# Garmin
|
|
20
|
-
printf %s 'alex@example.com' | docker compose -f docker-compose.yml --env-file .env run --rm -T \
|
|
21
|
-
--entrypoint catence-data console --athlete alex secret set \
|
|
22
|
-
--provider garmin --field email --value-stdin
|
|
23
|
-
printf %s 'your-garmin-password' | docker compose -f docker-compose.yml --env-file .env run --rm -T \
|
|
24
|
-
--entrypoint catence-data console --athlete alex secret set \
|
|
25
|
-
--provider garmin --field password --value-stdin
|
|
26
|
-
|
|
27
|
-
# Intervals.icu
|
|
28
|
-
printf %s 'intervals-api-key' | docker compose -f docker-compose.yml --env-file .env run --rm -T \
|
|
29
|
-
--entrypoint catence-data console --athlete alex secret set \
|
|
30
|
-
--provider intervals --field apiKey --value-stdin
|
|
31
|
-
printf %s '12345' | docker compose -f docker-compose.yml --env-file .env run --rm -T \
|
|
32
|
-
--entrypoint catence-data console --athlete alex secret set \
|
|
33
|
-
--provider intervals --field athleteId --value-stdin
|
|
34
|
-
|
|
35
|
-
# Strava (create an API application at https://www.strava.com/settings/api)
|
|
36
|
-
printf %s 'strava-client-id' | docker compose -f docker-compose.yml --env-file .env run --rm -T \
|
|
37
|
-
--entrypoint catence-data console --athlete alex secret set \
|
|
38
|
-
--provider strava --field clientId --value-stdin
|
|
39
|
-
printf %s 'strava-client-secret' | docker compose -f docker-compose.yml --env-file .env run --rm -T \
|
|
40
|
-
--entrypoint catence-data console --athlete alex secret set \
|
|
41
|
-
--provider strava --field clientSecret --value-stdin
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### 3. Sync data and build retrieval context
|
|
45
|
-
|
|
46
|
-
```sh
|
|
47
|
-
docker compose -f docker-compose.yml --env-file .env exec console \
|
|
48
|
-
catence-data sync --athlete alex --provider all --home /data
|
|
49
|
-
docker compose -f docker-compose.yml --env-file .env exec console \
|
|
50
|
-
catence-data build-retrieval-index --athlete alex --home /data
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### 4. Access the Console
|
|
54
|
-
|
|
55
|
-
Open `http://127.0.0.1:8000` (or the `--bind:--port` you configured) and log in with `CATENCE_CONSOLE_USERNAME` and the password whose hash is in `CATENCE_CONSOLE_PASSWORD_HASH`.
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
## Common Operations (Docker)
|
|
60
|
-
|
|
61
|
-
The `sync.sh` helper in `catence-deploy/` wraps the most frequent `catence-data` calls inside the **running** container (so the provider secrets from the data volume are already available).
|
|
62
|
-
|
|
63
|
-
```sh
|
|
64
|
-
# Incremental sync for one athlete (all providers)
|
|
65
|
-
./sync.sh --athlete alex sync
|
|
66
|
-
|
|
67
|
-
# Sync a specific provider
|
|
68
|
-
./sync.sh --athlete alex sync --provider intervals
|
|
69
|
-
|
|
70
|
-
# Sync from a specific date (Garmin)
|
|
71
|
-
./sync.sh --athlete alex sync --provider garmin --from 2025-07-29
|
|
72
|
-
|
|
73
|
-
# Full backfill from a date
|
|
74
|
-
./sync.sh --athlete alex backfill 2026-01-01
|
|
75
|
-
|
|
76
|
-
# Backfill with refresh (re-fetch existing data)
|
|
77
|
-
./sync.sh --athlete alex backfill 2026-01-01 --refresh
|
|
78
|
-
|
|
79
|
-
# Retry a failed sync run
|
|
80
|
-
./sync.sh --athlete alex retry --run <run-id>
|
|
81
|
-
|
|
82
|
-
# Coverage and error status
|
|
83
|
-
./sync.sh --athlete alex status
|
|
84
|
-
|
|
85
|
-
# List athlete IDs in the catalog
|
|
86
|
-
./sync.sh athletes
|
|
87
|
-
|
|
88
|
-
# Strava OAuth (uses clientId/clientSecret stored for this athlete)
|
|
89
|
-
docker compose -f docker-compose.yml --env-file .env exec console \
|
|
90
|
-
catence-data auth strava --athlete alex --callback --home /data
|
|
91
|
-
docker compose -f docker-compose.yml --env-file .env exec console \
|
|
92
|
-
catence-data disconnect strava --athlete alex --home /data
|
|
93
|
-
|
|
94
|
-
# Strava OAuth via SSH (remote Docker host accessed over SSH/Tailscale)
|
|
95
|
-
## Option 1: SSH Port Forwarding (recommended)
|
|
96
|
-
# On your LOCAL machine, forward the callback port to the remote Docker host:
|
|
97
|
-
ssh -L 8765:127.0.0.1:8765 user@docker-host
|
|
98
|
-
# Then run the standard callback flow on the REMOTE host (uses http://127.0.0.1:8765/strava/callback)
|
|
99
|
-
docker compose -f docker-compose.yml --env-file .env exec console \
|
|
100
|
-
catence-data auth strava --athlete alex --callback --home /data
|
|
101
|
-
|
|
102
|
-
## Option 2: Manual code exchange with http://localhost
|
|
103
|
-
# On the REMOTE host, get the authorization URL:
|
|
104
|
-
docker compose -f docker-compose.yml --env-file .env run --rm \
|
|
105
|
-
--entrypoint catence-data console auth strava \
|
|
106
|
-
--athlete alex --redirect-uri "http://localhost" --home /data
|
|
107
|
-
# Open the printed URL in YOUR LOCAL BROWSER, approve Strava, then copy the 'code' from the redirect URL
|
|
108
|
-
# Exchange the code on the REMOTE host:
|
|
109
|
-
docker compose -f docker-compose.yml --env-file .env run --rm \
|
|
110
|
-
--entrypoint catence-data console auth strava \
|
|
111
|
-
--athlete alex --code "THE_CODE_FROM_URL" --redirect-uri "http://localhost" --home /data
|
|
112
|
-
|
|
113
|
-
# Update the runtime and Console (re-run deploy script on the same channel)
|
|
114
|
-
curl -fsSL https://raw.githubusercontent.com/rifusaki/catence/beta/scripts/deploy-console.sh | bash -s beta
|
|
115
|
-
# or from checkout: ./scripts/deploy-console.sh beta
|
|
116
|
-
|
|
117
|
-
# Choose a non-default catalog location (bind mount instead of named volume)
|
|
118
|
-
# Stop the stack, edit docker-compose.yml to replace the volume with:
|
|
119
|
-
# volumes:
|
|
120
|
-
# - /srv/catence:/data
|
|
121
|
-
# Then restart and run the same commands (--home /data is implied by CATENCE_HOME).
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
|
|
126
|
-
## Connecting to the Docker-based MCP from Outside
|
|
127
|
-
|
|
128
|
-
### The MCP Server Inside the Container
|
|
129
|
-
|
|
130
|
-
By default, the Catence MCP server runs on **loopback only** inside the container at `http://127.0.0.1:8787/mcp`. It is **never exposed** to the host network or the internet — this is intentional for security.
|
|
131
|
-
|
|
132
|
-
The `CATENCE_MCP_BIND` variable controls **two things at once**:
|
|
133
|
-
|
|
134
|
-
1. **Docker port mapping**: which host interface exposes port 8787 to the Docker host.
|
|
135
|
-
2. **Server listen address**: which address the MCP server binds to inside the container.
|
|
136
|
-
|
|
137
|
-
| Value | Docker maps | Server binds | Effect |
|
|
138
|
-
|-------|-------------|--------------|--------|
|
|
139
|
-
| `127.0.0.1` (default) | `127.0.0.1:8787 → container:8787` | `127.0.0.1` | MCP reachable only from the Docker host's loopback — requires SSH tunnel for remote access. |
|
|
140
|
-
| `0.0.0.0` | `0.0.0.0:8787 → container:8787` | `0.0.0.0` | MCP reachable from any network interface — suitable for Tailscale or VPN exposure. |
|
|
141
|
-
|
|
142
|
-
Set it at deploy time with `--mcp-bind`, or by editing `CATENCE_MCP_BIND` in `.env`:
|
|
143
|
-
|
|
144
|
-
```sh
|
|
145
|
-
# Default (loopback only — SSH tunnel required for remote access)
|
|
146
|
-
./scripts/deploy-console.sh beta
|
|
147
|
-
|
|
148
|
-
# Tailscale / network exposure
|
|
149
|
-
./scripts/deploy-console.sh beta --mcp-bind 0.0.0.0
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
To change the binding after deployment, update `CATENCE_MCP_BIND` in `.env` and restart:
|
|
153
|
-
|
|
154
|
-
```sh
|
|
155
|
-
sed -i 's/CATENCE_MCP_BIND=.*/CATENCE_MCP_BIND=0.0.0.0/' catence-deploy/.env
|
|
156
|
-
docker compose -f catence-deploy/docker-compose.yml --env-file catence-deploy/.env up -d
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
### SSH Port Forwarding (Recommended for Remote MCP Clients)
|
|
160
|
-
|
|
161
|
-
From your **local machine**, forward the container's MCP port through the Docker host:
|
|
162
|
-
|
|
163
|
-
```sh
|
|
164
|
-
# Forward local port 8787 → Docker host port 8787 → container loopback 8787
|
|
165
|
-
ssh -L 8787:127.0.0.1:8787 user@docker-host
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
Then point your MCP client at `http://127.0.0.1:8787/mcp` on your local machine.
|
|
169
|
-
|
|
170
|
-
### Exposing MCP on Tailscale (Alternative)
|
|
171
|
-
|
|
172
|
-
To expose the MCP server directly on a Tailscale interface (or any network interface) without SSH tunneling:
|
|
173
|
-
|
|
174
|
-
```sh
|
|
175
|
-
# Deploy with MCP bound to all interfaces (0.0.0.0) — restrict via Tailscale ACLs/firewall
|
|
176
|
-
./scripts/deploy-console.sh beta --mcp-bind 0.0.0.0
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
Or set the environment variable before deploying:
|
|
180
|
-
|
|
181
|
-
```sh
|
|
182
|
-
CATENCE_MCP_BIND=0.0.0.0 ./scripts/deploy-console.sh beta
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
After deployment, the MCP server is available at `http://<tailscale-ip>:8787/mcp` from any device on your tailnet.
|
|
186
|
-
|
|
187
|
-
**Security note**: The MCP server has **no authentication** — it trusts the caller's `athleteId` parameter. When exposing on `0.0.0.0`, you **must** restrict access at the network layer (Tailscale ACLs, firewall rules, etc.). The Console UI remains on loopback (`127.0.0.1:8000`) and should still be fronted by Cloudflare Tunnel or a reverse proxy.
|
|
188
|
-
|
|
189
|
-
**Examples: Common MCP Clients**
|
|
190
|
-
|
|
191
|
-
```sh
|
|
192
|
-
# Via SSH tunnel (default loopback deployment)
|
|
193
|
-
# Opencode
|
|
194
|
-
opencode mcp add catence -- http://127.0.0.1:8787/mcp
|
|
195
|
-
|
|
196
|
-
# Codex
|
|
197
|
-
codex mcp add catence -- http://127.0.0.1:8787/mcp
|
|
198
|
-
|
|
199
|
-
# Claude Desktop
|
|
200
|
-
claude mcp add --transport http catence -- http://127.0.0.1:8787/mcp
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
```sh
|
|
204
|
-
# Via Tailscale (when deployed with --mcp-bind 0.0.0.0)
|
|
205
|
-
# Replace <tailscale-ip> with your server's Tailscale IP (from `tailscale ip`)
|
|
206
|
-
# Opencode
|
|
207
|
-
opencode mcp add catence -- http://<tailscale-ip>:8787/mcp
|
|
208
|
-
|
|
209
|
-
# Codex
|
|
210
|
-
codex mcp add catence -- http://<tailscale-ip>:8787/mcp
|
|
211
|
-
|
|
212
|
-
# Claude Desktop
|
|
213
|
-
claude mcp add --transport http catence -- http://<tailscale-ip>:8787/mcp
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
### Why Not Expose Port 8787 Directly?
|
|
217
|
-
|
|
218
|
-
- The MCP server has **no authentication** — it trusts the caller's `athleteId` parameter.
|
|
219
|
-
- Exposing it would allow any network caller to read all athlete data in the catalog.
|
|
220
|
-
- The Console proxies dashboard requests through its **authenticated** same-origin route.
|
|
221
|
-
- SSH port forwarding keeps the trust boundary at your SSH credentials.
|
|
222
|
-
|
|
223
|
-
---
|
|
224
|
-
|
|
225
|
-
## Quick Reference: `docker compose run` vs `docker compose exec`
|
|
226
|
-
|
|
227
|
-
| Command Type | Use For | Example |
|
|
228
|
-
|--------------|---------|---------|
|
|
229
|
-
| `run --rm --entrypoint catence-data console` | **One-off setup/secrets** — needs fresh stdin for `--value-stdin`, no running container required | `secret set`, `setup`, `auth strava --code` |
|
|
230
|
-
| `exec console catence-data` | **Recurring ops** — uses the running container's environment (secrets already in volume) | `sync`, `backfill`, `status`, `build-retrieval-index` |
|
|
231
|
-
|
|
232
|
-
The `sync.sh` helper uses `exec` for this reason.
|